OpenCV and reading image with floating point data - opencv

I use OpenCV to read the image. Then I use Matlab to load the same image.
Then I display the images. For OpenCV loaded image, the image is has no picture inside and just gray plane. For Matlab loaded image, it has the image what I want.
The image pixel values are very small floating point data like 0.0021. The code I used to load the image is shown as follow.
`Mat image(IMAGE_ROW, IMAGE_COL, CV_64FC3);
Mat gray(IMAGE_ROW, IMAGE_COL, CV_64FC1);
image = imread(filespath, CV_LOAD_IMAGE_COLOR );// Read the file
cv::imshow("Image", image);
cvtColor( image, gray, CV_BGR2GRAY, 1);
cv::imshow("gray", gray);`
Why I can't have the same image as loaded by Matlab?

well you can't do it with imwrite()/imread() as stated before.
but you can save/load floating point Mats using the FileStorage, like this:
Mat fm = Mat::ones(3,3,CV_32FC3); // dummy data
FileStorage fs("my.yml", FileStorage::WRITE );
fs << "mat1" << fm; //choose any key here, just be consistant with the one below
and read back in:
Mat fm;
FileStorage fs("my.yml", FileStorage::READ );
fs["mat1"] >> fm;

You don't need to explicitly initialize a cv::Mat image before calling cv::imread, it will initialize the image properly according to the size and format of the image read. So it doesn't matter that you've initialized your image with (IMAGE_ROW, IMAGE_COL, CV_64FC3).
OpenCV has no capabilities for writing/reading floating point images. From cv::imwrite manual:
Only 8-bit (or 16-bit in the case of PNG, JPEG 2000 and TIFF)
single-channel or 3-channel (with ‘BGR’ channel order) images can be
saved using this function.

You can load float images with opencv Mat img= imread(filename, CV_LOAD_IMAGE_ANYDEPTH);

Tried #berak solution, but got a "Missing , between elements" exception. As stated in this bug report, you must release the FileStorage object after writing operation, otherwise it will not properly finalise the file writing and thus raising that exception. Then, the corrected version of the codelet should be:
Mat fm = Mat::ones(3,3,CV_32FC3); // dummy data
FileStorage fs("my.yml", FileStorage::WRITE );
fs << "mat1" << fm; //choose any key here, just be consistant with the one below
fs.release(); //Release the file and finish the writing.

Related

OpenCV - How to downsample and upsample a cuFloatComplex image present in device memory

I have to downsample a image and do some filtering operations on it and then upsample the image back to the original size, these images are present in the CUDA device memory. I planned to do it by moving the images to opencv gpumat and then using the resize function but it doesn't to be working, so I wanted to know if someone could help me with resizing the images which is of type 'cuFloatComplex'.
Pasting the snippet of my attempt below:
/*
Inputs
dG = image of datatype cuFloatComplex
m = rows.
n =columns.
d_input= expected output.
*/
cuda::GpuMat d_input(m,n, CV_64FC2, dG);
cuda::GpuMat components[2];
cuda::split(d_input,components);
cuda::GpuMat real = components[0], imag = components[1];

How to determine the number of input image channels?

For reading an image file, I have to use either of
Mat img = imread(file,CV_LOAD_IMAGE_COLOR);
or
Mat img = imread(file,CV_LOAD_IMAGE_GRAYSCALE);
This means I have to know in advance whether the file contains a color or mono image. Isn't there a way to know the number of channels in advance so that I can apply the image read according to the number of channels?
According to the imread documentation, you should use <0 Return the loaded image as is (with alpha channel).
In highui_c.h there is this definition:
CV_LOAD_IMAGE_UNCHANGED =-1,
Oddly CV_LOAD_IMAGE_UNCHANGED is not mentioned in the imread documentation, but is used in one of the OpenCV tutorials.
This will do what you want:
Mat img = imread(file, CV_LOAD_IMAGE_UNCHANGED);

opencv: Mat2.copyTo(Mat1(Rect)) is giving grayscale only for copied area

I am trying to overlay image over video frame in android(native part, .cpp).I get my video frames in yuv420sp format, i pass this char * (buffer) to opencv and there i create a MAT with it
Mat frame(Size(width,height),8UC1,buff);
The same way,i have loaded my image into a char *(buffer),converted to yuv420SP and in the similar way i create image Mat:
Mat imageMat((Size(width,height),8UC1,imgBuff));
After this i copy the overlay image on the video frame i received as:
Rect roi(X,Y,U,V);
imageMat.copyTo(frame(roi));
and i need this merged frame in same yuv420sp format so after here i return :
return frame.data;//i am returning char * from this api to my .cpp file
The image is overlayed properly but problem is that only the overlayed part is in gray scale,rest full frame is properly coloured!
I just fail to understand whats wrong!
Note:
I tried few things already like:
1. I converted both the things(frame and image) via:
cvtColor(frame,frame,CV_COLOR_yuv420sp2BGR);
but i want response back in yuv420sp format only,and there is no such flag to turn it back to yuv420sp.
2.Tried with 8UC3,didnt really made any difference. Anyway,my video frame is returned coloured,then why the image is in grayscale?
Really stuck here! Any suggestion will be really helpful!

openCV: adding transparency to IplImage

