Direct Show YUY2 Pixel Output from videoInput - c++

I'm using videoInput to interface with DirectShow and get pixel data from my webcam.
From another question I've asked, people have suggested that the pixel format is just appended arrays in the order of the Y, U, and V channels.
FourCC's website suggests that the pixel format does not actually follow this pattern, and is instead |Y0|U0|Y1|V0|Y2|U0|Y3|V0|
I'm working on a few functions that convert the YUY2 input image into RGB and YV12, and after having little to no success, thought that it might be an issue with how I'm interpreting the initial YUY2 image data.
Am I correct in assuming that the pixel data should be in the format from the FourCC website, or are the Y, U and V channels separate arrays that have be concentrated (so the data is in the order of channels, for example: YYYYUUVV?

In YUY2 each row is a sequence of 4-byte packets: YUYV describing two adjacent pixels.
In YV12 there are 3 separate planes: first Y of size width*height then V and then U, both of size width/2 * height/2.

Related

Convert RGB32 image to ofPixels in Open Frameworks

I am trying to display a video from a video decoder library.
The video is delivered as a byte array with RGB32 pixel format.
Meaning every pixel is represented by 32 bits.
RRBBGGFF - 8bit R, 8bit G, 8bit B, 8bit 0xFF.
Similar to QT Qimage Format_RGB32.
I thnik I need to convert the pixel array to ofPixels, Then load the pixels to ofTexture.
Then I can draw the texture.
I don't know how to convert/set the ofPixels from this pixel format.
Any tips/ideas are so so welcome.
Thanks!
Try using a ofThreadChannel as described in this example in order to avoid writing and reading from your ofTexture / ofPixels.
Then you can load a uint8_t* by doing :
by using an ofTexture's method loadFromPixels() :
// assuming data is populating the externalBuffer
void* externalBuffer;
tex.loadFromPixels((uint8*)externalData, width, height, GL_RGBA);
Hope this helps,
Best,
P

YUV420 to grayscale in C++

I'm trying to write a function to convert a camera stream with a YUV420 pixel format to grayscale. To my understanding, I only need to extract the Y values since these are the luminance of the image frames.
I am using this page as a reference https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/pixfmt-yuv420.html, but I am having trouble understanding what a planar format is and how to essentially skip through the UV values. I think I would need to get the 2x2 Y values (e.g., Y00, Y01, Y10, Y11 in the above link) for every UV values, but I'm also not sure if I should just write them consecutively into my image frame's destination. That is, if I have a pointer to my destination and I have these for Y values, should I just write them in the order of Y00, Y01, Y10, Y11, Y02, etc?

OpenCV convertTo()

I came across this code:
image.convertTo(temp_image,CV_16SC3);
I saw the description of the convertTo() function from here, but what confuses me is image. How can we read the above code? What would be the relation between image and temp_image?
Thanks.
The other answers here are correct, but lack some details. Let me try.
image.convertTo(temp_image,CV_16SC3);
You have a source image image, and a destination image temp_image. You didn't specify the type of image, but probably is CV_8UC3 or CV_32FC3, i.e. a 3 channel image (since convertTo doesn't change the number of channels), where each channel has depth 8 bit (unsigned char, CV_8UC3) or 32 bit (float, CV_32FC3).
This line of code will change the depth of each channel, so that temp_image has each channel of depth 16 bit (short). Specifically it's a signed short, since the type specifier has the S: CV_16SC3.
Note that if you are narrowing down the depth, as in the case from float to signed short, then saturate_cast will make sure that all the values in temp_image will be in the correct range, i.e. in [–32768, 32767] for signed short.
Why you need to change the depth of an image?
Some OpenCV functions require input images with a specific depth.
You need a matrix to contain a different range of values. E.g. if you need to sum (or subtract) some images CV_8UC3 (tipically BGR images), you'd better store the result in a CV_16SC3 or you'll probably get wrong results due to saturations, since the range for CV_8U images is in [0,255]
You read with imread, or want to store with imwrite images with 16bit depth. This are usually used (AFAIK) in medical or graphics application to allow a wider range of colors. However, most monitors do not support 16bit image visualization.
There may be other cases, let me know if I miss the one important to you.
An image is a matrix of pixel information (i.e. a 1080p image will be a 1,920 × 1,080 matrix where each entry contains rbg values for that pixel). All you are doing is reformatting that matrix (each pixel entry, iteratively) into a new type (CV_16SC3) so it can be read by different programs.
The temp_image is a new matrix of pixel information based off of image formatted into CV_16SC3.
The first one is a source, the second one - destination. So, it takes image, converts it into type CV_16SC3 and stores in temp_image.

Conversion from YBR_FULL to RGB in c++?

Could you please explain the relationship between YBR_FULL and RGB so that I'm able to convert the YBR_FULL image to RGB in C++?
I'm getting the pixel data from a Dicom image as bytes in a buffer using DCMTK library. For some selected pixels I set the pixel values as 0, for RGB that works fine as when the images are Visualized the pixel values which are set to 0 are shown as black, but in case of YBR_FULL the those pixels are shown as green. I don't quite understand what the problem is. Could you please elaborate what mistake I'm doing?
this has been answered
Create BufferedImage from YBR_FULL Dicom Image
here's the link to the mathemetical formula
http://www.fourcc.org/fccyvrgb.php
If you are setting the YBR values to (0,0,0) your luminance (Y) is in the correct value, but the chroma (B and R) zero point is exactly in te middle of the range, so you should try with the value 128 (if B and R have one byte size). then you have YBR = (0, 128U, 128U)

Opencv storing Yuyv (YCrCb) in cv::Mat

I'm the data I get out of my webcam is yuv422. I'd like to store this yuv422 into a cv::Mat without converting it to RGB... Is this possible?
Thanks.
Given the chroma subsampling, it's probably going to be simpler if you unpack the YUYV data into a YUV matrix (3 channels of 8-bit data), then perform your filtering with cv::inRange etc. You just need to interpolate the U and V samples for each Y.
Another alternative would be to treat the matrix as 4 channels of 8-bit data, and then in your filter results, combine the results from the two Y sample channels.
Yes, just create a 3 channel matrix. Please take a look at the basic Mat tutorial