访问3通道矩阵的元素

时间:2012-03-14 15:07:47

标签: c++ opencv

下面的代码是为了访问转换为矩阵的3个RGB图像的元素并将它们放在一个更大的矩阵中。但是,我知道CV_MAT_ELEM(mat,type,row,col)仅用于访问单通道矩阵的元素,而我的图像都是3通道。那么,我是否会修复此代码,以访问3通道矩阵的元素而不是单个通道矩阵?

#include "cv.h" 
#include "highgui.h" 
#include "iostream" 

using namespace std; 

void cvDoubleMatPrint (const CvMat* mat)
{
int i, j;
for (i = 0; i < mat->rows; i++)
{
for (j = 0 ; j < mat->cols; j++)
{
    printf ( "%f ", cvGet2D (mat, i , j));
}
printf ( "\n" );
}
}


int main( int argc, char* argv ) 
{ 
CvMat *img0, *img1, *img2,  *img0_mat, *img1_mat, *img2_mat, *col0, *col1, *col2, *superMat = NULL;

img0 = cvLoadImageM("C:\\small\\walk mii.jpg", CV_LOAD_IMAGE_UNCHANGED);    
img1 = cvLoadImageM("C:\\small\\wave mii.jpg", CV_LOAD_IMAGE_UNCHANGED);  
img2 = cvLoadImageM("C:\\small\\fantasy.jpg", CV_LOAD_IMAGE_UNCHANGED); 

CvMat img0_header ,img1_header, img2_header;

col0 = cvReshape(img0, &img0_header, 0, 4800);
col1 = cvReshape(img1, &img1_header, 0, 4800);
col2 = cvReshape(img2, &img2_header, 0, 4800);

superMat = cvCreateMat(4800, 3, CV_8UC1);
cvSetZero(superMat);

for(int i=0; i<col0->height; i++)
{
CV_MAT_ELEM( *superMat, double, i, 0 ) = CV_MAT_ELEM( *col0, double, i, 0 );
}

for(int j=0; j<col1->height; j++)
{
CV_MAT_ELEM( *superMat, double, j, 1 ) = CV_MAT_ELEM( *col1, double, j, 0 );
}

 for(int k=0; k<col2->height; k++)
{
CV_MAT_ELEM( *superMat, double, k, 2 ) = CV_MAT_ELEM( *col2, double, k, 0 );
}


cvDoubleMatPrint(superMat);

cvWaitKey(0);
return 0;

2 个答案:

答案 0 :(得分:2)

我对C API并不熟悉,但这里是你如何使用C ++ API完成你的工作。

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <iostream>
#include <vector>

using namespace cv;
using namespace std;

int main(int /*argc*/, char** /*argv*/)
{
    cv::RNG rng = cv::theRNG();

    // create 3 random 10x10 matrices to simulate your situation.
    vector<Mat> matrices;
    for(int i = 0; i < 3; i++)
    {
        Mat temp(Size(10, 10), CV_64FC3);
        rng.fill(temp, RNG::UNIFORM, 0.0, 1.0);
        matrices.push_back(temp);
    }

    // reshape the matrices to have 1 row and 1 channel (i.e., 10x10x3 -> 300x1).
    vector<Mat> singleRows;
    vector<Mat>::iterator i;
    for(i = matrices.begin(); i != matrices.end(); i++)
    {
        singleRows.push_back(i->reshape(1, 1));
    }

    // finally, concatenate the matrices to make a 300x3 matrix.
    Mat concatenated;
    for(i = singleRows.begin(); i != singleRows.end(); i++)
    {
        concatenated.push_back(i->clone());
    }

    cout << concatenated.size().width << "x" << concatenated.size().height << endl;

    return 0;
}

如果您需要在C ++ API中访问RGB值,请参阅我的other post,了解如何使用cv::Vec3b类。一般来说,我建议在C API上使用C ++ API,因为它具有更多功能并且更易于使用。另外,请查看OpenCV函数splitmerge。这些功能对多通道管理很有用。希望有所帮助!

答案 1 :(得分:0)

我认为您可能正在寻找的是CvtPixToPlane,它可以将多通道阵列分成几个单通道阵列,或者从阵列中提取单个通道。

CvtPlaneToPix还可用于将多个单通道阵列组合成多通道阵列,或将单个通道插入阵列。

Some documentation on these two functions.

以下是将多通道阵列拆分为三个单通道阵列的示例,摘自Shervin Emami's Detect Blobs tutorial -

// Get the separate HSV color components of the color input image.
    IplImage* planeH = cvCreateImage( cvGetSize(imageBGR), 8, 1);   // Hue component.
    IplImage* planeS = cvCreateImage( cvGetSize(imageBGR), 8, 1);   // Saturation component.
    IplImage* planeV = cvCreateImage( cvGetSize(imageBGR), 8, 1);   // Brightness component.
    cvCvtPixToPlane(imageHSV, planeH, planeS, planeV, 0);   // Extract the 3 color components.

如您所见,他通过获取原始图像(imageBGR)的大小并将其设置为单通道图像来创建具有正确属性的图像。然后用cvCvtPixToPlane将他的多通道图像(imageHSV)分成三个单通道图像(planeH,planeS,planeV)

希望这有帮助:)