【视频开发】CximageMat 、CximagelplImage 以及 lplImageMat的转换、像素位深度

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)互转

 //to 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();
 
//to Cximage
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

  1. #pragma once     
  2. /*  
  3. * 类说明:OpenCV图像与CXimage图像互转  
  4. * 用于OpenCV的图像与CXimage图像格式互转进行封装。 OpenCV的图像位数必须是大等于8的整数倍,支持BMP,JPG图像格式;CXimage的图像位数可以是1、2、4、8、、24,支持BMP,JPG,TIF,PNG,GIF图像格式。  
  5. */    
  6.   
  7. #include <stdio.h>  
  8. #include "h/ximage.h"     
  9. #include <opencv2/opencv.hpp>  
  10. #pragma comment(lib,"lib/cximage.lib")  
  11. #pragma comment(lib,"lib/Jpeg.lib")  
  12. #pragma comment(lib,"lib/libpsd.lib")  
  13. #pragma comment(lib,"lib/png.lib")  
  14. #pragma comment(lib,"lib/zlib.lib")  
  15. #pragma comment(lib,"lib/tiff.lib")  
  16. #pragma comment(lib,"lib/jasper.lib")  
  17. #pragma comment(lib,"lib/libdcr.lib")  
  18. #pragma comment(lib,"lib/jbig.lib")    
  19. #pragma comment(lib,"lib/mng.lib")    
  20.   
  21. using namespace cv;  
  22. using namespace std;    
  23.     
  24. #include <opencv2/opencv.hpp>  
  25.   
  26. #ifdef _DEBUG     
  27.     #pragma comment(lib, "opencv_core249d.lib")     
  28.     #pragma comment(lib, "opencv_highgui249d.lib")     
  29.     #pragma comment(lib, "opencv_imgproc249d.lib")     
  30. #else     
  31.     #pragma comment(lib, "opencv_core249.lib")     
  32.     #pragma comment(lib, "opencv_highgui249.lib")     
  33.     #pragma comment(lib, "opencv_imgproc249.lib")     
  34. #endif     
  35.     
  36. class OpenCV2CXimage    
  37. {    
  38. public:    
  39.     OpenCV2CXimage(void);    
  40.     ~OpenCV2CXimage(void);    
  41.     
  42.     /*  
  43.     功能说明: 获取黑点标记的方式  
  44.     参数说明:  cxImage 图像处理类  
  45.     返回值: 黑点标记  
  46.     */    
  47.     static int OpenCV2CXimage::GetBlackColor(CxImage cxImage);    
  48.     
  49.     /*  
  50.     功能说明: 获取白点标记的方式  
  51.     参数说明:  cxImage 图像处理类  
  52.     返回值: 黑点标记  
  53.     */    
  54.     static int OpenCV2CXimage::GetWhiteColor(CxImage cxImage);    
  55.     
  56.     /*  
  57.     *功能说明:转换Cximage到IplImage(注:由于IplImage结构不支持图像像数非8位格式,所以强制转换成8位整数倍)  
  58.     *参数说明:src,表示原始Cximage图像;dst,[out] 表示Opencv图像IplImage结构  
  59.     *返回值:bool类型。true,表示成功;flase,表示失败。  
  60.     */    
  61.     bool Cximage2IplImage(CxImage *src,IplImage **dst);    
  62.     
  63.     /*  
  64.     *功能说明:转换IplImage到Cximage  
  65.     *参数说明:src,表示Opencv图像IplImage结构;dst,[out] 表示输出Cximage图像;nBpp,表示输出Cximage图像位数占多少位[一个像数占多少位](1,8,24);  
  66.     *返回值:bool类型。true,表示成功;flase,表示失败。  
  67.     */    
  68.     bool IplImage2Cximage(IplImage *src,CxImage *dst,long nBpp=8);    
  69.     
  70.     /*  
  71.     *功能说明:图象格式转换  
  72.     *参数说明:src,表示输入Cximage图像;dst,[out] 表示输出Cximage图像;imagetype,表示图象类型  
  73.     *返回值:bool类型。true,表示成功;flase,表示失败。  
  74.     */    
  75.     bool CxImageFormatConvert(CxImage *src,CxImage *dst,long imagetype = CXIMAGE_FORMAT_BMP);    
  76.     
  77. protected:    
  78.     RGBQUAD *m_pPal;//调色版     
  79.     int m_nPalatteCount;    
  80. };    


