opencv加载内存中图片
OpenCv读取与解码内存中的图片及过程中的内存问题 - swjtu_ray的博客 - 优快云博客 https://blog.youkuaiyun.com/swjtu_ray/article/details/52529535
开发中遇到的问题,为了让别人方便也让自己方便,特此记录。
有时候我们会需要读取内存里面的图片,为了提高效率,避免了从硬盘重复读取文件所消耗的时间。
以下是代码:
//data为图像再内存中的地址
CvMat mat = cvMat(width, height, CV_8UC1, data);//Read input binary image
//第二个参数为flag,在opencv文档中查询
IplImage *pIplImage = cvDecodeImage(&mat, 1);
//记住第二个参数为copy=true,否则释放后内存会出错
Mat image(pIplImage,true);
//cvDecodeImage产生的IplImage*对象***需要手动释放内存***
cvReleaseImage(&pIplImage);
有内存溢出的风险,试试看。
opencv从磁盘加载一张图片非常简单,通过cv::imread即可,代码如下
cv::Mat src_mat = cv::imread("1.jpg"); //读取图片1.jpg,imread会将图片内容解码成yuv或rgb存放到Mat对象
cv::Mat dst_mat = src_mat(cv::Rect(100, 100, 1600, 900)); //获取图片固定区域的内容
std::vector<uchar> jpg_buff;
bool ret = cv::imencode(".jpg", dst_mat, jpg_buff);//对固定区域的内容重新进行jpg编码,生成jpg图片,存入jpg_buff
FILE *file = fopen("2.jpg", "wb");
if (file != nullptr) {
fwrite(jpg_buff.data(), 1, jpg_buff.size(), file); //将jpg图片写入内存
fclose(file);
}
然而,很多情况,程序需要从内存中加载图片,例如通过网络上传的图片。很显然,这样的图片不能写入磁盘,然后再通过cv::imread读取,效率太低了。因此,需要从内存直接加载。然后通过cv::imdecode将图片解码成cv::Mat,代码如下:
FILE *file = fopen("1.jpg", "rb");
uchar *mem_pic = nullptr;
long size = 0;
if (file != nullptr) {
fseek(file, 0, SEEK_END);
size = ftell(file);
fseek(file, 0, SEEK_SET);
mem_pic = new uchar[size];
fread(mem_pic, 1, size, file);
fclose(file);
}
cv::_InputArray pic_arr(mem_pic, size);
cv::Mat src_mat = cv::imdecode(pic_arr, CV_LOAD_IMAGE_COLOR);
cv::Mat dst_src = src_mat(cv::Rect(100, 100, 1600, 900));
std::vector<uchar> pic_buff;
bool ret = cv::imencode(".jpg", dst_src, pic_buff);
file = fopen("3.jpg", "wb");
if (file != nullptr) {
fwrite(pic_buff.data(), 1, pic_buff.size(), file);
fclose(file);
}
cv::_Array还可以使用std::vector代替,代码如下:
FILE *file = fopen("1.jpg", "rb");
uchar *mem_pic = nullptr;
long size = 0;
if (file != nullptr) {
fseek(file, 0, SEEK_END);
size = ftell(file);
fseek(file, 0, SEEK_SET);
mem_pic = new uchar[size];
fread(mem_pic, 1, size, file);
fclose(file);
}
//cv::_InputArray pic_arr(mem_pic, size);
std::vector<uchar> pic_vec(mem_pic, mem_pic + size);
cv::Mat src_mat = cv::imdecode(pic_vec, CV_LOAD_IMAGE_COLOR);
cv::Mat dst_src = src_mat(cv::Rect(200, 200, 400, 225));
std::vector<uchar> pic_buff;
bool ret = cv::imencode(".jpg", dst_src, pic_buff);
file = fopen("3.jpg", "wb");
if (file != nullptr) {
fwrite(pic_buff.data(), 1, pic_buff.size(), file);
fclose(file);
}
从这个博客上下载的,为啥不写注释啊!
opencv加载内存中图片 - flyingshineangel的专栏 - 优快云博客 https://blog.youkuaiyun.com/flyingshineangel/article/details/86742617
得学习后有时间我来解惑答疑,现在我还不明白。
另外一个介绍
opencv加载内存中的图片数据 - 菜鸟逐梦 - 优快云博客 https://blog.youkuaiyun.com/qq_32435729/article/details/77061946
经过实践终于找到了 opencv加载内存中的图片数据的方法,现在记录下来。
//参数分别为 图片宽度,高度,类型,图片数据指针(unsigned char*)
//这个构造函数并没有从新分配内存
CvMat mCvmat = cvMat(w, h, CV_8UC1, mImgData);
IplImage* IpImg = cvDecodeImage(&mCvmat, 1);
//opencv3.0 IplImage到Mat类型的转换的方法
Mat image = cvarrToMat(IpImg);
if (!image.data)
{
return false;
}
cvReleaseImage(&IpImg);
或者(opencv 3.4.5实测)
//Mat和mImgData共享同一块内存区域
uchar* mImgData = new uchar[w*h*channel];
Mat imm(h,w,CV_8UC3, mImgData);
//process img
delete []mImgData;