1.传统的lplImage * -------> Mat格式
IplImage* img = cvLoadImage("greatwave.png", 1);
Mat mtx(img); // IplImage* ->Mat 共享数据
2、Mat -----> IplImage:
(1)将Mat类型转换到 IplImage *类型
Mat image1;
IplImage *image2 = (&(IplImage)image1); //同样只是创建图像头,而没有复制数据。
cvsaveimage("c:\image2.jpg",image2);//保存下来
(2)将Mat类型转换到 IplImage类型
只是创建图像头,而没有复制数据。
例:
IplImage ipl_img = img; // Mat -> IplImage
3、将CvMat类型转换为Mat类型
与IplImage的转换类似,可以选择是否复制数据。
Mat b = Mat(const CvMat* a, true);
//使用Mat的构造函数:Mat::Mat(const CvMat* m, bool copyData=false); 默认情况下copyData为false
CvMat* a;
//注意:以下三种效果一致,均为浅拷贝
Mat b(a); //a "copy" to b
Mat b(a, false); //a "copy" to b
Mat b = a; //a "copy" to b
//注意:当将参数copyData设为true后,则为深拷贝(复制整个图像数据)
Mat b = Mat(a, true); //a copy to b
4、将Mat类型转换为CvMat类型
与IplImage的转换类似,不复制数据,只创建矩阵头。
例:// 假设Mat类型的imgMat图像数据存在
CvMat cvMat = imgMat; // Mat -> CvMat
//注意:浅拷贝
Mat a;
CvMat b = a; //a "copy" to b
//注意:深拷贝
Mat a;
CvMat *b;
CvMat temp = a; //转化为CvMat类型,而不是复制数据
cvCopy(&temp, b); //真正复制数据 cvCopy使用前要先开辟内存空间
Mat之间的复制
//注意:浅拷贝 - 不复制数据只创建矩阵头,数据共享(更改a,b,c的任意一个都会对另外2个产生同样的作用)
Mat a;
Mat b = a; //a "copy" to b
Mat c(a); //a "copy" to c
//注意:深拷贝
Mat a;
Mat b = a.clone(); //a copy to b
Mat c;
a.copyTo(c); //a copy to c
CvMat之间的复制
//注意:深拷贝 - 单独分配空间,两者相互独立
CvMat* a;
CvMat* b = cvCloneMat(a); //copy a to b
5、 (1)IplImage转Cvmat
IplImage* src = cvLoadImage("rice.bmp",0);
CvMat* mat=cvCreateMat(src->height,src->width,CV_32SC1);
cvConvert(src,mat);
或者:Cvmat matObj;
* mat=cvGetmat(src,&matObj);
(2)Cvmat转IplImage
IplImage*
pImg = cvCreateImage(cvGetSize(mat),8,1);
cvGetImage(matI,pImg);
cvSaveImage("rice1.bmp",pImg);
4.1 IplImage与IplImage*
IplImage* imgTemp = cvCreateImage(cvSize(s_size, s_size), 8, 3);
IplImage temp = imgRGB.rowRange(rangeL, rangeR).colRange(valL, valR);
cvResize(&temp, imgTemp);
5、CxImage 开源库与Opencv (Mat)互转
CxImage img;
img.Load(
"C:\f.jpg"
);
uint8_t *buf=NULL;
int32_t
len=0;
bool
rs =img.Encode(buf,len,CXIMAGE_FORMAT_BMP);
cv::Mat temp2;
vector<uchar> buff2;
buff2.resize(len);
memcpy
(&buff2[0],buf,len);
temp2= cv::imdecode(buff2,1);
delete []buf; //要释放buf,这个buf在函数里分配了内存
cv::imshow(
"111"
,temp2);
cv::waitKey();
vector<uchar> buff;
cv::imencode(
".bmp"
,temp2,buff);
CxImage img2(&buff[0],buff.size(),CXIMAGE_FORMAT_BMP);
img2.Blt(GetDlgItem(IDC_STATIC_P)->GetDC()->GetSafeHdc());
6、OpenCV2CXimage.h
-
#pragma once
-
-
-
-
-
-
#include <stdio.h>
-
#include "h/ximage.h"
-
#include <opencv2/opencv.hpp>
-
#pragma comment(lib,"lib/cximage.lib")
-
#pragma comment(lib,"lib/Jpeg.lib")
-
#pragma comment(lib,"lib/libpsd.lib")
-
#pragma comment(lib,"lib/png.lib")
-
#pragma comment(lib,"lib/zlib.lib")
-
#pragma comment(lib,"lib/tiff.lib")
-
#pragma comment(lib,"lib/jasper.lib")
-
#pragma comment(lib,"lib/libdcr.lib")
-
#pragma comment(lib,"lib/jbig.lib")
-
#pragma comment(lib,"lib/mng.lib")
-
-
using namespace cv;
-
using namespace std;
-
-
#include <opencv2/opencv.hpp>
-
-
#ifdef _DEBUG
-
#pragma comment(lib, "opencv_core249d.lib")
-
#pragma comment(lib, "opencv_highgui249d.lib")
-
#pragma comment(lib, "opencv_imgproc249d.lib")
-
#else
-
#pragma comment(lib, "opencv_core249.lib")
-
#pragma comment(lib, "opencv_highgui249.lib")
-
#pragma comment(lib, "opencv_imgproc249.lib")
-
#endif
-
-
class OpenCV2CXimage
-
{
-
public:
-
OpenCV2CXimage(void);
-
~OpenCV2CXimage(void);
-
-
-
-
-
-
-
static int OpenCV2CXimage::GetBlackColor(CxImage cxImage);
-
-
-
-
-
-
-
static int OpenCV2CXimage::GetWhiteColor(CxImage cxImage);
-
-
-
-
-
-
-
bool Cximage2IplImage(CxImage *src,IplImage **dst);
-
-
-
-
-
-
-
bool IplImage2Cximage(IplImage *src,CxImage *dst,long nBpp=8);
-
-
-
-
-
-
-
bool CxImageFormatConvert(CxImage *src,CxImage *dst,long imagetype = CXIMAGE_FORMAT_BMP);
-
-
protected:
-
RGBQUAD *m_pPal;
-
int m_nPalatteCount;
-
};
OpenCV2CXimage.cpp
-
#include "StdAfx.h"
-
#include "OpenCV2CXimage.h"
-
#include <map>
-
using namespace std;
-
-
OpenCV2CXimage::OpenCV2CXimage(void)
-
{
-
m_pPal = NULL;
-
m_nPalatteCount = 0;
-
}
-
-
OpenCV2CXimage::~OpenCV2CXimage(void)
-
{
-
if(m_pPal!=NULL)
-
{
-
delete []m_pPal;
-
m_pPal = NULL;
-
}
-
}
-
-
-
-
-
-
int OpenCV2CXimage::GetBlackColor(CxImage cxImage)
-
{
-
long i;
-
int iBlackFlag = 0;
-
RGBQUAD *pData = cxImage.GetPalette();
-
long nPaletteSize = cxImage.GetPaletteSize()/sizeof(RGBQUAD);
-
for(i=0;i<nPaletteSize;i++)
-
{
-
if(pData[i].rgbBlue==0 && pData[i].rgbGreen==0 && pData[i].rgbRed==0)
-
{
-
iBlackFlag = i;
-
break;
-
}
-
}
-
return iBlackFlag;
-
}
-
-
-
-
-
-
int OpenCV2CXimage::GetWhiteColor(CxImage cxImage)
-
{
-
long i;
-
int iWhiteFlag = 255;
-
RGBQUAD *pData = cxImage.GetPalette();
-
long nPaletteSize = cxImage.GetPaletteSize()/sizeof(RGBQUAD);
-
for(i=0;i<nPaletteSize;i++)
-
{
-
if(pData[i].rgbBlue==255 && pData[i].rgbGreen==255 && pData[i].rgbRed==255)
-
{
-
iWhiteFlag = i;
-
break;
-
}
-
}
-
return iWhiteFlag;
-
}
-
-
-
-
-
-
-
bool OpenCV2CXimage::Cximage2IplImage(CxImage *src,IplImage **dst)
-
{
-
bool bRet = true;
-
if(!src || !src->IsValid())
-
{
-
bRet = false;
-
return bRet;
-
}
-
m_nPalatteCount = src->GetPaletteSize()/sizeof(RGBQUAD);;
-
m_pPal = src->GetPalette();
-
int iBackColor = GetBlackColor(*src);
-
long i = 0,j = 0;
-
long nImageWidth = 0,nImageHeight = 0;
-
nImageWidth = src->GetWidth();
-
nImageHeight = src->GetHeight();
-
long nBitCunt = src->GetBpp();
-
if(nBitCunt<=1)
-
{
-
*dst = cvCreateImage(cvSize(nImageWidth,nImageHeight),IPL_DEPTH_8U,1);
-
cvZero(*dst);
-
-
for(j=0;j<nImageHeight;j++)
-
{
-
for(i=0;i<nImageWidth;i++)
-
{
-
if(src->GetPixelIndex(i,j)==iBackColor)
-
{
-
CV_IMAGE_ELEM(*dst,uchar,nImageHeight-1-j,i) = 0;
-
}
-
else
-
{
-
CV_IMAGE_ELEM(*dst,uchar,nImageHeight-1-j,i) = 255;
-
}
-
}
-
}
-
}
-
else if(nBitCunt<=8)
-
{
-
*dst = cvCreateImage(cvSize(nImageWidth,nImageHeight),IPL_DEPTH_8U,1);
-
cvZero(*dst);
-
-
map<int,int> mapPalatte;
-
RGBQUAD szSystemPal[256];
-
int k = 0;
-
for(k=0;k<256;k++)
-
{
-
szSystemPal[k].rgbBlue = k;
-
szSystemPal[k].rgbGreen = k;
-
szSystemPal[k].rgbRed = k;
-
szSystemPal[k].rgbReserved = 0;
-
}
-
int m = 0;
-
for(m=0;m<m_nPalatteCount;m++)
-
{
-
for(k=0;k<256;k++)
-
{
-
if(m_pPal[m].rgbBlue==szSystemPal[k].rgbBlue && m_pPal[m].rgbGreen==szSystemPal[k].rgbGreen && m_pPal[m].rgbRed==szSystemPal[k].rgbRed)
-
{
-
mapPalatte.insert(make_pair(m,k));
-
break;
-
}
-
}
-
}
-
-
-
-
map<int,int>::iterator iter;
-
BYTE btIndex = 0;
-
for(j=0;j<nImageHeight;j++)
-
{
-
for(i=0;i<nImageWidth;i++)
-
{
-
btIndex = src->GetPixelIndex(i,j);
-
iter = mapPalatte.find(btIndex);
-
if(iter!=mapPalatte.end())
-
{
-
btIndex = iter->second;
-
}
-
CV_IMAGE_ELEM(*dst,uchar,nImageHeight-1-j,i) = btIndex;
-
}
-
}
-
}
-
else if(nBitCunt<=16)
-
{
-
*dst = cvCreateImage(cvSize(nImageWidth,nImageHeight),IPL_DEPTH_16U,1);
-
(*dst)->origin = 1;
-
cvZero(*dst);
-
-
for(j=0;j<nImageHeight;j++)
-
{
-
for(i=0;i<nImageWidth;i++)
-
{
-
BYTE *pSrc = src->GetBits(j) + 2*i;
-
CV_IMAGE_ELEM(*dst,ushort,j,i) = (*pSrc) + (*(pSrc+1))*256;
-
}
-
}
-
}
-
else
-
{
-
*dst = cvCreateImage(cvSize(nImageWidth,nImageHeight),IPL_DEPTH_8U,3);
-
(*dst)->origin = 1;
-
cvZero(*dst);
-
-
memcpy((*dst)->imageData,src->GetBits(0),src->GetSize());
-
}
-
return bRet;
-
}
-
-
-
-
-
-
-
bool OpenCV2CXimage::IplImage2Cximage(IplImage *src,CxImage *dst,long nBpp)
-
{
-
bool bRet = true;
-
if(src==NULL || dst==NULL)
-
{
-
return false;
-
}
-
if(!(nBpp==1 || nBpp==8 || nBpp==24))
-
{
-
return false;
-
}
-
long i = 0,j = 0;
-
CvSize csImageSize = cvGetSize(src);
-
CxImage ciTmp;
-
ciTmp.Create(csImageSize.width,csImageSize.height,src->depth,CXIMAGE_FORMAT_BMP);
-
if(src->depth== IPL_DEPTH_8U)
-
{
-
ciTmp.SetStdPalette();
-
BYTE gray = 0;
-
for(j=0;j<csImageSize.height;j++)
-
{
-
for(i=0;i<csImageSize.width;i++)
-
{
-
gray = CV_IMAGE_ELEM(src,uchar,csImageSize.height-1-j,i);
-
-
COLORREF color = 0;
-
color |= gray;
-
color |= gray << 8;
-
color |= gray << 16;
-
ciTmp.SetPixelColor(i,j,color);
-
}
-
}
-
}
-
else
-
{
-
-
memcpy(ciTmp.GetBits(0),src->imageData,src->imageSize);
-
}
-
-
-
dst->Create(csImageSize.width,csImageSize.height,nBpp,CXIMAGE_FORMAT_BMP);
-
if(nBpp==ciTmp.GetBpp())
-
{
-
dst->Copy(ciTmp);
-
dst->Save("dst.bmp",CXIMAGE_FORMAT_BMP);
-
}
-
else
-
{
-
if(nBpp==1)
-
{
-
-
map<int,int> mapPalatte;
-
RGBQUAD szSystemPal[256];
-
int k = 0;
-
for(k=0;k<256;k++)
-
{
-
szSystemPal[k].rgbBlue = k;
-
szSystemPal[k].rgbGreen = k;
-
szSystemPal[k].rgbRed = k;
-
szSystemPal[k].rgbReserved = 0;
-
}
-
int m = 0;
-
for(k=0;k<256;k++)
-
{
-
for(m=0;m<m_nPalatteCount;m++)
-
{
-
if(m_pPal[m].rgbBlue==szSystemPal[k].rgbBlue && m_pPal[m].rgbGreen==szSystemPal[k].rgbGreen && m_pPal[m].rgbRed==szSystemPal[k].rgbRed)
-
{
-
mapPalatte.insert(make_pair(k,m));
-
break;
-
}
-
}
-
}
-
-
byte btValue = 0;
-
map<int,int>::iterator iter;
-
long nImageWidth = 0;
-
long nImageHeight = 0;
-
if(ciTmp.GetBpp()>8)
-
{
-
ciTmp.GrayScale();
-
}
-
if(m_nPalatteCount==2)
-
{
-
dst->SetPalette(m_pPal,m_nPalatteCount);
-
btValue = 0;
-
nImageWidth = ciTmp.GetWidth();
-
nImageHeight = ciTmp.GetHeight();
-
for(j=0;j<nImageHeight;j++)
-
{
-
for(i=0;i<nImageWidth;i++)
-
{
-
btValue = ciTmp.GetPixelIndex(i,j);
-
iter = mapPalatte.find(btValue);
-
if(iter!=mapPalatte.end())
-
{
-
btValue = iter->second;
-
}
-
dst->SetPixelIndex(i,j,btValue);
-
}
-
}
-
}
-
else
-
{
-
ciTmp.Threshold(128);
-
dst->Copy(ciTmp);
-
}
-
}
-
else if(nBpp==8)
-
{
-
-
map<int,int> mapPalatte;
-
RGBQUAD szSystemPal[256];
-
int k = 0;
-
for(k=0;k<256;k++)
-
{
-
szSystemPal[k].rgbBlue = k;
-
szSystemPal[k].rgbGreen = k;
-
szSystemPal[k].rgbRed = k;
-
szSystemPal[k].rgbReserved = 0;
-
}
-
int m = 0;
-
for(k=0;k<256;k++)
-
{
-
for(m=0;m<m_nPalatteCount;m++)
-
{
-
if(m_pPal[m].rgbBlue==szSystemPal[k].rgbBlue && m_pPal[m].rgbGreen==szSystemPal[k].rgbGreen && m_pPal[m].rgbRed==szSystemPal[k].rgbRed)
-
{
-
mapPalatte.insert(make_pair(k,m));
-
break;
-
}
-
}
-
}
-
-
byte btValue = 0;
-
map<int,int>::iterator iter;
-
long nImageWidth = 0;
-
long nImageHeight = 0;
-
if(ciTmp.GetBpp()!=8)
-
{
-
ciTmp.GrayScale();
-
}
-
if(m_nPalatteCount==8)
-
{
-
dst->SetPalette(m_pPal,m_nPalatteCount);
-
btValue = 0;
-
nImageWidth = ciTmp.GetWidth();
-
nImageHeight = ciTmp.GetHeight();
-
for(j=0;j<nImageHeight;j++)
-
{
-
for(i=0;i<nImageWidth;i++)
-
{
-
btValue = ciTmp.GetPixelIndex(i,j);
-
iter = mapPalatte.find(btValue);
-
if(iter!=mapPalatte.end())
-
{
-
btValue = iter->second;
-
}
-
dst->SetPixelIndex(i,j,btValue);
-
}
-
}
-
}
-
else
-
{
-
dst->Copy(ciTmp);
-
}
-
}
-
else
-
{
-
if(ciTmp.GetBpp()==24)
-
{
-
dst->Copy(ciTmp);
-
}
-
else
-
{
-
byte btValue = 0;
-
COLORREF clValue;
-
map<int,int>::iterator iter;
-
long nImageWidth = 0;
-
long nImageHeight = 0;
-
bRet = ciTmp.IncreaseBpp(24);
-
dst->Copy(ciTmp);
-
}
-
}
-
}
-
return bRet;
-
}
-
-
-
bool OpenCV2CXimage::CxImageFormatConvert(CxImage *src,CxImage *dst,long imagetype)
-
{
-
bool bRet = true;
-
if(src==NULL || dst==NULL)
-
{
-
return false;
-
}
-
if(!(imagetype>0 && imagetype<=19))
-
{
-
return false;
-
}
-
if(src->GetType()==imagetype)
-
{
-
dst->Copy(*src);
-
}
-
else
-
{
-
dst->Create(src->GetWidth(),src->GetHeight(),src->GetBpp(),imagetype);
-
src->SetType(imagetype);
-
dst->Copy(*src);
-
}
-
return true;
-
}
main函数:
-
-
-
-
#include "stdafx.h"
-
#include "OpenCV2CXimage.h"
-
-
int _tmain(int argc, _TCHAR* argv[])
-
{
-
-
-
IplImage *img;
-
OpenCV2CXimage o2i;
-
CxImage cimg("gimg.bmp",CXIMAGE_FORMAT_BMP);
-
CxImage *cimg1 = new CxImage();
-
cimg1->Load("gimg.bmp",CXIMAGE_FORMAT_BMP);
-
o2i.Cximage2IplImage(cimg1 ,&img);
-
cvSaveImage("img.jpg",img);
-
-
-
-
-
CxImage *cimg2 = new CxImage();
-
IplImage *img1;
-
img1=cvLoadImage("gimg.bmp",0);
-
o2i.IplImage2Cximage(img1,cimg2,8);
-
cimg2->Save("test2.bmp",CXIMAGE_FORMAT_BMP);
-
-
-
CxImage im1,im2,im3;
-
int h1,w1,h2,w2,h3,w3,bpp;
-
im1.Load("E:\2.jpg");
-
im2.Load("E:\1.jpg");
-
h1=im1.GetHeight();
-
w1=im1.GetWidth();
-
h2=im2.GetHeight();
-
w2=im2.GetWidth();
-
h3=h1;
-
w3=w1+w2;
-
bpp=im1.GetBpp();
-
im3.Create(w3,h3,bpp);
-
im3.MixFrom(im1,0,0);
-
im3.MixFrom(im2,w1,0);
-
im3.Save("e:\3.jpg",CXIMAGE_FORMAT_JPG);
-
-
-
CxImage imagesy;
-
if( !imagesy.Load("E:\1.jpg", CXIMAGE_FORMAT_JPG))
-
{
-
return TRUE;
-
}
-
if (imagesy.IsValid())
-
{
-
CxImage::CXTEXTINFO textword;
-
imagesy.InitTextInfo( &textword );
-
-
_stprintf( textword.lfont.lfFaceName, _T("Times New Roman"));
-
textword.lfont.lfCharSet = GB2312_CHARSET ;
-
textword.lfont.lfWeight = 8 ;
-
textword.lfont.lfItalic = 0 ;
-
textword.lfont.lfUnderline = 0 ;
-
textword.fcolor = RGB( 255,255,160 );
-
textword.bcolor = RGB( 0, 80,160 );
-
textword.opaque = 1;
-
textword.b_opacity = (float)(0)/(float)200.;
-
textword.b_round = (BYTE) 10 ;
-
textword.smooth = (BYTE)1;
-
_stprintf( textword.text, _T("水印文字") );
-
-
imagesy.DrawStringEx(0,0,100,&textword);
-
-
imagesy.Save("e:\z2_sy.jpg",CXIMAGE_FORMAT_JPG);
-
}
-
return 0;
一.Mat基础(如果加了using namespace cv ,以下的cv:: 都可以省略)
在计算机内存中,数字图像是已矩阵的形式保存的。OpenCV2中,数据结构Mat是保存图像像素信息的矩阵,它主要包含两部分:矩阵头和一个指向像素数据的矩阵指针。
矩阵头主要包含,矩阵尺寸、存储方法、存储地址和引用次数等。
矩阵头的大小是一个常数,不会随着图像的大小而改变,但是保存图像像素数据的矩阵则会随着图像的大小而改变,通常数据量会很大,比矩阵头大几个数量级。这样,在图像复制和传递过程中,主要的开销是由存放图像像素的矩阵而引起的。因此,OpenCV使用了引用次数,当进行图像复制和传递时,不再复制整个Mat数据,而只是复制矩阵头和指向像素矩阵的指针。例如:
cv::Mat a ;
a = cv::imread( "f:\psb.jpg" );
cv::Mat b = a ;
|
上面的a,b有各自的矩阵头,但是其矩阵指针指向同一个矩阵,也就是其中任何一个改变了矩阵数据都会影响另外一个。
那么,多个Mat共用一个矩阵数据,最后谁来释放矩阵数据呢?
这就是引用计数的作用,当Mat对象每被复制一次时,就会将引用计数加1,而每销毁一个Mat对象(共用同一个矩阵数据)时引用计数会被减1,当引用计数为0时,矩阵数据会被清理。
上图是Mat对象a,b共用一个矩阵,故其引用计数refcount为2.
但是有些时候仍然会需要复制矩阵数据本身(不只是矩阵头和矩阵指针),这时候可以使用clone 和copyTo方法。
cv::Mat c = a.clone();
cv::Mat d ;
a.copyTo(d);
上面代码中的c,d各自拥有自己的矩阵,改变自己的矩阵数据不会相互影响。
在使用Mat中,需要记住:
- OpenCV中的内存分配是自动完成的(不是特别指定的话)
- 使用OpenCV的C++ 接口时不需要考虑内存释放问题
- Mat的赋值运算和拷贝构造函数只会拷贝矩阵头,仍然共同同一个矩阵
- 如果要复制矩阵数据,可以使用clone和copyTo函数
2.Mat存储方法
Mat中矩阵的每个元素可以使用不同的数据类型,最小的数据类型是char,占用一个字节或者8位,可以是有符号的(0到255)或者是无符号的(-127到127)。在RGB颜色空间中,使用三个char类型可以表示1600万中颜色,但在图像处理的过程中有可能会使用到float或者double来表示图像的像素。
Mat的创建
cv::Mat img(2,2,CV_8UC3,cv::Scalar(0,0,255));
上述代码创建了一个2行2列的矩阵,矩阵元素使用8位无符号char类型保存,具有3通道,每个像素的初始值是(0,0,255)
构造函数的前两个参数指定了矩阵的行和列
第三个参数指定矩阵元素的数据类型以及通道数,
四部分分别指定:元素的大小,是有符号还是无符号,数据类型以及通道数
最后一个参数,Scalar是short型的vector,提供矩阵的初始化。
Create方法
该方法不能为矩阵设置初始值,只是在改变尺寸时为矩阵数据重新分配内存。使用方法:
img.create(4,4,CV_8UC(2));
创建了一个4行4列有2个通道的矩阵
MATLAB形式的初始化
cv::Mat e = cv::Mat::eye(4,4,CV_64F);
cv::Mat z = cv::Mat::ones(2,2,CV_32F);
cv::Mat o = cv::Mat::zeros(3,3,CV_8UC1);
Mat e是4行4列的对角矩阵
Mat z是2行2列的单位矩阵
Mat o是3行3列的零矩阵
小矩阵的初始化
对于小矩阵可以使用逗号分割的初始化函数
Mat c =(Mat_<double>(3,3)<<1,2,3,0,-1,0,4,5,6);
3.Mat的输入输出
使用imread函数,向Mat对象中写入一个图像。
a = cv::imread("f:\psb.jpg");//读入图像
imread的原型如下
cv::Mat imread(const string& filename,int flags=1)
filename指定要读取图像的位置
flags指定图像的颜色空间
flags > 0 3通道的彩色图像
flags = 0 灰度图像
flags < 0 不作改变
也可以有以下的枚举值
CV_LOAD_IMAGE_ANYDEPTH、CV_LOAD_IMAGE_COLOR、CV_LOAD_IMAGE_GRAYSCALE
使用imwrite函数,将Mat对象保存到指定的文件中。
imwrite的函数原型如下:
bool imwrite(const string& filename,InputArray img,constvector<int>& params=vector<int>())
filename,指定的文件
img 要保存的Mat对象
params 用来指定图像的保存编码方式。
使用filename的扩展名来指定图像的保存格式(.jpg .png .bmp),对于不同的图像保存类型,params是不同的值
- JPEG,params用来指定图像的质量(0到100),默认的是95. CV_IMWRITE_JPEG_QUALITY
- PNG,params用来指定图像的压缩级别(0到9),压缩级别越高图像占用的空间越小,保存图像所用的时间越久。默认值是3. CV_IMWRITE_PNG_COMPRESSION
- PPM,PGM,PBM,params是一个标记(0或者1),默认的是1.CV_IMWRITE_PXM_BINARY
imwrite只能保存8位(或者是16位无符号(CV_16UC)的PNG,JPEG200或者TIFF图像)单通道或者三通道的图像,如果要保存的不是这样的图片,可以使用convertTo或者cvtColor来进行转变。
下面代码展示了如果使用imwrite向文件中写入一个4通道的png图像
-
#include <iostream>
-
#include <opencv2/core/core.hpp>
-
#include <opencv2/highgui/highgui.hpp>
-
-
using namespace std;
-
using namespace cv;
-
-
Mat src;
-
Mat image;
-
string str = "./";
-
-
/*创建alpha表,整体偏红色,左上角到右下角呈现从完全透明到完全不透明变化趋势*/
-
void createAlphaMat(Mat &mat)
-
{
-
for (int i = 0; i < mat.rows; ++i) {
-
for (int j = 0; j < mat.cols; ++j) {
-
Vec4b& rgba = mat.at<Vec4b>(i, j);
-
rgba[0] = UCHAR_MAX; //r分量一直最大,所以整体偏红
-
rgba[1] = saturate_cast<uchar>((float (mat.cols - j)) / ((float)mat.cols) * UCHAR_MAX);
-
rgba[2] = saturate_cast<uchar>((float (mat.rows - i)) / ((float)mat.rows) * UCHAR_MAX);
-
rgba[3] = saturate_cast<uchar>(0.5 * (rgba[1] + rgba[2]));
-
}
-
}
-
}
-
-
int main()
-
{
-
/*采用默认参数进行图片的保存*/
-
src = imread("test.jpg");
-
imwrite(str+"原图.jpg", src); //c版本中的保存图片为cvSaveImage()函数,c++版本中直接与matlab的相似,imwrite()函数。
-
imshow("src", src);
-
Rect rect(src.cols/4, src.rows/4, src.cols/2, src.rows/2);
-
image = src(rect);
-
imwrite(str+"截取原图中的一部分区域小图.jpg", image);
-
imshow("image", image);
-
-
/*采用自己设置的参数来保存图片*/
-
Mat mat(480, 640, CV_8UC4);
-
createAlphaMat(mat);
-
vector<int> compression_params;
-
compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
-
compression_params.push_back(9); //png格式下,默认的参数为3.
-
try {
-
imwrite("alpha.png", mat, compression_params);
-
}
-
catch (runtime_error& ex) {
-
fprintf(stderr, "Exception converting image to PNG format: %s
", ex.what());
-
return 1;
-
}
-
fprintf(stdout, "Saved PNG file with alpha data.
");
-
-
waitKey(0);
-
return 0;
-
}
生成的alpha表图像显示如下:
OpenCV提供了用以窗口的形式显示图片的方法,代码如下:
-
Mat img = imread("f:psb.jpg");
-
const string name ="Hu";
-
namedWindow(name);
-
imshow(name,img);
-
waitKey();
Mat矩阵中数据元素的地址计算公式:
addr(Mi0,i1,…im-1) = M.data + M.step[0] * i0 + M.step[1] * i1 + … + M.step[m-1] * im-1 。
其中 m = M.dims 是指M的维度
i. data:Mat对象中的一个指针,指向内存中存放矩阵数据的一块内存 (uchar* data).
ii. row: 行;col:列;rows:行数;cols:列数。
iii. dims :Mat所代表的矩阵的维度,如 3 * 4 的矩阵为 2 维,3 * 4 * 5 的为3维.
iv. channels:通道,矩阵中的每一个矩阵元素拥有的值的个数,比如说 3 * 4 矩阵中一共 12 个元素,如果每个元素有三个值,那么就说这个矩阵是 3 通道的,即 channels = 3。常见的是一张彩色图片有红、绿、蓝三个通道。但是opencv用imread(opencv读图的函数)读进来的图像,三通道存放顺序为B、G、R。
v. depth:深度,即每一个像素的位数(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位;
vi. step:是一个数组,定义了矩阵的布局,具体见下面图片分析,另外注意 step1 (step / elemSize1),M.step[m-1] 总是等于 elemSize,M.step1(i)返回的是第i维的步长,因此M.step1(m-1)总是等于 channels,m是M的维度;这里是解释步长step[k]的,步长也可以看作是与第k维的存储单位,在2维的矩阵中,因为存储是按照行的顺序存储的,整个矩阵存储为一个平面,所以第k=0维的步长也就是单位肯定就是一行所占的字节数;如果是3维的话,第0维是按照面为单位来存储的,第1维是按照行为单位来存储的,第2维是按照元素类型为单位存储的,每个元素类型是基本类型(即uchar,float,short等等)与通道数的乘积...;也就是基本数据类型与通道数组成元素,多个元素组成了行,多行组成了面,多个面组成了3维体,多个3维体 组成4维超体。。。以此类推,如此看来某一维的步长应该等于高一维的步长step*低一维的大小size 。
vii. elemSize : 矩阵中每一个元素的数据大小,如果是n通道,就是(n*数据类型)。如果Mat中的数据的数据类型是 CV_8U 那么 elemSize = 1,CV_8UC3 那么 elemSize = 3,CV_16UC2 那么 elemSize = 4;记住另外有个 elemSize1 表示的是矩阵中数据类型的大小,即 elemSize / channels 的大小。
像素位深度是指每个像素所用的位数(bit),像素位深度决定了彩色图像的每个像素可能有的颜色数,或者确定灰度图像的每个像素可能有的灰度级数。例如,一幅彩色图像的每个像素用R、G、B三个分量来表示,若每个分量用8位,那么一个像素共用24位表示,就说像素的深度为24位,每个像素可以是224,即16777216〔千万级〕种颜色中的一种。在这个意义上, 往往把像素的位深度说成是图像深度。表示一个像素的位数越多,它能表达的颜色数目就越多, 而它的深度就越深。虽然像素位深度或图像深度可以很深,但由于设备本身的限制,加上人眼自身分辨率的局限,一般情况下,一味追求特别深的像素深度没有意义。因为,像素深度越深,数据量越大,所需要的传输带宽及存储空间就越大。相反,如果像素深度太浅,会影响图像的质量,图像看起来让人觉得很粗糙而不自然。
提示:假如像素位深度是8(bit),那么以虚线框中4个像素点而言,以4 :2:0格式为例,釆样总共为6个采样点(4个亮度分量加2个色度分量),总共需要6×8=48比特,平均每个像素48/4=12比特,这就是为什么有些情况下4 :2:0采样格式也被称为“12比特每像素采样”的原因。