OpenCV2CXimage.cpp


  1. #include "StdAfx.h"     
  2. #include "OpenCV2CXimage.h"     
  3. #include <map>     
  4. using namespace std;    
  5.     
  6. OpenCV2CXimage::OpenCV2CXimage(void)    
  7. {    
  8.     m_pPal = NULL;    
  9.     m_nPalatteCount = 0;    
  10. }    
  11.     
  12. OpenCV2CXimage::~OpenCV2CXimage(void)    
  13. {    
  14.     if(m_pPal!=NULL)    
  15.     {    
  16.         delete []m_pPal;    
  17.         m_pPal = NULL;    
  18.     }    
  19. }    
  20.     
  21. //函数名: GetBlackColor     
  22. //功能:  获取黑点标记的方式     
  23. //参数:  cxImage 图像处理类     
  24. //返回值: 黑点标记     
  25. int OpenCV2CXimage::GetBlackColor(CxImage cxImage)    
  26. {    
  27.     long i;    
  28.     int iBlackFlag = 0;    
  29.     RGBQUAD *pData = cxImage.GetPalette();    
  30.     long nPaletteSize = cxImage.GetPaletteSize()/sizeof(RGBQUAD);    
  31.     for(i=0;i<nPaletteSize;i++)    
  32.     {    
  33.         if(pData[i].rgbBlue==0 && pData[i].rgbGreen==0 && pData[i].rgbRed==0)    
  34.         {    
  35.             iBlackFlag = i;    
  36.             break;    
  37.         }    
  38.     }    
  39.     return iBlackFlag;    
  40. }    
  41.     
  42. //函数名: GetWhiteColor     
  43. //功能:  获取白点标记的方式     
  44. //参数:  cxImage 图像处理类     
  45. //返回值: 黑点标记     
  46. int OpenCV2CXimage::GetWhiteColor(CxImage cxImage)    
  47. {    
  48.     long i;    
  49.     int iWhiteFlag = 255;    
  50.     RGBQUAD *pData = cxImage.GetPalette();    
  51.     long nPaletteSize = cxImage.GetPaletteSize()/sizeof(RGBQUAD);    
  52.     for(i=0;i<nPaletteSize;i++)    
  53.     {    
  54.         if(pData[i].rgbBlue==255 && pData[i].rgbGreen==255 && pData[i].rgbRed==255)    
  55.         {    
  56.             iWhiteFlag = i;    
  57.             break;    
  58.         }    
  59.     }    
  60.     return iWhiteFlag;    
  61. }    
  62.     
  63. /*  
  64. *功能说明:转换Cximage到IplImage  
  65. *参数说明:src,表示原始Cximage图像;dst,[out] 表示Opencv图像IplImage结构  
  66. *返回值:bool类型。true,表示成功;flase,表示失败。  
  67. */    
  68. bool OpenCV2CXimage::Cximage2IplImage(CxImage *src,IplImage **dst)    
  69. {    
  70.     bool bRet = true;    
  71.     if(!src || !src->IsValid())    
  72.     {    
  73.         bRet = false;    
  74.         return bRet;    
  75.     }    
  76.     m_nPalatteCount = src->GetPaletteSize()/sizeof(RGBQUAD);;    
  77.     m_pPal = src->GetPalette();    
  78.     int iBackColor = GetBlackColor(*src);    
  79.     long i = 0,j = 0;    
  80.     long nImageWidth = 0,nImageHeight = 0;    
  81.     nImageWidth = src->GetWidth();    
  82.     nImageHeight = src->GetHeight();    
  83.     long nBitCunt = src->GetBpp();    
  84.     if(nBitCunt<=1)    
  85.     {    
  86.         *dst = cvCreateImage(cvSize(nImageWidth,nImageHeight),IPL_DEPTH_8U,1);     
  87.         cvZero(*dst);    
  88.         //转换Cximage to IplImage     
  89.         for(j=0;j<nImageHeight;j++)    
  90.         {    
  91.             for(i=0;i<nImageWidth;i++)    
  92.             {    
  93.                 if(src->GetPixelIndex(i,j)==iBackColor)    
  94.                 {    
  95.                     CV_IMAGE_ELEM(*dst,uchar,nImageHeight-1-j,i) = 0;    
  96.                 }    
  97.                 else    
  98.                 {    
  99.                     CV_IMAGE_ELEM(*dst,uchar,nImageHeight-1-j,i) = 255;    
  100.                 }    
  101.             }    
  102.         }    
  103.     }    
  104.     else if(nBitCunt<=8)    
  105.     {    
  106.         *dst = cvCreateImage(cvSize(nImageWidth,nImageHeight),IPL_DEPTH_8U,1);     
  107.         cvZero(*dst);    
  108.         //对应图像调色版与标准调色版的关系     
  109.         map<int,int> mapPalatte;    
  110.         RGBQUAD szSystemPal[256];    
  111.         int k = 0;    
  112.         for(k=0;k<256;k++)    
  113.         {    
  114.             szSystemPal[k].rgbBlue = k;    
  115.             szSystemPal[k].rgbGreen = k;    
  116.             szSystemPal[k].rgbRed = k;    
  117.             szSystemPal[k].rgbReserved = 0;    
  118.         }    
  119.         int m = 0;    
  120.         for(m=0;m<m_nPalatteCount;m++)    
  121.         {    
  122.             for(k=0;k<256;k++)    
  123.             {    
  124.                 if(m_pPal[m].rgbBlue==szSystemPal[k].rgbBlue && m_pPal[m].rgbGreen==szSystemPal[k].rgbGreen && m_pPal[m].rgbRed==szSystemPal[k].rgbRed)    
  125.                 {    
  126.                     mapPalatte.insert(make_pair(m,k));    
  127.                     break;    
  128.                 }    
  129.             }    
  130.         }    
  131.         //////////////////////////////////////////////////////////////////////////     
  132.     
  133.         //转换Cximage to IplImage     
  134.         map<int,int>::iterator iter;    
  135.         BYTE btIndex = 0;    
  136.         for(j=0;j<nImageHeight;j++)    
  137.         {    
  138.             for(i=0;i<nImageWidth;i++)    
  139.             {    
  140.                 btIndex = src->GetPixelIndex(i,j);    
  141.                 iter = mapPalatte.find(btIndex);    
  142.                 if(iter!=mapPalatte.end())    
  143.                 {    
  144.                     btIndex = iter->second;    
  145.                 }    
  146.                 CV_IMAGE_ELEM(*dst,uchar,nImageHeight-1-j,i) = btIndex;    
  147.             }    
  148.         }    
  149.     }    
  150.     else if(nBitCunt<=16)    
  151.     {    
  152.         *dst = cvCreateImage(cvSize(nImageWidth,nImageHeight),IPL_DEPTH_16U,1);     
  153.         (*dst)->origin = 1;//底—左结构 (Windows bitmaps 风格)      
  154.         cvZero(*dst);    
  155.         //转换Cximage to IplImage     
  156.         for(j=0;j<nImageHeight;j++)    
  157.         {    
  158.             for(i=0;i<nImageWidth;i++)    
  159.             {    
  160.                 BYTE *pSrc = src->GetBits(j) + 2*i;    
  161.                 CV_IMAGE_ELEM(*dst,ushort,j,i) = (*pSrc) + (*(pSrc+1))*256;    
  162.             }    
  163.         }    
  164.     }    
  165.     else //24色     
  166.     {    
  167.         *dst = cvCreateImage(cvSize(nImageWidth,nImageHeight),IPL_DEPTH_8U,3);     
  168.         (*dst)->origin = 1;//底—左结构 (Windows bitmaps 风格)      
  169.         cvZero(*dst);    
  170.         //转换Cximage to IplImag     
  171.         memcpy((*dst)->imageData,src->GetBits(0),src->GetSize());    
  172.     }    
  173.     return bRet;    
  174. }    
  175.     
  176. /*  
  177. *功能说明:转换IplImage到Cximage  
  178. *参数说明:src,表示Opencv图像IplImage结构;dst,[out] 表示输出Cximage图像;nBpp,表示输出Cximage图像位数占多少位[一个像数占多少位]  
  179. *返回值:bool类型。true,表示成功;flase,表示失败。  
  180. */    
  181. bool OpenCV2CXimage::IplImage2Cximage(IplImage *src,CxImage *dst,long nBpp)    
  182. {    
  183.     bool bRet = true;    
  184.     if(src==NULL || dst==NULL)    
  185.     {    
  186.         return false;    
  187.     }    
  188.     if(!(nBpp==1 || nBpp==8 || nBpp==24))    
  189.     {    
  190.         return false;    
  191.     }    
  192.     long i = 0,j = 0;    
  193.     CvSize csImageSize = cvGetSize(src);    
  194.     CxImage ciTmp;    
  195.     ciTmp.Create(csImageSize.width,csImageSize.height,src->depth,CXIMAGE_FORMAT_BMP);   
  196.     if(src->depth== IPL_DEPTH_8U)//灰度     
  197.     {    
  198.         ciTmp.SetStdPalette();    
  199.         BYTE gray = 0;    
  200.         for(j=0;j<csImageSize.height;j++)    
  201.         {    
  202.             for(i=0;i<csImageSize.width;i++)    
  203.             {                  
  204.                 gray = CV_IMAGE_ELEM(src,uchar,csImageSize.height-1-j,i);    
  205.           
  206.                 COLORREF color = 0;  
  207.                 color |= gray;  
  208.                 color |= gray << 8;  
  209.                 color |= gray << 16;  
  210.                 ciTmp.SetPixelColor(i,j,color);  
  211.             }    
  212.         }    
  213.     }    
  214.     else //彩色     
  215.     {    
  216.         //转换IplImag to Cximage     
  217.         memcpy(ciTmp.GetBits(0),src->imageData,src->imageSize);    
  218.     }    
  219.     
  220.     //转换成需要的目标图像     
  221.     dst->Create(csImageSize.width,csImageSize.height,nBpp,CXIMAGE_FORMAT_BMP);    
  222.     if(nBpp==ciTmp.GetBpp())    
  223.     {    
  224.         dst->Copy(ciTmp);    
  225.         dst->Save("dst.bmp",CXIMAGE_FORMAT_BMP);  
  226.     }    
  227.     else    
  228.     {    
  229.         if(nBpp==1)//二值     
  230.         {    
  231.             //对应图像调色版与标准调色版的关系     
  232.             map<int,int> mapPalatte;    
  233.             RGBQUAD szSystemPal[256];    
  234.             int k = 0;    
  235.             for(k=0;k<256;k++)    
  236.             {    
  237.                 szSystemPal[k].rgbBlue = k;    
  238.                 szSystemPal[k].rgbGreen = k;    
  239.                 szSystemPal[k].rgbRed = k;    
  240.                 szSystemPal[k].rgbReserved = 0;    
  241.             }    
  242.             int m = 0;    
  243.             for(k=0;k<256;k++)    
  244.             {    
  245.                 for(m=0;m<m_nPalatteCount;m++)    
  246.                 {    
  247.                     if(m_pPal[m].rgbBlue==szSystemPal[k].rgbBlue && m_pPal[m].rgbGreen==szSystemPal[k].rgbGreen && m_pPal[m].rgbRed==szSystemPal[k].rgbRed)    
  248.                     {    
  249.                         mapPalatte.insert(make_pair(k,m));    
  250.                         break;    
  251.                     }    
  252.                 }    
  253.             }    
  254.             //////////////////////////////////////////////////////////////////////////     
  255.             byte btValue = 0;    
  256.             map<int,int>::iterator iter;    
  257.             long nImageWidth = 0;    
  258.             long nImageHeight = 0;    
  259.             if(ciTmp.GetBpp()>8)    
  260.             {    
  261.                 ciTmp.GrayScale();    
  262.             }    
  263.             if(m_nPalatteCount==2) //表示原始的图象为二值图象     
  264.             {    
  265.                 dst->SetPalette(m_pPal,m_nPalatteCount);    
  266.                 btValue = 0;    
  267.                 nImageWidth = ciTmp.GetWidth();    
  268.                 nImageHeight = ciTmp.GetHeight();    
  269.                 for(j=0;j<nImageHeight;j++)    
  270.                 {    
  271.                     for(i=0;i<nImageWidth;i++)    
  272.                     {    
  273.                         btValue = ciTmp.GetPixelIndex(i,j);    
  274.                         iter = mapPalatte.find(btValue);    
  275.                         if(iter!=mapPalatte.end())    
  276.                         {    
  277.                             btValue = iter->second;    
  278.                         }    
  279.                         dst->SetPixelIndex(i,j,btValue);    
  280.                     }    
  281.                 }    
  282.             }    
  283.             else    
  284.             {    
  285.                 ciTmp.Threshold(128);    
  286.                 dst->Copy(ciTmp);    
  287.             }    
  288.         }    
  289.         else if(nBpp==8)    
  290.         {    
  291.             //对应图像调色版与标准调色版的关系     
  292.             map<int,int> mapPalatte;    
  293.             RGBQUAD szSystemPal[256];    
  294.             int k = 0;    
  295.             for(k=0;k<256;k++)    
  296.             {    
  297.                 szSystemPal[k].rgbBlue = k;    
  298.                 szSystemPal[k].rgbGreen = k;    
  299.                 szSystemPal[k].rgbRed = k;    
  300.                 szSystemPal[k].rgbReserved = 0;    
  301.             }    
  302.             int m = 0;    
  303.             for(k=0;k<256;k++)    
  304.             {    
  305.                 for(m=0;m<m_nPalatteCount;m++)    
  306.                 {    
  307.                     if(m_pPal[m].rgbBlue==szSystemPal[k].rgbBlue && m_pPal[m].rgbGreen==szSystemPal[k].rgbGreen && m_pPal[m].rgbRed==szSystemPal[k].rgbRed)    
  308.                     {    
  309.                         mapPalatte.insert(make_pair(k,m));    
  310.                         break;    
  311.                     }    
  312.                 }    
  313.             }    
  314.             //////////////////////////////////////////////////////////////////////////     
  315.             byte btValue = 0;    
  316.             map<int,int>::iterator iter;    
  317.             long nImageWidth = 0;    
  318.             long nImageHeight = 0;    
  319.             if(ciTmp.GetBpp()!=8)    
  320.             {    
  321.                 ciTmp.GrayScale();    
  322.             }    
  323.             if(m_nPalatteCount==8) //表示原始的图象为灰度图象     
  324.             {    
  325.                 dst->SetPalette(m_pPal,m_nPalatteCount);    
  326.                 btValue = 0;    
  327.                 nImageWidth = ciTmp.GetWidth();    
  328.                 nImageHeight = ciTmp.GetHeight();    
  329.                 for(j=0;j<nImageHeight;j++)    
  330.                 {    
  331.                     for(i=0;i<nImageWidth;i++)    
  332.                     {    
  333.                         btValue = ciTmp.GetPixelIndex(i,j);    
  334.                         iter = mapPalatte.find(btValue);    
  335.                         if(iter!=mapPalatte.end())    
  336.                         {    
  337.                             btValue = iter->second;    
  338.                         }    
  339.                         dst->SetPixelIndex(i,j,btValue);    
  340.                     }    
  341.                 }    
  342.             }    
  343.             else    
  344.             {    
  345.                 dst->Copy(ciTmp);    
  346.             }    
  347.         }    
  348.         else    
  349.         {    
  350.             if(ciTmp.GetBpp()==24)    
  351.             {    
  352.                 dst->Copy(ciTmp);    
  353.             }    
  354.             else    
  355.             {    
  356.                 byte btValue = 0;    
  357.                 COLORREF clValue;    
  358.                 map<int,int>::iterator iter;    
  359.                 long nImageWidth = 0;    
  360.                 long nImageHeight = 0;    
  361.                 bRet = ciTmp.IncreaseBpp(24);    
  362.                 dst->Copy(ciTmp);    
  363.             }    
  364.         }    
  365.     }    
  366.     return bRet;    
  367. }    
  368.     
  369. //图象格式转换     
  370. bool OpenCV2CXimage::CxImageFormatConvert(CxImage *src,CxImage *dst,long imagetype)    
  371. {    
  372.     bool bRet = true;    
  373.     if(src==NULL || dst==NULL)    
  374.     {    
  375.         return false;    
  376.     }    
  377.     if(!(imagetype>0 && imagetype<=19))    
  378.     {    
  379.         return false;    
  380.     }    
  381.     if(src->GetType()==imagetype)    
  382.     {    
  383.         dst->Copy(*src);    
  384.     }    
  385.     else    
  386.     {    
  387.         dst->Create(src->GetWidth(),src->GetHeight(),src->GetBpp(),imagetype);    
  388.         src->SetType(imagetype);    
  389.         dst->Copy(*src);    
  390.     }    
  391.     return true;    
  392. }    


