博舍

OpenCV基础: 图像矩阵Mat的数据类型与访问等 opencv图像数据类型转换

OpenCV基础: 图像矩阵Mat的数据类型与访问等

质量声明:原创文章,内容质量问题请评论吐槽。如对您产生干扰,可私信删除。主要参考:,Mat数据类型总结,像素值读取at()函数

文章目录Mat矩阵的定义独立定义引用定义(内存相同)复制定义(内存独立)特殊定义模板定义Mat矩阵的数据类型基本类型数据类型转换convertTo归一化cv::normalizeMat数组的访问独立访问数组元素区块访问与赋值区域替换

摘要:随时更新完善opencv中Mat相关的定义,类型,访问和应用.

Mat矩阵的定义

opencv中的cv::Mat类用于定义任意维度的稠密数组,所谓稠密,是指该数组任一位置的元素都有确定值,即使是0.

独立定义

定义变量的同时进行初始化:

cv::Matimg(640,480,CV_8UC1,cv::Scalar(100));//定义单通道灰度图,640x480,100cv::Matsrc(800,640,CV_8UC3,cv::Scalar(70,160,70));//定义三通道彩色图,数据类型为8位无符号整型cv::Matdst(960,540,CV_32FC3,cv::Scalar(1.0f,0.0f,0.0f));//定义三通道彩色图,数据类型为32位浮点型

先定义,再初始化:

cv::Matsrc;src.create(800,640,CV_8UC1);img.setTo(cv::Scalar(0));cv::Matsrc(800,640,CV_8UC3);src.setTo(cv::Scalar(255,0,0));引用定义(内存相同)cv::Matdst(src);cv::Matdst=src;cv::Mat&dst=src;cv::Matroi(src,cv::Rect(0,0,200,100));复制定义(内存独立)

clone与copyTo:

cv::Matdst=src.clone();cv::Matdst;src.copyTo(dst);

构造同型矩阵:

cv::Matdst(src.size(),CV_8UC1,cv::Scalar(0));

独立提取ROI:

cv::Matroi=src(cv::Rect(0,0,200,100)).clone();cv::Rectroi_rect(0,0,200,100);cv::Matroi=src(roi_rect).clone();cv::Rectroi_rect(0,0,200,100);cv::Matroi;src(roi_rect).copyTo(roi);特殊定义

零矩阵:

cv::Matzeros=cv::Mat::zeros(100,100,CV_8UC1);

幺矩阵:

cv::Matones=cv::Mat::ones(100,100,CV_8UC1);

单位阵:

cv::Mateye=cv::Mat::eye(100,100,CV_8UC1);

特别注意:如果创建多通道数组,则只有第一通道被赋值,其余通道为全0.以下示例创建的是个蓝色图像,而不是纯白图像:

cv::Matblue=cv::Mat::ones(100,100,CV_8UC3)*255;模板定义

(待完善)

cv::Matm(constcv::Vec&vec,bool=copyData=true);cv::Mat(constcv::Matx&vec,boolcopyData=true);cv::Mat(conststd::vector&vec,boolcopyData=true);Mat矩阵的数据类型基本类型明确矩阵元素的数据类型,对于访问数组元素和元素运算至关重要,选错数据类型会产生错误结果,误导后续处理.一个有效的数据类型需要同时指明数据的类型和通道数,格式为CV_{8U,8S,16U,16S,32S,32F,64F}C{1,2,3}数值位数bits具体类型取值范围等同C++变量CV_8U8位无符号整数(0……255)uchar,unsignedcharCV_8S8位带符号整数(-128……127)charCV_16U16位无符号整数(0……65535)ushort,unsignedshort,unsignedshortintCV_16S16位带符号整数(-32768……32767)short,shortintCV_32S32位带符号整数(-2147483648……2147483647)int,longCV_32F32位单精度浮点数±(1.18e-38……3.40e38)floatCV_64F64位双精度浮点数±(2.23e-308……1.79e308)double注:CV_USRTYPE1supporthasbeendroppedinOpenCV4.0.如何获取未知矩阵的数据类型,最直接的方法是查阅接口文档,熟记常用变量的数据类型也可以通过成员函数type()获得Mat矩阵元素的数据类型,不建议使用depth()获取通道中的元素类型.但type()函数返回的是int型数值,需进一步查表,才能得到对应的数据类型.类型C1C2C3C4CV_8U081624CV_8S191725CV_16U2101826CV_16S3111927CV_32S4122028CV_32F5132129CV_64F6142230

