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);
Related
I've got the following image:
And I'm doing the following
First I read an image img = skimage.io.imread('original.jpg') that has the following histogram:
Then, after applying he_img = skimage.exposure.equalize_hist(a), I get the following histogram:
but when I save, then load and see the histogram of that image I get the following:
skimage.io.imsave(fname = 'he.jpg', arr= he_img)
saved = skimage.io.imread('he.jpg')
What else do I need to add to my process in order to being able to save the equalized image?
The problem with this was that I was using JPG. JPG uses lossy compression to save images, adding noise to the image affecting to the equalization and increassing the images entropy.
To solve this I tried PNG that is a lossless compression format for storing images. The code for this is:
img = skimage.io.imread('original.jpg')
hist_equalized_img = skimage.exposure.equalize_hist(img)
skimage.io.imsave(fname = 'he.png', arr= hist_equalized_img)
import cv2;
input_path = 'input.JPG';
output_path = 'output.jpg';
input_image = cv2.imread(input_path,cv2.IMREAD_UNCHANGED)
cv2.imwrite(output_path,input_image)
Check the input output image comparision here
This is the original image - https://imgur.com/a/iRAS9NY
There is a color change between input and output image. Please help me modify the code so the input and output images are exactly matching. Thanks!
The image is in AdobeRGB format. That is the issue. We are using GIMP to convert into SRGB and then using it in our sfotware. It is working fine now.
I am trying to read a medical imaging data which is in .tif format using Octave . It so happens that only software from https://fiji.sc/ has the ability to read the medical images I have. A sample of the image that I am referring is this one. This image is readable in.tif format only in fiji. The image can also be converted to jpg image. Only after data points is visible to other image editing software. Now the issue is , I want to load it into octave and read it - at the moment it is not possible. The imshow() function in octave is not allowing me to visualize the given .tif file.
So, if anybody has experience in reading such file formats please let me know. Thanks.
Your linked image is a 16bit grayscale image, see $ gm identify -verbose hello.tif. So lets load it into GNU Octave:
img = imread ("hello.tif");
hist (img(:), 200); # show histogram
Ah!, the main information of your image is in the range 0-600 (probably the image aquisition system used had 11 or 12bit resolution), so lets scale and print this part as color encoded (viridis) image:
imagesc (img, [0 600])
colorbar
Is this what you want? Of course we can also use a gray colormap, try: colormap gray
If this still doesn't fit your need you should really explain what you expect to see....
imread() relies on image magic to do the conversion, some versions of which can only read TIFF in 8-bit mode (giving a warning message), but when and how this happens I do not know.
It works for me using a .raw ṕicture converted to .tif in Fiji. I am specifically interested in several spectral analysis from my pictures which are taken illuminating with 660 and 850nm.
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.
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);