问题
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