• 【视频开发】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 ", ex.what());  
    48.         return 1;  
    49.     }  
    50.     fprintf(stdout, "Saved PNG file with alpha data. ");  
    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比特每像素采样”的原因。

  • 相关阅读:
    11g新特性-dba_users安全性的一些增强
    sysbench的安装与使用(with MySQL)
    参数table_open_cache
    参数max_allowed_packet
    解决linux下unzip中文有乱码的问题
    11g添加asm
    有了iscsi存储怎么让主机识别以及使用创建lvm
    用rlwrap使sqlplus可以上下翻页
    卸载已经安装的rpm包
    物化视图刷新慢--有可能是mv log被多个mv使用造成的
  • 原文地址:https://www.cnblogs.com/huty/p/8517054.html
Copyright © 2020-2023  润新知