main函数:

  1. // OpencvtoCximg.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "OpenCV2CXimage.h"  
  6.   
  7. int _tmain(int argc, _TCHAR* argv[])  
  8. {  
  9. //  cvNamedWindow("img",CV_WINDOW_AUTOSIZE);  
  10.     //Cximage--->IplImage  
  11.     IplImage *img;  
  12.     OpenCV2CXimage o2i;  
  13.     CxImage cimg("gimg.bmp",CXIMAGE_FORMAT_BMP);  
  14.     CxImage *cimg1 = new CxImage();  
  15.     cimg1->Load("gimg.bmp",CXIMAGE_FORMAT_BMP);  
  16.     o2i.Cximage2IplImage(cimg1 ,&img);  
  17.     cvSaveImage("img.jpg",img);  
  18.     //cvShowImage("img",img);  
  19.     //cvWaitKey(0);  
  20.   
  21.     //IplImage-->Cximage   
  1. CxImage *cimg2 = new CxImage();  
  2. IplImage *img1;  
  3. img1=cvLoadImage("gimg.bmp",0);  
  4. o2i.IplImage2Cximage(img1,cimg2,8);   
  5. cimg2->Save("test2.bmp",CXIMAGE_FORMAT_BMP);  
  6.   
  7. //CxImage合并图片  
  8. CxImage im1,im2,im3;    
  9. int h1,w1,h2,w2,h3,w3,bpp;    
  10. im1.Load("E:\\2.jpg");    
  11. im2.Load("E:\\1.jpg");    
  12.    h1=im1.GetHeight();    
  13. w1=im1.GetWidth();    
  14. h2=im2.GetHeight();    
  15. w2=im2.GetWidth();    
  16. h3=h1;    
  17. w3=w1+w2;    
  18. bpp=im1.GetBpp();    
  19. im3.Create(w3,h3,bpp);    
  20. im3.MixFrom(im1,0,0);    
  21. im3.MixFrom(im2,w1,0);    
  22. im3.Save("e:\\3.jpg",CXIMAGE_FORMAT_JPG);    
  23.   
  24. //用CxImage给图片加上文字水印  
  25. CxImage imagesy;     
  26. if( !imagesy.Load("E:\\1.jpg", CXIMAGE_FORMAT_JPG))    
  27. {     
  28.     return TRUE;   
  29. }    
  30. if (imagesy.IsValid())    
  31. {    
  32.     CxImage::CXTEXTINFO  textword;    
  33.     imagesy.InitTextInfo( &textword );    
  34.   
  35.     _stprintf( textword.lfont.lfFaceName,  _T("Times New Roman"));    
  36.     textword.lfont.lfCharSet   =  GB2312_CHARSET  ;    
  37.     textword.lfont.lfWeight    =  8 ;    
  38.     textword.lfont.lfItalic    =  0 ;     
  39.     textword.lfont.lfUnderline =  0 ;     
  40.     textword.fcolor =  RGB( 255,255,160 );    
  41.     textword.bcolor = RGB(   0, 80,160 );    
  42.     textword.opaque =  1; //背景    
  43.     textword.b_opacity = (float)(0)/(float)200.;  //透明度    
  44.     textword.b_round   = (BYTE) 10 ; //四舍五入为背景矩形半径    
  45.     textword.smooth    = (BYTE)1;  //平滑选项的文本    
  46.     _stprintf( textword.text, _T("水印文字") );    
  47.   
  48.     imagesy.DrawStringEx(0,0,100,&textword);    
  49.   
  50.     imagesy.Save("e:\\z2_sy.jpg",CXIMAGE_FORMAT_JPG);    
  51. }    
  52. 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中,需要记住:
  1. OpenCV中的内存分配是自动完成的(不是特别指定的话)
  2. 使用OpenCV的C++ 接口时不需要考虑内存释放问题
  3. Mat的赋值运算和拷贝构造函数只会拷贝矩阵头,仍然共同同一个矩阵
  4. 如果要复制矩阵数据,可以使用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图像
[html] view plain copy
 print?
  1. #include <iostream>  
  2. #include <opencv2/core/core.hpp>  
  3. #include <opencv2/highgui/highgui.hpp>  
  4.   
  5. using namespace std;  
  6. using namespace cv;  
  7.   
  8. Mat src;  
  9. Mat image;  
  10. string str = "./";  
  11.   
  12. /*创建alpha表,整体偏红色,左上角到右下角呈现从完全透明到完全不透明变化趋势*/  
  13. void createAlphaMat(Mat &mat)  
  14. {  
  15.     for (int i = 0; i < mat.rows; ++i) {  
  16.         for (int j = 0; j < mat.cols; ++j) {  
  17.             Vec4b& rgba = mat.at<Vec4b>(i, j);  
  18.             rgba[0] = UCHAR_MAX;    //r分量一直最大,所以整体偏红  
  19.             rgba[1] = saturate_cast<uchar>((float (mat.cols - j)) / ((float)mat.cols) * UCHAR_MAX);  
  20.             rgba[2] = saturate_cast<uchar>((float (mat.rows - i)) / ((float)mat.rows) * UCHAR_MAX);  
  21.             rgba[3] = saturate_cast<uchar>(0.5 * (rgba[1] + rgba[2]));  
  22.         }  
  23.     }  
  24. }  
  25.   
  26. int main()  
  27. {  
  28.     /*采用默认参数进行图片的保存*/  
  29.     src = imread("test.jpg");  
  30.     imwrite(str+"原图.jpg", src); //c版本中的保存图片为cvSaveImage()函数,c++版本中直接与matlab的相似,imwrite()函数。  
  31.     imshow("src", src);  
  32.     Rect rect(src.cols/4, src.rows/4, src.cols/2, src.rows/2);  
  33.     image = src(rect);  
  34.     imwrite(str+"截取原图中的一部分区域小图.jpg", image);  
  35.     imshow("image", image);  
  36.   
  37.     /*采用自己设置的参数来保存图片*/  
  38.     Mat mat(480, 640, CV_8UC4);  
  39.     createAlphaMat(mat);  
  40.     vector<int> compression_params;  
  41.     compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);  
  42.     compression_params.push_back(9);    //png格式下,默认的参数为3.  
  43.     try {  
  44.         imwrite("alpha.png", mat, compression_params);  
  45.     }  
  46.     catch (runtime_error& ex) {  
  47.         fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what());  
  48.         return 1;  
  49.     }  
  50.     fprintf(stdout, "Saved PNG file with alpha data.\n");  
  51.   
  52.     waitKey(0);  
  53.     return 0;  
  54. }  

