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;
boolrs =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\n", ex.what());  
- 
        return 1;  
- 
    }  
- 
    fprintf(stdout, "Saved PNG file with alpha data.\n");  
- 
  
- 
    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比特每像素采样”的原因。