How to process a JPEG binary data in OpenCV?

こ雲淡風輕ζ 提交于 2019-12-11 02:53:29

问题


I am trying to process a JPEG Binary data in OpenCV. When I do that I get Segmentation fault (core dumped).

I read JPEG file through fread command and stored in a buffer.

After reading, I copied the buffer data to a Mat variable, When I tried to do grayscale conversion on copied data using cvtColor OpenCV function. I get Segmentation Fault.

int main( int argc, char** argv )
{

    Mat threshold_output;
    Mat gray_image;

    unsigned char *pre_image;
    FILE *read_image;
    FILE *write_image;
    int filesize;
    size_t data, write;

    read_image = fopen(argv[1] , "rb"); //Read Jpeg as Binary
    write_image = fopen("output11.jpg", "wb"); //Write JPEG

    if(read_image == NULL)
    {
        printf("Image Not Found\r\n");
    }
    fseek(read_image, 0, SEEK_END);
    int fileLen = ftell(read_image);
    fseek(read_image, 0, SEEK_SET);

    pre_image = (unsigned char *)malloc(fileLen);
    data = fread(pre_image, 1, fileLen, read_image);
    write = fwrite(pre_image, 1, fileLen, write_image);

    // Printed and verify the values
    printf("File Size %d\r\n", fileLen);
    printf("Read bytes %zu\r\n", data);
    printf("Write bytes %zu\r\n", data);

    fclose(read_image);
    fclose(write_image);

    /* Copy the Jpeg Binary buffer to a MAt Variable*/  
    cv::Mat image(Size(640, 480), CV_8UC3, pre_image); //Seg Fault comes here
    /* Convert Grayscale */
    cvtColor( image, gray_image, CV_BGR2GRAY);
    /* Threshold conversion */
    threshold( gray_image, threshold_output, 80, 255, THRESH_BINARY );

    namedWindow( "Thresholded", CV_WINDOW_AUTOSIZE );
    imshow( "Thresholded", image );

    waitKey(0);
    return 0;
}

I have attached the code for reference. I have verified that both fread and fwrite works properly. But when I do the cvtColor only I got error.


回答1:


As @Micka already pointed out, you should use cv::imdecode

You can use it with your FILE*. You probably may want to use fstreams if you're using C++. You can also rely directly on OpenCV capabilities to read files.

The code below will show you these options for reading files. Code for writing is similar (I can add it if you need it).

Remember that if you want to write the binary stream, you should use imencode

#include <opencv2\opencv.hpp>
#include <fstream>
#include <stdio.h>

using namespace std;
using namespace cv;

int main()
{

    ////////////////////////////////
    // Method 1: using FILE*
    ////////////////////////////////

    FILE* read_image = fopen("path_to_image", "rb");
    if (read_image == NULL)
    {
        printf("Image Not Found\n");
    }

    fseek(read_image, 0, SEEK_END);
    int fileLen = ftell(read_image);
    fseek(read_image, 0, SEEK_SET);

    unsigned char* pre_image = (unsigned char *)malloc(fileLen);
    size_t data = fread(pre_image, 1, fileLen, read_image);

    // Printed and verify the values
    printf("File Size %d\n", fileLen);
    printf("Read bytes %d\n", data);

    fclose(read_image);

    vector<unsigned char> buffer(pre_image, pre_image + data);
    Mat img = imdecode(buffer, IMREAD_ANYCOLOR);

    ////////////////////////////////
    //// Method 2: using fstreams
    ////////////////////////////////

    //ifstream ifs("path_to_image", iostream::binary);
    //filebuf* pbuf = ifs.rdbuf();
    //size_t size = pbuf->pubseekoff(0, ifs.end, ifs.in);
    //pbuf->pubseekpos(0, ifs.in);
    //vector<char> buffer(size);
    //pbuf->sgetn(buffer.data(), size);
    //ifs.close();
    //Mat img = imdecode(buffer, IMREAD_ANYCOLOR);


    ////////////////////////////////
    //// Method 3: using imread
    ////////////////////////////////

    //Mat img = imread("path_to_image", IMREAD_ANYCOLOR);


    // Work with img as you want

    imshow("img", img);
    waitKey();


    return 0;
}



回答2:


OpenCV uses channels like BGR etc and can't perform computer vision operations on ENCODED images, since encoded images don't consist of pixel data but some encoded data which can be transformed to pixels. OpenCV assumes that images are already decoded so it can work on pixel data.

BUT: you can use a binary image buffer (like your pre_image) and let openCV DECODE it.

use cv::imdecode to do it and after that you'll get a legal cv::Mat image. http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#imdecode



来源:https://stackoverflow.com/questions/31831210/how-to-process-a-jpeg-binary-data-in-opencv

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!