如何在OpenCV中处理JPEG二进制数据?

时间:2015-08-05 11:26:58

标签: opencv mat

我正在尝试在OpenCV中处理JPEG二进制数据。当我这样做时,我得到分段错误(核心转储)

我通过fread命令读取JPEG文件并存储在缓冲区中。

阅读后,我将缓冲区数据复制到Mat变量, 当我尝试使用cvtColor OpenCV函数对复制的数据进行灰度转换时。我得到分段错误。

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;
}

我附上了代码以供参考。我已确认freadfwrite都能正常运行。 但是当我执行cvtColor时,我才会收到错误。

2 个答案:

答案 0 :(得分:1)

OpenCV使用类似BGR等的频道,并且无法对ENCODED图像执行计算机视觉操作,因为编码图像不是由像素数据组成,而是由一些可以转换为像素的编码数据组成。 OpenCV假设图像已经被解码,因此它可以处理像素数据。

但是:您可以使用二进制图像缓冲区(如pre_image)并让openCV解码它。

使用cv::imdecode来执行此操作,之后您将获得合法的cv::Mat图片。 http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#imdecode

答案 1 :(得分:1)

正如@Micka已经指出的那样,你应该使用cv::imdecode

您可以将其与FILE*一起使用。如果您正在使用C ++,则可能需要使用fstreams。您还可以直接依赖OpenCV功能来读取文件。

下面的代码将向您展示这些用于阅读文件的选项。写作代码类似(如果需要,我可以添加)。

请记住,如果要编写二进制流,则应使用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;
}