OpenCV - confusion over bit depth requirements of different functions - c++

I find myself doing a lot of convertTo() calls in my C++ opencv code. It's somewhat confusing and I'm not sure when I need to convert the bit depth of an image until I get an error message.
For example, I have a Mat representing an image that is 16U. I then try to call matchTemplate() and get an assertion error that it expects 8U or 32F. Why shouldn't template matching work at 16U? Similar issues when I'm displaying the image as well (although bit depth restrictions make more sense in the case of displaying images). I find myself fiddling with convertTo() and scaling factors and such trying to get images to show up properly with imshow() and wish I were able to do this more elegantly (maybe I'm spoiled by matlab's imagesc function).
Am I missing something fundamental about what openCV expects of bit depth usage? How deal with the opencv library functions' requirements for bit depth in a cleaner way?

Assuming you are using the C interface :
cvMatchTemplate(const CvArr* image, const CvArr* templ, CvArr* result,int method)
image – Image where the search is running; should be 8-bit or 32-bit
floating-point
Most of the functions in OpenCv will use either 8U (for greyscale images) or 32F (for color 3 channel images).

The most common image type is 8U (for both color and grey). This is the preferred format of OpenCV.
Other formats are supported on a more function specific basis.

Related

Qt - Conversion JPEG to PNG not giving the same image

I would like to convert a jpeg image into png and to do so I am using the code below:
QImageReader reader;
reader.setFileName(imagePath);
QImage image = reader.read();
QImageWriter writer;
writer.setFileName(newImagePath);
writer.write(image);
I thought the output image would be exactly the same as the input one but the difference image is not null and I cannot figure out why. The difference image looks like a noise image with values ranging from -5 to 6.
I tried to do the same thing with another librairy called VTK but I don't have the same problem, the image before and after compression are exactly the same.
Any suggestion is welcome !
Different JPEG decoders can produce slightly different RGB values
(more so if the JPEG contains a ICC profile); there a lot of numerical rounding and conversions involved (however, encoders are supposed to differ in no more than one bit per pixel from the reference implementation, but I would not bet on that; see eg this answer and this one).
I suggest you try to do the pixel-by-pixel comparison inside QImage.

Is there a SURF_CUDA implementation for colored images?

Recently started playing around with OpenCV, trying that SURF algorithm, that is really slow on CPU, and does not work with color images on GPU (has an assertion that checks for type==CV_8UC1), and converting images to grayscale gives some pretty bad results.
I'm wondering if there is a colored implementation on gpu in OpenCV, somewhere else, or if there is some kinda tricky workaround like doing the algorithm on all 3 channels and then magically merging them?
Thanks.
There's no special handling of color images in OpenCV's non-GPU version of SURF; the code shows that it just calls cvtColor(img, img, COLOR_BGR2GRAY) if it gets an image with more than one channel.
You might try converting the image to HSV and using one or more of the H, S, and/or V channels. More discussion at this question.

HSI color format in python with opencv library

Good morning, I was reviewing in python, along with Opencv, conversions to formats of different colors, but I do not find the HSI format, with the cv2.cvtColor() function.
Does anyone know if it matches the COLOR_BGR2HLS parameter?
Thank you for your attention
According to the Wikipedia article given HERE, the HSV, HLS and HSI color space terminology can be used interchangeably.
There is another option available in OpenCV as well cv2.cvtColor(img1,cv2.COLOR_BGR2HSV).
If you work out both the options, the resulting image would appear slightly different as in the following:
Using HSV:
Using HLS:
Now if you split the channels of these images (to split use cv2.split()) and analyze them:
The hue channel appears to be the same in both cases.
The saturation channel also provides the same result but appear to be switched.
You will notice a slight difference between the value channel of HSV image and the luminosity channel of the HLS image.
Work it out for an image and you will see for yourself.
HSV, HLS and HSI are similar not exactly same

pixel conversion to raw bits (bit-stream)

I want to read the contents of every pixel in an image i have and convert it to a bit-stream (raw bits) or contain it in a 2-D array . Which would be the best place to start looking for such a conversion?
Specifics of the image : Standard test image called lena.bmp
size : 256 x 256
Bit depth of pixel : 8
Also I would like to know the importance of the number of bits per pixel with regards to this question since packing and unpacking will also be incorporated .
CImg is a nice simple, lightweight C++ library which can load and save a number of image formats (including BMP).
It's a single header file, so there's no need to compile or link the library. Just include the header, and you're good to go.
You should investigate OpenCV: a cross-platform computer vision library. It provides a C++ API as well as a C API, and it supports many image formats including bmp.
In the C++ interface, cv::Mat is the type that represents a 2D image. A simple application that loads and displays an image can be found here.
To learn how to access the matrix elements (pixels) you can check these threads:
OpenCV get pixel information from Mat image
Pixel access in OpenCV 2.2
Common Matrix Operations in OpenCV
OpenCV’s C++ interface offers a short introduction to cv::Mat. There has been many threads on Stackoverflow regarding OpenCV, there's a lot of valuable content around and you can benefit a lot by using the search box.
This page has a collection of books/tutorials/install guides focused on OpenCV, but this the newest official tutorial.

