Convert 1 channel image to 3 channel - opencv

I am trying to convert a 1 channel image (16 bit) to a 3 channel image in OpenCV 2.3.1. I am having trouble using the merge function and get the following error:
Mat temp, tmp2;
Mat hud;
tmp2 = cv_ptr->image;
tmp2.convertTo(temp, CV_16UC1);
temp = temp.t();
cv::flip(temp, temp, 1);
resize(temp, temp, Size(320, 240));
merge(temp, 3, hud);
error: no matching function for call to ‘merge(cv::Mat&, int, cv::Mat&)’
Can anyone help me with this? Thanks in advance!

If temp is the 1 channel matrix that you want to convert to 3 channels, then the following will work:
cv::Mat out;
cv::Mat in[] = {temp, temp, temp};
cv::merge(in, 3, out);
check the Documenation for more info.

Here is a solution that does not require replicating the single channel image before creating a 3-channel image from it. The memory footprint of this solution is 3 times less than the solution that uses merge (by volting above).
See openCV documentation for cv::mixChannels if you want to understand why this works
// copy channel 0 from the first image to all channels of the second image
int from_to[] = { 0,0, 0,1, 0,2};
Mat threeChannelImage(singleChannelImage.size(), CV_8UC3);
mixChannels(&singleChannelImage, 1, & threeChannelImage, 1, from_to, 3);

It looks like you aren't quite using merge correctly. You need to specify all of the cannels that are to be 'merged'. I think you want a three channel frame, with all the channels identical, in Python I would write this:
cv.Merge(temp, temp, temp, None, hud)
From the opencv documentation:
cvMerge: Composes a multi-channel array from several single-channel arrays or inserts a single channel into the array.

Related

How could I create an opencv matrix with separate rgb channel data

Suppose I have three char arrays r[1024], g[1024], b[1024] which contains the rgb data of one image. How could I create a cv::Mat with these channel data ?
Something like this:
// Create three single channel Mats
cv::Mat R(rows,cols,CV_8UC1,&r[0]);
cv::Mat G(rows,cols,CV_8UC1,&g[0]);
cv::Mat B(rows,cols,CV_8UC1,&b[0]);
Then merge into single image:
// Now merge the 3 individual channels into 3-band bad boy
auto channels = std::vector<cv::Mat>{B, G, R};
cv::Mat ThreeBandBoy;
cv::merge(channels, ThreeBandBoy);

Mat Single channel Element Access

Using three channel Mat we can access element like
Mat draw(480, 480, CV_8UC3);
Vec3b pix(255,0,0);
draw.at<Vec3b>(i,j)=pix;
But in the case of single channel Mat like
Mat draw(480, 480, CV_8UC1);
how can I access Mat element. I already tried some thing like
draw.at<float>(i,j)=255;
but wrong result. Am I wrong in the above case ?, any help will appreciated.....
Thanks in advance.............
That draw.at<float>(i,j)=255; should be
draw.at<uchar>(i,j)=255;
You have declared the Mat as type 8 bit unsigned char, 1 channel:
Mat draw(480, 480, CV_8UC1);
so trying to write a 4 byte quantity to a single byte container is going to cause not only incorrect result, but probably corru[tion of other data structures.
The following is going to write (255.0) to 4 bytes not 1:
draw.at<float>(i,j)=255;
if you want to use CV_8UC1 then accessing an element in the Mat would be like this
(draw.at<Vec3b>(i,j)).val[k]=255;
where K is the channel number (0 to 3)

HOGDescriptor::computeGradient using OpenCV

I try to compute gradient map using HOGDescriptor.
My code:
HOGDescriptor hog;
hog.compute(faceROI,ders,Size(32,32),Size(0,0),locs);
Mat grad;
Mat sec;
hog.computeGradient(frame_gray, grad, angleofs);
imshow("1", frame_gray);
imshow("2", grad); //here program fails: Unhandled exception at memory location
imshow("3", angleofs); //grad.data = "". Why??
I cant find goot examples of using HOGDescriptor::computeGradient.
Help please!
To visualize OpenCv's HOGDescriptor::Calculate(..), use this, it's amazing.
imshow("2", grad); fails because imshow expects that grad image is a 1, 3 or 4 channel image whereas it is a 2 channel image.
First channel contains the gradient in x direction whereas the second channel contains the gradient in y. You should split the channels in two images to visualize them:
Mat grad_channel[2];
split(grad, grad_channel);
imshow("grad_x", grad_channel[0]);
imshow("grad_y", grad_channel[1]);
Best

conversion of cvMat to IplImage

I have two programs, one which accepts an Image as a matrix and does the processing like tracking objects using contour detection.The second program takes image as an array(IplImage) and counting no. of objects.But I want to merge these programs to count as well as track these objects.How can I merge them ?
In the following code left is CvMat, left1 is IplImage. In this way you can manually convert cvmat to IplImage.
for (int y=0;y<height1;y++)
{
uchar* leftdata=(uchar*)(left->data.ptr+y*left->step);
uchar* left1data=(uchar* )(left->imageData+y*left1step);
for (int x=0;x<width1;x++)
left1data[x]=leftdata[x];
}
or here is another link How to convert a Mat variable type in an IplImage variable type in OpenCV 2.0?

Can not convert with cvMerge,DFT

I am trying to make the dft of one single channeled image, and as cvDft is expecting complex values, I was adviced to merge the original image with another image with all 0's so this last one will be considered as imaginary part.
My problem comes when using cvmerge function,
Mat tmp = imread(filename,0);
if( tmp.empty() )
{cout << "Usage: dft <image_name>" << endl;
return -1;}
Mat Result(tmp.rows,tmp.cols,CV_64F,2);
Mat tmp1(tmp.rows,tmp.cols,CV_64F, 0);
Mat image(tmp.rows,tmp.cols,CV_64F,2);
cvMerge(tmp,tmp1,image);`
It gives me the next error: can not convert cvMAt to cvArr
Anyone could help me? thanks!
1) it seems like you're mixing up 2 different styles of opencv code
cv::Mat (- Mat) is a c++ class from the new version of opencv, cvMerge is a c function from the old version of opencv.
instead of using cvmerge use merge
2) you're trying to merge a matrix (tmp) of type CV_8U (probably) with a CV_64F
use convertTo to get tmp as CV_64F
3) why is your Result & image mats (the destination mat) are initializes to cv::Scalar(2)? i think you're misusing the constractor parameters. see here for more info.
4) you're image mat is a single channel mat and you wanted it as a 2 channel mat (as mentioned in the question), change the declaration to
Mat image(tmp.rows,tmp.cols,CV_64FC2);

Resources