I am facing a problem while writing image from cvMat.
This is what I have done.
IplImage* low_threshold_mask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
CvMat* labelMat = cvCreateMat(low_threshold_mask->height,low_threshold_mask->width,CV_32F);
/* I populate elements of labelMat inside a function. Its done like this: cvmSet(labelMat,r,c,label); // where label is of type long */
To check the values I dump each pixel value in a text file and also dump the image.
IplImage* labelImg;
IplImage imageHeader;
labelImg = cvGetImage(labelMat, &imageHeader);
Now when I cross-check pixel intensity with corresponding value in dumped text file, I find mis-match. I feel I have got correct values in text file but wrong ones in image.
Can anyone help in figuring out the mistake?
---------------------New addition-------------------
I am still facing the problem. I have uploaded my programs. I will explain where exactly I am facing the error.
Libraries used: Along with openCV, I am using disjoint_sets of boost library.
Basically I am doing connected component labeling.
For debugging purpose, for 20th frame, I have dumped the label info of each pixel both in a)text file as well b) an image with intensity levels same as the final label of the pixels. So i am expecting the values same in both text and image. But that's not happening. And I am unable to figure out why. The text files shows the correct values but not the image. I am checking pixel values of image in Matlab(i had taken care of indices in matlab starts with 1 not 0).
My text files
a) (frame20final.txt) gets populated in GrimsonGMM.cpp/ConCompLabeling().
b) (frame20image.txt) gets populated in main.cpp
My dumped image(frame-ccs.jpg) gets populated in main.cpp.
Both the text files get same values. So there must be some mistake in writing the image from CvMat.
Test Video: person15_walking_d1_uncomp.avi
You can try with any other video also.
Thanks in advance,
Kaushik
I understood why I was getting the error. I was dumping in .jpg image which was doing compression. This was resolved when I used .png
Your question its so easy.
You want to work with CvMat and after do operations with CvMat you want to plot your CvMat like it was an image.
You must create imageHeader, something like this.
CvMat* mat = cvCreateMatHeader(rows, cols, type);
mat->step = 4 * (mat->cols * CV_ELEM_SIZE1(mat->type) * CV_MAT_CN(mat->type) / 4 + 1);//critical
cvCreateData(mat);
In OpenCV 2.0 and below C++ interface it's not really necessary to change from Mat to IplImage.
You can plot your image using cvShowImage and if you want to convert intoIplImage
just do a easy cast IplImage *img = labelMat;
Related
I'm working currently with EmguCV and I need empty Mat. But apparently when I create it, the new Mat has sometimes some random values which I do not want.
I'm creating it like that:
Mat mask =new Mat(mainImg.Size,Emgu.CV.CvEnum.DepthType.Cv8U,1);
And when I display the 'mask' it looks like that:
It should be completely black but as you can see there is some trash which cause me trouble in reading the mat.
Does anyone know why it is like that? Maybe is there a clever way to clear the Mat?
Thanks in advance!
To create an empty Mat just use the code below.
Mat img = new Mat();
If you want to make it a specific size, use the following code. In your question above, you were choosing a depth type of 8U, which might be contributing to your low quality of an image. Here I choose a depth type of 32F, which should increase the quality of the new mask image. I also added 3 channels instead of 1, so you can have full access to the Bgr color space.
Mat mask = new Mat(500, 500, DepthType.Cv32F, 3);
Mat objects are great because you don't need to specify the size or depth of the image beforhand. Simmilarly, if you want to use an Image instead, you can use the code below.
Image<Bgr, byte> img = new Image<Bgr, byte>(500, 500);
You will need to add some dependencies, but this is the easiest and my preferred way of doing it.
I have a grayscale photo that I am trying to colour programmatically so that it looks 'real', with user input 'painting' the colour (eg red). It feels like it should be simple, but I've been stuck trying a few ways that don't look right, so thought I'd ask the community in case I've missed something obvious. I've tried the following
Converting to HSV, and combining the "Hue" and Saturation from the colour selected by the user, with the "Value" from the image.
Building a colour transformation matrix to multiply the BGR values (ie R = 0.8R + 1.1G + 1.0B). This works well for 'tinting', and adds a nice pastel effect, but doesn't really keep the depth or boldness of colour I want.
(favourite so far - see answers) multiply RGB from colour channel by RGB of image.
To add to the comment by user Alexander Reynolds, the question that you're asking is a known open research problem in the field of computer graphics, because the problem is under-constrained without using statistical priors of some sort. The state of the art in the CG community is found here, presented at SIGGRAPH 2016.
http://hi.cs.waseda.ac.jp/~iizuka/projects/colorization/en/
Also see:
http://richzhang.github.io/colorization/
I've had another think and play with photoshop, and implemented a multiply blend mode on BGR space to get an ok result.
Implemented in java
Mat multiplyBlend(Mat values, Mat colours) {//values 1 channel, colours 3
//simulates BGR Multiply blend mode
ArrayList<Mat> splitColours = new ArrayList<Mat>();
Core.split(colours, splitColours);
Core.multiply(values, splitColours.get(0), splitColours.get(0), 1/255.0f);
Core.multiply(values, splitColours.get(1), splitColours.get(1), 1/255.0f);
Core.multiply(values, splitColours.get(2), splitColours.get(2), 1/255.0f);
Mat ret = new Mat();
Core.merge(splitColours, ret);
return ret;
}
I'm working with the OpenCV library in XCode and doing a colour tracking application that draws lines from one point to the next. I was wondering if it's possible to put the output not as the video but as a white background.
So instead of
cvShowImage("video",frame);
Is there a function that would show (backgroundcolour, frame)?
edit:
I've added this code but since canvas is not an image it won't let me write on to it instead of frame.
cv::Mat canvas(320, 240, CV_8UC3, Scalar(255,255,255));
IplImage* imgYellowThresh1 = GetThresholdedImage1(canvas);
cvAdd(&canvas,imgScribble,&canvas);
cvShowImage("video",&canvas);
So the erro is on the GetThresholdedImage1 saying "no matching function for call to GetThresholdedImage1"
No, not it such a simple way you proposed. The solution would be to create separate Mat and draw the lines on it.
cv::Mat canvas(rows, cols, CV_8U3C, Scalar(255,255,255)); //set size, type and fill color
You would prepare this mat an the begining of code, and then use the draw functions on it. So instead of drawing the lines on frame you would draw on canvas.
EDIT:
There was slight misconception. The problem is you are using old C API. To learn about the latest C++ API, follow this tutorials:
http://docs.opencv.org/doc/tutorials/tutorials.html
I am cropping an opencv Mat:
cv::Size size = img.size();
cv::Rect roi(size.width*/4., size.height/4.,size.width/2., size.height/.2);
img= img(roi);
I then use img.data pointer to create a vtkImageData (via vtkImageImport):
vtkSmartPointer<vtkImageImport> importer = vtkSmartPointer<vtkImageImport>::New();
importer->SetImportVoidPointer(img.data);
...
importer->Update();
vtkImageData* vtkImg = importer->GetOutput();
I don't get the expected result when I display the vtkImg. I've digged into opencv's code and the problem is that when creating the cropped data, opencv does not allocate a new pointer that is 4 times smaller but instead keeps the same already allocated block, advances the pointer upstream and flags the new img variable as not continuous. Therefore my vtk image still imports data from the original uncropped Mat. I know I could import the full image to vtkImageData and then do the cropping with a vtk filter but I would prefer not to.
Is there a way with opencv to obtain a cropped image that is "physically" cropped (with a newly allocated data pointer)?
Thank you
I believe you are looking for cv::Mat::clone(). It makes a deep copy of the underlying image data and returns a cv::Mat object which contains said data.
You would then change the line
img= img(roi);
to
img = img(roi).clone();
After which img contains only the cropped data.
I'm new to OpenCV and just started sifting through the APIs. I intend to fetch the color, intensity and texture values of each pixel constituting the image. I was fiddling with the structure - IplImage to start with but couldn't make much progress.
Please let me know of any means to do this.
cheers
Have you tried OpenCV 2.0? They have a new C++ interface which makes things much easier. You can use their new Mat class to load images, access pixels efficiently, etc. It's much cleaner than IplImage fun. I use \doc\opencv.pdf as my reference to anything I need. It's got tutorials, and examples with the new C++ interface, etc. - enough and more to get you started.
If you have anymore specific OpenCV questions, please feel free to ask.
Here's some demo code to get you started: (I've used the cv namespace):
// Load the image (looks like MATLAB :) ? )
Mat M = imread("h:\\lena.bmp");
// Display
namedWindow("Lena",CV_WINDOW_AUTOSIZE);
imshow("Lena",M);
waitKey();
// Crop out rectangle from (100,100) of size (200,200) of the red channel
const int offset[2] = {100,100};
const int dims[2] = {200,200};
Mat Red(dims[0],dims[1],CV_8UC1);
// Read it from M into Red
uchar* lena = M.data;
for(int i=0;i<dims[0];++i)
for(int j=0;j<dims[0];++j)
{
// P = i*rows*channels + j*channels + c
Red.at<uchar>(i,j) = *(lena + (i+offset[0])*M.rows*M.channels() + (j+offset[1])*M.channels()+0);
}
//Display
namedWindow("RedRect",CV_WINDOW_AUTOSIZE);
imshow("RedRect",Red);
waitKey();