提示:PNG格式的彩色图像除了BGR3个通道外,还有一个透明度通道,所以存在C4.示例:

cv::Matsrc=cv::Mat::ones(100,100,CV_8SC3);cout

Mat类型转换之int(阈值0

目录

1、方式一、利用 IplImage数据类型转换

2、利用 cvConvertScale进行阈值转换

3、将 IplImage转换成Mat类型

1、方式一、利用 IplImage数据类型转换

1、声明一个 IplImage指针*dst,并进行数据深度转换dst的数据部分在数值上与src的值一致,而其深度转换成了64F。 其中深度指的是每一个像素的位数(bits),在opencv的Mat.depth()中得到的是一个0–6的数字,分别代表不同的位数:enum{CV_8U=0,CV_8S=1,CV_16U=2,CV_16S=3,CV_32S=4,CV_32F=5,CV_64F=6};可见0和1都代表8位,2和3都代表16位,4和5代表32位,6代表64位。

//dst的数据部分在数值上与src的值一致,而其深度转换成了64F,实现由int类型转换到double。

 IplImage*dst=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_64F,3);//IplImage类型的*src中存储的是转换前的数据2、利用 cvConvertScale进行阈值转换

 //将输入图像的像素点double类型值域由0-255转换成0-1 

cvConvertScale(src,dst,1.0/255,0); 3、将 IplImage转换成Mat类型 dst_image=cv::cvarrToMat(dst);//dst_image存储转换后的Mat数据

方式二、利用Mat矩阵数据类型转换cv::convertTo函数实现

src.convertTo(src,CV_64FC3,1.0/225);src的数据类型是CV_8UC3

一般图像文件格式使用的是unsigned8bits,对应的整型数据类型有:CV_8UC1、CV_8UC2,CV_8UC3

其中,CV_8UC3表示3通道8位的unsignedchar型。

浮点数据类型说明:

float是32位,对应的CvMat数据结构类型是:CV_32FC1,CV_32FC2,CV_32FC3;其中,CV_32FC3表示32位的3通道float型 

double是64位,对应的CvMat数据结构类型是:CV_64FC1,CV_64FC2,CV_64FC3;其中,CV_64FC3表示64位的3通道double型。

转载请注明:Allen101zhang的CSDN博客 Mat类型转换之int(阈值0-255)转double(阈值0-1)类型OpenCV实现_拾光夕拾的博客-CSDN博客_opencvmat0-255

关注公众号“拾光夕拾”,回复“1024”即可免费领取110本经典编程电子书。

opencv 图像类型(Mat、图像字节流、Bitmap、BITMAPINFO、CxImage、AVFrame)之间的转换

一、Mat与IplimageMatIplimage:直接赋值

IplImage*iplImg=cvLoadImage("greatwave.jpg",1);Matmtx(iplImg);//IplImage*->Mat共享数据//or:Matmtx=iplImg;cvReleaseImage(&iplImg);

Iplimage ---> CvvImage:用“Copyof”

CvvImagecImg;Iplimagemyimg;cImg.Copyof(myimg,-1);

Opencv2.2版本以上CvvImage类的使用,参考这篇文章Opencv2.2版本以上CvvImage类的使用-我自逍遥笑-博客园

二、Mat与图像数据

