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);
Related
I am going to extract a single channel from a multichannel matrix. Given Mat img is a three-channel matrix, I want to extract the first channel. Is there any handy function to do this, something like: out = img(:,:,1) in MATLAB. I know cv::split is capable of this by split out individual channels. But I want another method, since I will not use many other channels extracted.
There is a function for this in OpenCV, sort-of to my surprise: cv::extractChannel(). From the docs:
C++ signature:
void cv::extractChannel ( InputArray src,
OutputArray dst,
int coi
)
Python signature:
dst = cv.extractChannel( src, coi[, dst] )
Description:
Extracts a single channel from src (coi is 0-based index)
Parameters
* src input array
* dst output array
* coi index of channel to extract
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)
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?
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.
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);