I am trying to save a JPEG image onto the disk using imwrite, seems that I am missing something. I am always getting a black image of around 4KBs. What am I doing wrong here?
Image I see seems fine but once onto the disk, its completely black.
std::vector<int> qualityType(1);
qualityType.push_back(CV_IMWRITE_JPEG_QUALITY);
cv::imwrite("Final.jpg",image,qualityType);
The following code works for me on 8bit (1 and 3 channel) images:
std::vector<int> qualityType;
qualityType.push_back(CV_IMWRITE_JPEG_QUALITY);
qualityType.push_back(90);
cv::imwrite("Final.jpg",image,qualityType);
In your code qualityType is initialized incorrectly. Your vector contains 2 values
{<some unknown number>, CV_IMWRITE_JPEG_QUALITY}
but should be
{CV_IMWRITE_JPEG_QUALITY, <desired quality value>}
imwrite prints on a 0 to 255 scale, but your image is in a 0 to 1 scale. To scale up, use this line:
image.convertTo(image, CV_8UC3, 255.0);
I only had to convert it to 16bit image
image.convertTo(image,CV_16UC3,255,255);
as per document, 8 or 16 bit images can be saved.
Related
In my rails app, i let the user upload images to use as thumbnails for resources they've made. I do all the image processing with imagemagick's convert command: i convert to jpg, letterbox it to 800x600px and then make some smaller thumbnail versions of that.
This is all working fine. The problem is that some images that have come off my iPhone, for example, have the wrong orientation. My desktop seems to variously deal with this: when i see the tiny thumbnail for the image in the file chooser dialog, it's got the wrong orientation, but if I open it in the image viewing tool, it's got the correct orientation.
Presumably there's some header or metadata or something in the image file which tells the app that it needs to rotate the file? I think that I need to read this in before I do any other processing of the image, so that I can rotate the image (if necessary) before doing all the other stuff.
Can anyone tell me how I can do this, in bash on an Ubuntu server?
thanks, Max
EDIT: a bit of googling suggests that this is to to with EXIF headers...
It's true that you will have to look for orientation value reading Exif metadata of Image. Using imagemagick you can get this value by
identify -format '%[exif:orientation]' <Path to Image>
//or by using
identify -format '%[orientation]' <Path to Image>
Exif Orientation values range from 1 to 8 and maps to orientation as below:
1 = Horizontal (normal)
2 = Mirror horizontal
3 = Rotate 180
4 = Mirror vertical
5 = Mirror horizontal and rotate 270 CW
6 = Rotate 90 CW
7 = Mirror horizontal and rotate 90 CW
8 = Rotate 270 CW
Thus, image would require orientation correction if this metadata tag returns with a non 1 value. If this tag returns with no value it can be assumed to be having normal orientation.
To correct orientation to normal you can use following command
convert -auto-orient <inputImagePath> <outputImagePath>
Try
identify -format "%f %[EXIF:Orientation]" <imagename>
This gives a number from 1 to 8. These numbers are documented here
I have a image that I am trying to read via imread but after reading the image it comes to a matrix of 256 x 256 x 4 but to work on it i need it to be 256 x 256 x 3. I am trying but I am unable. So how can I try to convert it?
im = imread('Test1.tif');
It is always a good idea to inspect the output of imfinfo whenever you're not sure about an image format...
If you carefully read the documentation of the imread function regarding TIFF images:
If the color image uses the CMYK color space, A is an m-by-n-by-4 array. To determine which color space is used, use imfinfo to get information about the graphics file and look at the value of the PhotometricInterpretation field.
I am trying to understand why I am not getting expected result from the following lines of code:
pix=np.asarray(Image.open(File))) #I am reading a pbm file into memory
img = Image.fromarray((pix), '1') #rewriting
img.save("test1.pbm")
newpix=~pix #inverting the image
img = Image.fromarray((newpix), '1')
img.save("test2.pbm")
original image and test1.pbm(image 1) is same, but test2.pbm (image 2) isn't what I am expecting (the foreground pixels become background ones and vice versa). I am attaching the images here (converted to jpeg). What am I doing wrong?
Another issue is that for most of the foreground pixels in test1.pbm, the value is False. But that is not reflected in the saved image.
I converted both of these images from this original image http://www.mathgoodies.com/lessons/graphs/images/line_example1.jpg using Imagemagick.
I don't recognise which language you are using, but your original image, when converted with ImageMagick like this:
convert cdLTY.jpg -negate out.jpg
looks like this:
So I deduce the problem is in your inversion. I don't know what
newpix=~pix
does (probably complelementing it or inverting all the bits?) but I think you need to subtract each pixel from 255 to invert your image, so if a pixel is 10 in the original image, it needs to be 255-10 or 245 in the new image.
Explanation
Pixels are normally encoded with 0=black and 255=white. So, if your pixel was originally black (0) when you do new pixel = 255 - original value, it will become 255-0, or 255 meaning it is now white. Likewise, if a pixel starts off white (255), when you do 255-255 you get 0 which is now black.
I am writing a function that generates series of images. I am using the imwrite function to write each image to a file:
Ecc=sqrt(real(E(:,:,1)).^2+real(E(:,:,2)).^2+real(E(:,:,3)).^2+imag(E(:,:,1)).^2+imag(E(:,:,2)).^2+imag(E(:,:,3)).^2);
clf
Q=imagesc(nx/rad,ny/rad,Ecc);
if i==1
cl=caxis;
else
caxis(cl)
end
imwrite(Q,['Frame-',num2str(i),'.tif'],'tif');
But I am not getting the images. The files are generated just fine, but they are just white images with dimension 1x1. Any help please?
Thank you
Use imwrite on Ecc instead of Q. The output of imagesc (as I recall) is a handle to the figure, which is not what you want to write out. Write out Ecc instead.
Adding to what user3817401 has written.
Completly white images can result from data not being scaled prior to being sent to imwrite. Consider following:
Ecc = (Ecc - min(min(Ecc))) / (max(max(Ecc)) - min(min(Ecc)));
promply before imwrite. This will guarantee, that the image is in range 0-1 and should solve the problem.
The function imagesc returns a handle (you store it as Q), not scaled image data. Then, the function imwrite is interpreting Q as an image. Because it is a handle, it is just 1x1 and it's value is not meaningful as an image. Try scaling Ecc as desired and then writing that instead.
In past I have used OpenCv for processing 32 bit .bmp files, and have got successful results. How do I make use of Opencv functions to process 12bit raw data?
My processing will be mostly operations like finding the some of 1000 pixels and so on.
EDIT
The file that I am getting is .bin file. And the Pixels in Image are placed like this(the file has all the content like this, coz I am taking a picture of white paper):
(FF)(0F)(FF)(0F)(FF)(0F)(FF)(0F)(FF)(0F)(FF)(0F)(FF)(0F)
Clearly I can do 16 bit processing on this.
Well I wanted to do 16 bit processing on this image. The secret is then reveled in another question .
For 16 bit I will have to switch to PNG not bmp!
This document says I can use 16 bit PNG in OpenCV
From what I know, OpenCV is only handling 8, 16 and 32 bits images correctly.
depending on what you want to do, you should
either transforming your 12 bits image into 8bits (assuming it s a 12 bits bayer encoded image)
or convert it manually to 16 by padding the values with zeros. From what I found here, this might already been done on your image.
I'd advise you to look closer at how your pixels are exactly placed in your image before doing anything. This will greatly help you to know what is best.
A good way to do this is using bless or another hex editor
EDIT:
Taken from here, Your data are (I think) encoded over 16 bits with padding
Simply convert from 16 bits to 8 bits using Opencv should do the trick, as it is what is done while converting to JPEG.
Have you at least tried ?
Left shift the bits and store them as 16bit.
For a monochrome camera:
cv::Mat imgOpenCV = cv::Mat(cv::Size(img->width, img->height), CV_16UC1, (char*)img->imageData, cv::Mat::AUTO_STEP); //Convert the raw image
imgOpenCV.convertTo(imgOpenCV, CV_16UC1, 1.0*(2^4), 0.0); //Shift left 4 bits
For a color camera:
// Convert the image using the manufacturer's SDK (Imperx in this case)
IpxImage* imgConverted = nullptr;
IpxError err = IPX_CAM_ERR_OK;
IpxSize imgSize;
imgSize.height = img->height;
imgSize.width = img->width;
uint32_t pixelType = II_PIX_BGR12;
err = IpxCreateImage(&imgConverted, imgSize, pixelType);
err = IpxBayer_ConvertImage(hBayer, img, imgConverted);
// Create OpenCV converted image
cv::Mat imgOpenCV = cv::Mat(cv::Size(imgConverted->width, imgConverted->height), CV_16UC3, (char*)imgConverted->imageData, cv::Mat::AUTO_STEP); //Convert the image
imgOpenCV.convertTo(imgOpenCV, CV_16UC3, 1.0*(2^4), 0.0); //Shift left 4 bits
You could also use the manufacturer's SDK to convert to 16 bit directly, but I suspect this scales the bit depth instead of shifting it in some cases. I'd rather preserve the raw bit depth information, so doing the shift myself prevents me from having to look under the hood when I switch manufacturers (GigE cameras force you to use the manufacturer SDK unfortunately).
No function of OpenCV supports 12 bit data.
Read the data as 'char'. 3 char = 2x12 bit data.
This data can be conveniently converted to 16bit data:
Left shift char1 by 4 and store to short1.
Add it with (char2 & 0xF0) to get the first 12 bit data in short1.
Left shift (char2 & 0x0F) by 8 and store to short2.
Add it with char3 to get the next 12 bit data in short2.