image color conversion

I need to convert 24bppRGB to 16bppRGB, 8bppRGB, 4bppRGB, 8bpp grayscal and 4bpp grayscale. Any good link or other suggestions?
preferably using Windows/GDI+
[EDIT] speed is more critical than quality. source images are screenshots
[EDIT1] color conversion is required to minimize space
You're better off getting yourself a library, as others have suggested. Aside from ImageMagick, there are others, such as OpenCV. The benefits of leaving this to a library are:
Save yourself some time -- by cutting out dev and testing time for the algorithm
Speed. Most libraries out there are optimized to a level far greater than a standard developer (such as ourselves) could achieve
Standards compliance. There are many image formats out there, and using a library cuts the problem of standards compliance out of the equation.
If you're doing this yourself, then your problem can be divided into the following sub-problems:
Simple color quantization. As #Alf P. Steinbach pointed out, this is just "downscaling" the number of colors. RGB24 has 8 bits per R, G, B channels, each. For RGB16 you can do a number of conversions:
Equal number of bits for each of R, G, B. This typically means 4 or 5 bits each.
Favor the green channel (human eyes are more sensitive to green) and give it 6 bits. R and B get 5 bits.
You can even do the same thing for RGB24 to RGB8, but the results won't be as pretty as a palletized image:
4 bits green, 2 red, 2 blue.
3 bits green, 5 bits between red and blue
Palletization (indexed color). This is for going from RGB24 to RGB8 and RGB4. This is a hard problem to solve by yourself.
Color to grayscale conversion. Very easy. Convert your RGB24 to YUV' color space, and keep the Y' channel. That will give you 8bpp grayscale. If you want 4bpp grayscale, then you either quantize or do palletization.
Also be sure to check out chroma subsampling. Often, you can decrease the bitrate by a third without visible losses to image quality.
With that breakdown, you can divide and conquer. Problems 1 and 2 you can solve pretty quickly. That will allow you to see the quality you can get simply by doing coarser color quantization.
Whether or not you want to solve Problem 2 will depend on the result from above. You said that speed is more important, so if the quality of color quantization only is good enough, don't bother with palletization.
Finally, you never mentioned WHY you are doing this. If this is for reducing storage space, then you should be looking at image compression. Even lossless compression will give you better results than reducing the color depth alone.
EDIT
If you're set on using PNG as the final format, then your options are quite limited, because both RGB16 and RGB8 are not valid combinations in the PNG header.
So what this means is: regardless of bit depth, you will have to switch to index color if you want RGB color images below 24bpp (8 bits per channel). This means you will NOT be able to take advantage of the color quantization and chroma decimation that I mentioned above -- it's not supported in PNG. So this means you will have to solve Problem 2 -- palletization.
But before you think about that, some more questions:
What are the dimensions of your images?
What sort of ideal file-size are you after?
How close to that ideal file-size do you get with straight RBG24 + PNG compression?
What is the source of your images? You've mentioned screenshots, but since you're so concerned about disk space, I'm beginning to suspect that you might be dealing with image sequences (video). If this is so, then you could do better than PNG compression.
Oh, and if you're serious about doing things with PNG, then definitely have a look at this library.
Find your self a copy of the ImageMagick [sic] library. It's very configurable, so you can teach it about the details of some binary format that you need to process...
See: ImageMagick, which has a very practical license.
I received acceptable results (preliminary) by GDI+, v.1.1 that is shipped with Vista and Win7. It allows conversion to 16bpp (I used PixelFormat16bppRGB565) and to 8bpp and 4bpp using standard palettes. Better quality could be received by "optimal palette" - GDI+ would calculate optimal palette for each screenshot, but it's two times slower conversion. Grayscale was received by specifying simple custom palette, e.g. as demonstrated here, except that I didn't need to modify pixels manually, Bitmap::ConvertFormat() did it for me.
[EDIT] results were really acceptable until I decided to check the solution on WinXP. Surprisingly, Microsoft decided to not ship GDI+ v.1.1 (required for Bitmap::ConvertFormat) to WinXP. Nice move! So I continue researching...
[EDIT] had to reimplement this on clean GDI hardcoding palettes from GDI+