生成的alpha表图像显示如下:

   

4.Mat的显示

OpenCV提供了用以窗口的形式显示图片的方法,代码如下:

[html] view plain copy
 print?
  1. Mat img = imread("f:\psb.jpg");  
  2. const string name ="Hu";  
  3. namedWindow(name);  
  4. imshow(name,img);  
  5. 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. dataMat对象中的一个指针,指向内存中存放矩阵数据的一块内存 (uchar* data).

ii. row: 行;col:列;rows:行数;cols:列数。

iii. dims :Mat所代表的矩阵的维度,如 3 * 4 的矩阵为 维,3 * 4 * 5 的为3.

iv. channels:通道,矩阵中的每一个矩阵元素拥有的值的个数,比如说 3 * 4 矩阵中一共 12 个元素,如果每个元素有三个值,那么就说这个矩阵是 通道的,即 channels = 3。常见的是一张彩色图片有红、绿、蓝三个通道。但是opencvimreadopencv读图的函数)读进来的图像,三通道存放顺序为BGR

v. depth深度,即每一个像素的位数(bits),在opencvMat.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 }; 可见 01都代表8位, 23都代表16位,45代表32位,6代表64位; 

vi. step:是一个数组,定义了矩阵的布局,具体见下面图片分析,另外注意 step1 (step / elemSize1)M.step[m-1] 总是等于 elemSizeM.step1(i)返回的是第i维的步长,因此M.step1(m-1)总是等于 channelsmM的维度;这里是解释步长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 = 1CV_8UC3 那么 elemSize = 3CV_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比特每像素采样”的原因。

posted @ 2017-08-03 23:27  ZhangPYi  阅读(347)  评论(0编辑  收藏  举报