我正在尝试在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;
}
我附上了代码以供参考。我已确认fread
和fwrite
都能正常运行。
但是当我执行cvtColor
时,我才会收到错误。
答案 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;
}