Reading pixel values from a binary file

asked 2016-03-11 19:13:21 -0500

froosher gravatar image

I have a series of 128x128 pixel sized frames stored in a binary file. Each pixel has 32 bits of information, I am interested in the last 12 bits of each pixel, these 12 bits should provide me with a grayscale image.

I know openCV doesn't support 12-bit, so I tried to do the masking using 0xfff, not sure if that is right. In my attempt I am looking at the 99th frame of the video, there is a 1024 byte header in each file that I am skipping, and each frame has 66960 bytes, hence the 66960*99 to skip to the 99th frame. I also skip a reserved 4 bytes which is in each.

The resulting image I get looks almost right, except it seems like there is a gray mask over the whole image. I have both what I am getting and what it should look like at the bottom attached.

My attempt is below, I know I am getting the pixel information right because I am checking pixel values by using another software, I believe the problem is in the way I am using the data types and Mat image type (unsigned int, short etc and CV_16U, CV_16S, CV_32). Please help with how to pad the pixel data and/or what type Mat to use. Thanks.

    file = fopen("binary_file", "rb");
    fseek(file, 0, SEEK_END);

    //frame loop
    unsigned int buffer[65536];
    fseek(file,4+1024+66960*99, SEEK_SET);
    fread(buffer, 4, 65536, ff);

    Mat img(128,128,CV_16S);
    int p = 0;
    for (int y = 0; y < img.rows; y++) {
        for (int x = 0; x < img.cols; x++) {
            img.at<short>(y, x) = ((buffer[p] & ((1 << 12) - 1)) & 0xfff);
            p++;
        }
    }
    imgshow("img",img);

What I get, looks masked

What it should look like

edit retag flag offensive close merge delete

Comments

1

May be you can try something like this

file = fopen("binary_file", "rb"); fseek(file, 0, SEEK_END);

//frame loop
unsigned int buffer[65536];
fseek(file,4+1024+66960*99, SEEK_SET);
fread(buffer, 4, 65536, ff);

Mat img(128,128,CV_32S,buffer),img1,img2;
bitwise_and(img,0xFFF,img1);
img1.convertTo(img2,CV_16U);

Without data it's difficult to test.

LBerger gravatar imageLBerger ( 2016-03-12 04:31:26 -0500 )edit
1

There seems to be some mismatch with the size of your buffers:

The image is 128x128x4 =65536 bytes

you load it into an unsigned int buffer with double that size (I believe an unsigned int is 16 bit, and you have 65536 of them). At this point each pixel takes up TWO 16 bit ints.

You then load into a signed 16 bit Mat. Each pixel in the original image is now on two pixels in the Mat.

The fact that the Mat is signed while the data isn't will probably turn your blacks to 50% Gray. Your whites may be dim because you are displaying a 12 bit image when OpenCV is expecting 16 bits and probably scales brightness accordingly.

I think LBerger's solution will work better for you with the following changes:

  • change buffer to unsigned char - just for neatness
  • change img to CV_32U
Guyygarty gravatar imageGuyygarty ( 2016-03-12 14:35:03 -0500 )edit

You may also want to multiply img by 16 to get 0x0000 1111 1111 1111 to display as white.

Guyygarty gravatar imageGuyygarty ( 2016-03-12 14:40:39 -0500 )edit