std::vectorMat2ImageData(constcv::Mat&img,std::stringimgType="jpg"){   std::vectorvecImgData;   std::vectorvecCompression_params;   vecCompression_params.push_back(CV_IMWRITE_JPEG_QUALITY);   vecCompression_params.push_back(100);   imgType="."+imgType;   cv::imencode(imgType,img,vecImgData,vecCompression_params);   returnvecImgData;}cv::MatImageData2Mat(std::vectorvecImageData){   cv::Matimg;   img=cv::imdecode(vecImageData,CV_LOAD_IMAGE_COLOR);   returnimg;}

三、Mat转Bitmap

//获取图片宽度。绘制图片时,一定要保证Mat图片符合window图片要求(即每行字节数为4的倍数),如果不满足则要进行适当的转化,否则画出的图像会出现问题(图像不是标准图像,反而是斜的)。intGetSuiteableWidth(constintprewidth){   intnwidth=0;   intnremainder=prewidth%4;   if(nremainder==0)   {      returnprewidth;//宽度pix   }   else   {      return(prewidth/4+1)*4;//宽度pix   }   return0;}voidFillBitmapInfo(BITMAPINFO*bmi,intwidth,intheight,intbpp,intorigin){   BITMAPINFOHEADER*bmih=&(bmi->bmiHeader);    memset(bmih,0,sizeof(*bmih));   bmih->biSize=sizeof(BITMAPINFOHEADER);//指定文件大小,包括这14个字节   /*32位的Windows操作系统处理4个字节(32位)的速度比较快,所以BMP的每一行颜色占用的字节数规定为4的整数倍。MyBmp.bmp中一行颜色有两个像素,共占用6字节,如果要补齐4*2=8字节,就要再加两个0字节。行补位的公式为:widthBytes=(width*biBitCount+31)/32*4*/   //width=(width*bpp+width)/32*4;   bmih->biWidth=GetSuiteableWidth(width);//宽度pix   bmih->biHeight=origin?abs(height):-abs(height);//高度 .bMP文件的数据从下到上,从左到右的。也就是说,从文件中最先读到的是图象最下面一行的左边第一个象素,然后是左边第二个象素……接下来是倒数第二行左边第一个象素,左边第二个象素……依次类推,最后得到的是最上面一行的最右一个象素。   bmih->biPlanes=1;//目标设备的级别,必须为1   bmih->biBitCount=(unsignedshort)bpp;//每个像素所需的位数,必须是1(双色),每个像素的位数   //1-黑白图,4-16色,8-256色,24-真彩色4(16色),8(256色)或24(真彩色)之一   bmih->biCompression=BI_RGB;//位图压缩类型,必须是0(不压缩),1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一//   bmih->biSizeImage=bmih->biHeight*8*height;   /*biSizeImage   指定实际的位图数据占用的字节数,其实也可以从以下的公式中计算出来:   biSizeImage=biWidth’×biHeight   要注意的是:上述公式中的biWidth’必须是4的整倍数(所以不是biWidth,而是biWidth’,   表示大于或等于biWidth的,最接近4的整倍数。举个例子,如果biWidth=240,则biWidth’=240;   如果biWidth=241,biWidth’=244)。*/}CBitmap*Mat2CBitmap(constcv::MatimgTmp){   HDChDC=this->GetDC()->GetSafeHdc();   ucharbuffer[sizeof(BITMAPINFOHEADER)+1024];   BITMAPINFO*bmi=(BITMAPINFO*)buffer;   intbmp_w=imgTmp.cols,bmp_h=imgTmp.rows;   intnchannels=imgTmp.channels();   intbpp=(imgTmp.depth()+1)*nchannels;   FillBitmapInfo(bmi,bmp_w,bmp_h,bpp*8,0);   /*   DWORDbiSizeImage;//位图的大小,以字节为单位   LONGbiXPelsPerMeter;//位图水平分辨率,每米像素数   LONGbiYPelsPerMeter;//位图垂直分辨率,每米像素数   DWORDbiClrUsed;//位图实际使用的颜色表中的颜色数   DWORDbiClrImportant;//位图显示过程中重要的颜色数72*8   */   char*pBits=NULL;   HBITMAPhBitmap=CreateDIBSection(hDC,bmi,DIB_RGB_COLORS,(void**)&pBits,NULL,0);   intpixelBytes=imgTmp.channels()*(imgTmp.depth()+1);//计算一个像素多少个字节      if(bmp_w%4==0)   {      memcpy(pBits,imgTmp.data,pixelBytes*bmp_w*bmp_h);   }   else   {      //原始图像宽度不是4的倍数,将实际图片数据一行一行拷贝过去       intntempW=GetSuiteableWidth(bmp_w);      for(size_ti=0;iAttach(hBitmap);   returnpBitmap;}

