如何在 OpenCV 中处理 JPEG 二进制数据?
How to process a JPEG binary data in OpenCV?
我正在尝试在 OpenCV 中处理 JPEG 二进制数据。当我这样做时,我得到 Segmentation fault (core dumped).
我通过 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
时,只有我得到了错误。
OpenCV 使用 BGR 等通道,无法对编码图像执行计算机视觉操作,因为编码图像不包含像素数据,而是一些可以转换为像素的编码数据。 OpenCV 假定图像已经解码,因此它可以处理像素数据。
但是:您可以使用二进制图像缓冲区(就像您的 pre_image
)并让 openCV 对其进行解码。
使用 cv::imdecode
完成此操作,然后您将获得合法的 cv::Mat
图像。 http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#imdecode
正如@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;
}
我正在尝试在 OpenCV 中处理 JPEG 二进制数据。当我这样做时,我得到 Segmentation fault (core dumped).
我通过 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
时,只有我得到了错误。
OpenCV 使用 BGR 等通道,无法对编码图像执行计算机视觉操作,因为编码图像不包含像素数据,而是一些可以转换为像素的编码数据。 OpenCV 假定图像已经解码,因此它可以处理像素数据。
但是:您可以使用二进制图像缓冲区(就像您的 pre_image
)并让 openCV 对其进行解码。
使用 cv::imdecode
完成此操作,然后您将获得合法的 cv::Mat
图像。 http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#imdecode
正如@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;
}