I have a 3-channel IplImage. I would like to create a 4-channel image and set the alpha channel for it to a value less than 1.0 to make it semi-transparent.
First I set the alpha channel (the 4-th channel) to 0.5:
cvSet(Image_c4, cvScalar(0,0,0,0.5);
Here is the command that I used to copy the 3-channel image into a 4-channel image.
cvCvtColor(Image_c3, Image_c4, CV_RGB2RGBA);
The problem: Image_c3 is in color. Image_c4 becomes a gray scale copy of Image_c3 (and with no transparency).
Update:
It turned out that the code above is actually correct and works and is actually more concise than the suggested solutions in the answers below. I had an unrelated bug somewhere else.
Maybe there is another way but I add transparency like this:
// BGR split
cvSplit(im1_bgr, im1_b, im1_g, im1_r, NULL);
// Alpha channel creation (transparency)
IplImage *im1_a = cvCreateImage(cvGetSize(im1_bgr), 8, 1);
// Set the alpha value
cvSet(im1_a, cvScalar(128), NULL);
// Merge the 4 channel to an BGRA image
IplImage *im1_bgra = cvCreateImage(cvGetSize(im1_bgr), 8, 4);
cvMerge(im1_b, im1_g, im1_r, im1_a, im1_bgra);
//This code help to make a transparency image But it take src image as one //single color background see![Removing background and added black background color ][1]
Mat dst;//(src.rows,src.cols,CV_8UC4);
Mat tmp,alpha;
cvtColor(src,tmp,CV_BGR2GRAY);
threshold(tmp,alpha,0,255,THRESH_BINARY);
Mat rgb[3];
split(src,rgb);
Mat rgba[4]={rgb[0],rgb[1],rgb[2],alpha};
merge(rgba,4,dst);
imwrite("dst.png",dst);
//dst is transparency image see here![output image as transparency image][2]
[1]: http://i.stack.imgur.com/9THqs.png
[2]: http://i.stack.imgur.com/mpmgy.png

Is Picture-in-Picture possible using OpenCV?

I would like to add a smaller image on top of a larger image (eventually for PiP on a video feed). I can do it by iterating through the relevant data property in the large image and add the pixels from the small image. But is there a simpler and neater way? I'm using EMGU.
My idea was to define an ROI in the large image of the same size as the small image. Set the Large image equal to the small image and then simply remove the ROI. Ie in pseudo code:
Large.ROI = rectangle defined by small image;
Large = Small;
Large.ROI = Rectangle.Empty;
However this doesn't work and the large image doesn't change. Any suggestions would be much appreciated.
Large image:
Small image:
Desired result:
If you using C++ API then the following code snippet should work:
cv::Mat big;
cv::Mat small;
// Define roi area (it has small image dimensions).
cv::Rect roi = cv::Rect(50,50, small.cols, small.rows);
// Take a sub-view of the large image
cv::Mat subView = big(roi);
// Copy contents of the small image to large
small.copyTo(subView);
Take care to not go out of dimensions of big image.
I don't know if this will help, i haven't used emgu. However this was how i was able to do image in image with opencv.
drawIntoArea(Mat &src, Mat &dst, int x, int y, int width, int height)
{
Mat scaledSrc;
// Destination image for the converted src image.
Mat convertedSrc(src.rows,src.cols,CV_8UC3, Scalar(0,0,255));
// Convert the src image into the correct destination image type
// Could also use MixChannels here.
// Expand to support range of image source types.
if (src.type() != dst.type())
{
cvtColor(src, convertedSrc, CV_GRAY2RGB);
}else{
src.copyTo(convertedSrc);
}
// Resize the converted source image to the desired target width.
resize(convertedSrc, scaledSrc,Size(width,height),1,1,INTER_AREA);
// create a region of interest in the destination image to copy the newly sized and converted source image into.
Mat ROI = dst(Rect(x, y, scaledSrc.cols, scaledSrc.rows));
scaledSrc.copyTo(ROI);
}
I have a lot of experience with EMGU. As far as I am aware the method your employing is the only direct way of display the sub-image data within your large image. You would likely have to refresh your larger image which would have the inherent effect of wiping your transferred data and copy the smaller image back over.
While a solution is possible I think the method is flawed. The required processing time will effect the display rate of any image in the larger viewing frame.
An improved method would be to add another control. Effectively you have your video feed window showing your larger image in the background and a smaller control on-top of this displaying your smaller image. Effectively you could have as many of these smaller controls as you like. You will in effect be displaying two images or video feeds in two different controls (e.g. image boxes). As you have the code to do so all you will have to do is ensure the order of which your controls are displayed.
I have assumed you are not programming the output to a Console Window. If you need any more help please feel free to ask.
As for the comments EMGU is written in C# and while appreciate your view on not calling EMGU OpenCV why should it not be tagged as an OpenCV orientated question. After all EMGU is simply OpenCV library with a c# wrapper. I have found many resources on OpenCV useful for EMGU and vice versa.
Cheers
Chris
Based on #BloodAxe's answer, using EMGU 3.4 the following works:
// Define roi area (it has small image dimensions).
var ROI = new System.Drawing.Rectangle(100, 500, 200, 200)
// Take a sub-view of the large image
Mat subView = new Mat(bigImage, ROI);
// Copy contents of the small image to large
small.CopyTo(subView);

Resources