四、Mat转BITMAPINFO

voidMat2BITMAPINFO(constcv::Matimage,BITMAPINFO*imgInfo){   //根据图像通道数建立图像信息(这里假定图像像素为24与32位或者8位(有颜色表的类似))  if(image.channels()==3||image.channels()==4)  {    imgInfo=(BITMAPINFO*)newBYTE[sizeof(BITMAPINFOHEADER)];  }  else  //8位,有颜色表  {    imgInfo=(BITMAPINFO*)newBYTE[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)];    //颜色表赋值    for(inti(0);ibmiColors[i].rgbBlue=i;      imgInfo->bmiColors[i].rgbGreen=i;      imgInfo->bmiColors[i].rgbRed=i;      imgInfo->bmiColors[i].rgbReserved=0;    }  }  //头文件信息(注意由实际显示情况可得出图像原点显示在空间左下角)  imgInfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);  imgInfo->bmiHeader.biBitCount=8*image.channels();  imgInfo->bmiHeader.biHeight=-image.rows;  imgInfo->bmiHeader.biWidth=image.cols;  imgInfo->bmiHeader.biPlanes=1;  imgInfo->bmiHeader.biCompression=BI_RGB;  imgInfo->bmiHeader.biSizeImage=image.channels()*image.cols*image.rows;  imgInfo->bmiHeader.biXPelsPerMeter=0;  imgInfo->bmiHeader.biYPelsPerMeter=0;  imgInfo->bmiHeader.biClrUsed=0;  imgInfo->bmiHeader.biClrImportant=0;}//测试代码voidCPointMatchDlg::OnPaint(){  CDC*pDC;  pDC=GetDlgItem(IDC_MATCH_PICTURE_CONTROL)->GetDC();  CRecrimgCtrlRect;  GetDlgItem(IDC_MATCH_PICTURE_CONTROL)->GetClientRect(&imgCtrlRect);     pDC->SetStretchBltMode(COLORONCOLOR);  ::StretchDIBits(pDC->GetSafeHdc(),         0,0,         imgCtrlRect.Width(),m_imgCtrlRect.Height(),         0,0,         m_image.cols,m_image.rows,         m_image.data,         m_imgInfo,         DIB_RGB_COLORS,         SRCCOPY);  ReleaseDC(pDC);}

注意:这里绘制图片时,一定要保证Mat图片符合window图片要求(即每行字节数为4的倍数),如果不满足则要进行适当的转化,否则画出的图像会出现问题(图像不是标准图像,反而是斜的)。如果图片行字节数不是4的倍数,修改为如下语句:

cv::MattempImg= cv::imread("d:\test.jpeg",cv::IMREAD_UNCHANGED); m_image=cv::Mat::zeros(tempImg.rows,(tempImg.cols+3)/4*4,m_image.type()); //转化行字节数为4的倍数tempImage.copyTo(m_image(cv::Rect(0,0,tempImg.cols,tempImg.rows)));

五、Mat与CxImage

CxImageimg;img.Load("C:\f.jpg");uint8_t*buf=NULL;int32_tlen=0;boolrs=img.Encode(buf,len,CXIMAGE_FORMAT_BMP);cv::Mattemp2;vectorbuff2;buff2.resize(len);memcpy(&buff2[0],buf,len);temp2=cv::imdecode(buff2,1);delete[]buf;//要释放buf,这个buf在函数里分配了内存cv::imshow("111",temp2);cv::waitKey(); //toCximagevectorbuff;cv::imencode(".bmp",temp2,buff);CxImageimg2(&buff[0],buff.size(),CXIMAGE_FORMAT_BMP);img2.Blt(GetDlgItem(IDC_STATIC_P)->GetDC()->GetSafeHdc());

六、Mat与AVFrame

Mat是opencv的图像格式,颜色空间为BGR,对应FFmpeg格式为AV_PIX_FMT_BGR24。AVFrame一般为YUV420P,以此格式为例。这个通过FFmpeg的格式转换函数就可以解决。

extern"C"{#include"libavutil/avutil.h"#include"libavcodec/avcodec.h"#include"libavformat/avformat.h"#include"libswscale/swscale.h"#include}#include//AVFrame转cv::matcv::MatavframeToCvmat(constAVFrame*frame){intwidth=frame->width;intheight=frame->height;cv::Matimage(height,width,CV_8UC3);intcvLinesizes[1];cvLinesizes[0]=image.step1();SwsContext*conversion=sws_getContext(width,height,(AVPixelFormat)frame->format,width,height,AVPixelFormat::AV_PIX_FMT_BGR24,SWS_FAST_BILINEAR,NULL,NULL,NULL);sws_scale(conversion,frame->data,frame->linesize,0,height,&image.data,cvLinesizes);sws_freeContext(conversion);returnimage;}//cv::Mat转AVFrameAVFrame*cvmatToAvframe(cv::Mat*image,AVFrame*frame){intwidth=image->cols;intheight=image->rows;intcvLinesizes[1];cvLinesizes[0]=image->step1();if(frame==NULL){frame=av_frame_alloc();av_image_alloc(frame->data,frame->linesize,width,height,AVPixelFormat::AV_PIX_FMT_YUV420P,1);}SwsContext*conversion=sws_getContext(width,height,AVPixelFormat::AV_PIX_FMT_BGR24,width,height,(AVPixelFormat)frame->format,SWS_FAST_BILINEAR,NULL,NULL,NULL);sws_scale(conversion,&image->data,cvLinesizes,0,height,frame->data,frame->linesize);sws_freeContext(conversion);returnframe;}cv::MatavframeToCvmat2(AVFrame*yuv420Frame){//得到AVFrame信息intsrcW=yuv420Frame->width;intsrcH=yuv420Frame->height;SwsContext*swsCtx=sws_getContext(srcW,srcH,(AVPixelFormat)yuv420Frame->format,srcW,srcH,(AVPixelFormat)AV_PIX_FMT_BGR24,SWS_BICUBIC,NULL,NULL,NULL);//生成Mat对象cv::Matmat;mat.create(cv::Size(srcW,srcH),CV_8UC3);//格式转换,直接填充Mat的数据dataAVFrame*bgr24Frame=av_frame_alloc();av_image_fill_arrays(bgr24Frame->data,bgr24Frame->linesize,(uint8_t*)mat.data,(AVPixelFormat)AV_PIX_FMT_BGR24,srcW,srcH,1);sws_scale(swsCtx,(constuint8_t*const*)yuv420Frame->data,yuv420Frame->linesize,0,srcH,bgr24Frame->data,bgr24Frame->linesize);//释放av_frame_free(bgr24Frame);sws_freeContext(swsCtx);returnmat;}AVFrame*cvmatToAvframe2(cv::Mat&inMat){//得到Mat信息AVPixelFormatdstFormat=AV_PIX_FMT_YUV420P;intwidth=inMat.cols;intheight=inMat.rows;//创建AVFrame填充参数注:调用者释放该frameAVFrame*frame=av_frame_alloc();frame->width=width;frame->height=height;frame->format=dstFormat;//初始化AVFrame内部空间intret=av_frame_get_buffer(frame,32);if(retdata[2],data+frame_size*5/4,frame_size/4);returnframe;}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。

上一篇

下一篇