سؤال

أحاول تعلم كيفية استخدام واجهة c++ الجديدة لـ openCV.

كيف يمكنني الوصول إلى عناصر مصفوفة متعددة القنوات.على سبيل المثال:

Mat myMat(size(3, 3), CV_32FC2);

for (int i = 0; i < 3; ++i)
{
    for (int j = 0; j < 3; ++j)
    {
        //myMat_at_(i,j) = (i,j);
    }
}

ما هي أسهل طريقة للقيام بذلك؟شيء مثل cvSet2D للواجهة القديمة
ما هي الطريقة الأكثر فعالية؟يشبه استخدام المؤشرات المباشرة في الواجهة القديمة.

شكرًا لك

هل كانت مفيدة؟

المحلول

typedef struct elem_ {
        float f1;
        float f2;
} elem;
elem data[9] = { 0.0f };
CvMat mat = cvMat(3, 3, CV_32FC2, data );

float f1 = CV_MAT_ELEM(mat, elem, row, col).f1;
float f2 = CV_MAT_ELEM(mat, elem, row, col).f2;

CV_MAT_ELEM(mat, elem, row, col).f1 = 1212.0f;
CV_MAT_ELEM(mat, elem, row, col).f2 = 326.0f;

تحديث :ل OpenCV2.0

1.اختر نوعًا واحدًا لتمثيل العنصر

حصيرة (أو CvMat) لها 3 أبعاد:الصف، العمود، القناة.
يمكننا الوصول إلى عنصر واحد (أو بكسل) في المصفوفة عن طريق تحديد الصف والعمود.

CV_32FC2 يعني أن العنصر هو قيمة النقطة العائمة 32 بت مع قناتين.
لذا فإن العنصر الموجود في الكود أعلاه هو تمثيل مقبول لـ CV_32FC2.

يمكنك استخدام تمثيلات أخرى تريدها.على سبيل المثال :

typedef struct elem_ { float val[2];    } elem;
typedef struct elem_ { float x;float y; } elem;

يضيف OpenCV2.0 بعض الأنواع الجديدة لتمثيل العنصر في المصفوفة، مثل:

template<typename _Tp, int cn> class CV_EXPORTS Vec // cxcore.hpp (208)

حتى نتمكن من استخدام Vec<float,2> لتمثيل CV_32FC2, ، او استعمل :

typedef Vec<float, 2> Vec2f; // cxcore.hpp (254)

راجع الكود المصدري للحصول على المزيد من النوع الذي يمكن أن يمثل العنصر الخاص بك.
هنا نستخدم Vec2f

2.الوصول إلى العنصر

الطريقة الأسهل والأكثر فعالية للوصول إلى العنصر الموجود في فئة Mat هي Mat::at.
لديها 4 الأحمال الزائدة:

template<typename _Tp> _Tp& at(int y, int x);                // cxcore.hpp (868)
template<typename _Tp> const _Tp& at(int y, int x) const;    // cxcore.hpp (870)
template<typename _Tp> _Tp& at(Point pt);                    // cxcore.hpp (869)
template<typename _Tp> const _Tp& at(Point pt) const;        // cxcore.hpp (871)
// defineded in cxmat.hpp (454-468)

// we can access the element like this :
Mat m( Size(3,3) , CV_32FC2 );
Vec2f& elem = m.at<Vec2f>( row , col ); // or m.at<Vec2f>( Point(col,row) );
elem[0] = 1212.0f;
elem[1] = 326.0f;
float c1 = m.at<Vec2f>( row , col )[0]; // or m.at<Vec2f>( Point(col,row) );
float c2 = m.at<Vec2f>( row , col )[1];
m.at<Vec2f>( row, col )[0] = 1986.0f;
m.at<Vec2f>( row, col )[1] = 326.0f;

3.التفاعل مع الواجهة القديمة

يوفر Mat وظيفتين للتحويل:

// converts header to CvMat; no data is copied     // cxcore.hpp (829)
operator CvMat() const;                            // defined in cxmat.hpp
// converts header to IplImage; no data is copied
operator IplImage() const;

// we can interact a Mat object with old interface :
Mat new_matrix( ... );
CvMat old_matrix = new_matrix;  // be careful about its lifetime
CV_MAT_ELEM(old_mat, elem, row, col).f1 = 1212.0f;

نصائح أخرى

وفيك يجب استخدام Vec3b بدلا من Vec3i:

for (int i=0; i<image.rows; i++)
{
    for (int j=0; j<image.cols; j++)
    {
        if (someArray[i][j] == 0)
        {
            image.at<Vec3b>(i,j)[0] = 0;
            image.at<Vec3b>(i,j)[1] = 0;
            image.at<Vec3b>(i,j)[2] = 0;
        }
    }
}

ويمكنك الوصول إلى مجموعة البيانات الأساسية مباشرة:

Mat myMat(size(3, 3), CV_32FC2);

myMat.ptr<float>(y)[2*x]; // first channel
myMat.ptr<float>(y)[2*x+1]; // second channel

وذلك يعتمد على نوع بيانات بساط الذي تستخدمه، إذا كان رقمية، مثل CV_32FC1 يمكنك استخدام:

myMat.at<float>(i, j)

وإذا كان نوع uchar ثم يمكنك الوصول إلى عنصر باستخدام

(symb.at<Vec3b>(i, j)).val[k]

وحيث ك هي القناة، أن يكون ل0 الصور الرمادية و 3 الملونة

أفضل طريقة للوصول إلى مصفوفة متعددة القنوات باستخدام واجهة برمجة تطبيقات c++ هي إنشاء مؤشر إلى صف معين باستخدام طريقة ptr.

على سبيل المثال؛

type elem = matrix.ptr<type>(i)[N~c~*j+c]

أين

  • يكتب:نوع البيانات (float، int، char إلخ ..)
  • أنا:الصف الذي يهمك
  • نورث كارولاينا:عدد القنوات
  • ي:العمود الذي تهتم به
  • ج:العمود الذي تهتم به (0-3)

للحصول على معلومات حول تحويلات c->c++ الأخرى، راجع هذا الرابط: مصدر

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top