I need to extract CbCr chroma data from JPEG images, for image analysis. (in C/C++)
As I understand it, the JPEG "raw data" is compressed YCbCr. Am I correct in this assumption? How can I verify this for a given image?
I am currently using TubroJpeg lib. The documentation of tjDecompressToYUV says that it:
Decompress a JPEG image to a YUV planar image. This function
performs JPEG but leaves out the color conversion step, so a
planar YUV is generated instead of an RGB image.
I am a bit confused as to the output of this function. I thought that YUV and YCbCr were slightly different color spaces. Does this mean that for UV chroma I'd need to manipulate the output, and that the output "UV" components are actually CbCr components ?
The JPEG standard has no knowledge of color spaces. It simply compresses color components.
If is the specific file format (e.g. JFIF, EXIF, ADOBE) that specifies the color format. In most cases it is YCbCR. In some cases it is not (some adobe).
This link may explained the confusion
http://en.wikipedia.org/wiki/Yuv#Confusion_with_Y.27CbCr
YUV and YCbCR are similar, but different. If there is no color conversion, I have to believe that they have confused YUV and YCbCr.
Related
I have a video streamed from a source camera, that provides each frame into a uchar* buffer.
This buffer is YUV 4:2:2, using UYVY format.
I want to obtain a workable Mat in YUV, where I can split channels and do every filter I want.
The problem is that UYVY format is compressed and I don't find any way to explode data directly into YUV format, whitout passing from BGR.
For example, I tried this, but I don't want for performance reasons, to pass from BGR:
cvtColor(inMat, middleMat, COLOR_YUV2BGR_UYVY);
cvtColor(middleMat, outMat, COLOR_BGR2YUV);
I need something similar to:
cvtColor(inMat, outMat, COLOR_YUV2YUV_UYVY);
Thanks in advance
Giuseppe
I use he libjpeg to manipulate jpeg images.
My question is simple :
Is the output of the libjpeg always RGB (or luminance for monochrome images) ?
I'm not an expert with the color spaces...
Thanks !
Strictly speaking, JPEG is always YCbCr (YUV), so that's the output. You may apply other colorspaces, but typically only RGB or (less commonly) CMYK are supported, and the underlying data in the file will remain YCbCr. Grayscale simply leaves the second two channels out and only encodes Y.
I'm using WIC (Windows Imaging Component) to decode image files and get access to the pixel data. I'm trying to figure out the pixel order (i.e., bottom-up or top-down).
I use IWICImagingFactory::CreateDecoderFromFileName to create the decoder from which I grab the (first) frame (IWICBitmapFrameDecode). With the frame, I use GetPixelFormat and GetSize to compute a buffer size, and finally I use CopyPixels to get the decoded pixel data into my buffer.
This works fine with a variety of JPEG files, giving me pixel rows in top-down sequence, and the pixels are in BGRX order (GUID_WICPixelFormat32bppBGR).
When I try with GIF files, however, the pixel rows come in bottom-up sequence. The reported pixel format is RGBA (GUID_WICPixelFormat32bppRGBA), but the ground truth shows the channel order is BGRA (with the blue in the low byte of each 32-bit pixel, just like JPEG).
My primary question: Is there a way for me to query the top-down/bottom-up orientation of the pixel data?
I found a similar question that asked about rotation when using JPEG sources, and the answer was to query the EXIF data to know whether the image was rotated. But EXIF isn't used with GIF. So I'm wondering whether I'm supposed to assume that pixels are always bottom-up, except for ones that do have an EXIF orientation that says otherwise. Update 6/25/2020 Nope, the JPEG orientation is neutral and the GIF has no orientation information, yet MS Paint and other programs can open the files in the correct orientation.
My secondary question: What's up with the incorrect channel order (RGB/BGR) from the GIF decoder?
Not only that, the WIC documentation says that the GIF decoder should return indexes into a color table (GUID_WICPixelFormat8bppIndexed) rather than actual pixel values. Is it possible some software on my machine installed its own buggy GIF decoder that supersedes the one that comes with Windows 10?
To query photo orientation for formats that support it you should use System.Photo.Orientation photo metadata policy (or one of file format specific metadata query paths) using IWICMetadataQueryReader interface.
As for GetPixelFormat() reporting "incorrect" pixel format, it is right there in the Remarks section:
The pixel format returned by this method is not necessarily the pixel format the image is stored as. The codec may perform a format conversion from the storage pixel format to an output pixel format.
Native byte order of image bitmaps under Windows is BGRA, so that is what you are getting from the decoder. If you want image in a different format you need to use IWICImagingFactory::CreateFormatConverter() to create a format converter and convert the image data before copying.
Finally, GIF doesn't have orientation metadata because it is always encoded from top to bottom. Most likely reason you are getting a vertically inverted image is because you are reading it directly from the decoder -- try calling CopyPixels() on the converter instead.
I'm trying to get a YUV420 palanar or semiplanar (NV12) image out of jpeg using libjpeg.
I see that there is a option to specify output format to JCS_YCbCr which would generally be a YUV format, but as far as i understand it would give me the data as arrays of 3 elements { Y, U, V }. So to get the image to the right format i would have to rearange and subsample the pixels myself and i want to avoid that for performance reasons.
So I was wondering is there a way to configure libjpeg to output a YUV420p / NV12 buffer directly.
Just take a look at gst_jpeg_decode() in gstreamer source tree. This function along with gst_jpeg_decode_direct() function does exactly what you want to do.
Note that it gives YUV420 planar output, bypassing all color conversion done by libjpeg. (Note: this assumes that the input JPEG is encoded in YUV420 color space (aka I420), which is true for almost all JPEGs out there.
My platform is Windows. I didn't expect reading indexed palette image to be this difficult in C++. In case you are not familiar with it, it's single channel image but expresses its pixel color with 256 indexed colors called palette.
I was using OpenCV but its imread just converts the file to a 3 channel image so I have no way to save it back to indexed palette image or compare it with another indexed palette image.
I tried to use Bitmap but for some reason, it does not read correct pixel values.
So right now, I am looking for a light library or code to read pixels from indexed palette file.
Using OpenCV to read or write a image from real cameras will lose and change the image information, so I prefer to use gdi+, which is more powerful in dealing with image format problems to solve your problem.
As comments on the question shows, I decided to have two methods, OpenCV for non-indexed-palette images and Bitmap (GDI+) for indexed palette images. Now everything is working perfect.