zoukankan      html  css  js  c++  java
  • opencv Mat 与MFC中的CImage相互转换

    MatCImage.h

    #pragma
    once #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> using namespace cv; using namespace std; class MatCImage { public: /*MatToCImage *简介: * OpenCV的Mat转ATL/MFC的CImage,仅支持单通道灰度或三通道彩色 *参数: * mat:OpenCV的Mat * cimage:ATL/MFC的CImage */ void MatToCImage(Mat& mat, CImage& cimage); /*CImageToMat *简介: * ATL/MFC的CImage转OpenCV的Mat,仅支持单通道灰度或三通道彩色 *参数: * cimage:ATL/MFC的CImage * mat:OpenCV的Mat */ void CImageToMat(CImage& cimage, Mat& mat); // VS默认工程是Unicode编码(宽字节),有时需要ANSI,即单字节,实现宽到单的转化 string CString2StdString(const CString& cstr); // 显示图像到指定窗口 void DisplayImage(CWnd* m_pMyWnd,const CImage& image); // 格式转换,AWX云图转到可以显示的opencv支持的格式 Mat AWX2Mat(CString filePath); void DisplayImageEx(CWnd* pWnd, const CImage& image); };

    MatCImage.c

    #include "stdafx.h"
    #include "MatCImage.h"
    
    // 实现cv::Mat 结构到 CImage结构的转化  
    void MatCImage::MatToCImage(Mat& mat, CImage& cimage)  
    {  
        if (0 == mat.total())  
        {  
            return;  
        }  
    
    
        int nChannels = mat.channels();  
        if ((1 != nChannels) && (3 != nChannels))  
        {  
            return;  
        }  
        int nWidth    = mat.cols;  
        int nHeight   = mat.rows;  
    
    
        //重建cimage  
        cimage.Destroy();  //这一步是防止重复利用造成内存问题
        cimage.Create(nWidth, nHeight, 8 * nChannels);  //默认图像像素单通道占用1个字节
    
    
        //拷贝数据  
    
    
        uchar* pucRow;                                  //指向数据区的行指针  
        uchar* pucImage = (uchar*)cimage.GetBits();     //指向数据区的指针  
        int nStep = cimage.GetPitch();                  //每行的字节数,注意这个返回值有正有负  
    
        // 如果是1个通道的图像(灰度图像) DIB格式才需要对调色板设置    
        // CImage中内置了调色板,我们要对他进行赋值:  
        if (1 == nChannels)                             //对于单通道的图像需要初始化调色板  
        {  
            RGBQUAD* rgbquadColorTable;  
            int nMaxColors = 256;  
            rgbquadColorTable = new RGBQUAD[nMaxColors];  
             //这里可以通过CI.GetMaxColorTableEntries()得到大小(如果你是CI.Load读入图像的话)    
            cimage.GetColorTable(0, nMaxColors, rgbquadColorTable);  //这里是取得指针  
            for (int nColor = 0; nColor < nMaxColors; nColor++)  
            {  
                //BYTE和uchar一回事,但MFC中都用它  
                rgbquadColorTable[nColor].rgbBlue = (uchar)nColor;  // (BYTE)nColor
                rgbquadColorTable[nColor].rgbGreen = (uchar)nColor;  
                rgbquadColorTable[nColor].rgbRed = (uchar)nColor;  
            }  
            cimage.SetColorTable(0, nMaxColors, rgbquadColorTable);  
            delete []rgbquadColorTable;  
        }  
    
    
        for (int nRow = 0; nRow < nHeight; nRow++)  
        {  
            pucRow = (mat.ptr<uchar>(nRow));  
            for (int nCol = 0; nCol < nWidth; nCol++)  
            {  
                if (1 == nChannels)  
                {  
                    *(pucImage + nRow * nStep + nCol) = pucRow[nCol];  
                }  
                else if (3 == nChannels)  
                {  
                    for (int nCha = 0 ; nCha < 3; nCha++)  
                    {  
                        *(pucImage + nRow * nStep + nCol * 3 + nCha) = pucRow[nCol * 3 + nCha];  
                    }             
                }  
            }     
        }  
    }  
    
    void MatCImage::CImageToMat(CImage& cimage, Mat& mat)  
    {  
        if (true == cimage.IsNull())  
        {  
            return;  
        }  
    
    
        int nChannels = cimage.GetBPP() / 8;  
        if ((1 != nChannels) && (3 != nChannels))  
        {  
            return;  
        }  
        int nWidth    = cimage.GetWidth();  
        int nHeight   = cimage.GetHeight();  
    
    
        //重建mat  
        if (1 == nChannels)  
        {  
            mat.create(nHeight, nWidth, CV_8UC1);  
        }  
        else if(3 == nChannels)  
        {  
            mat.create(nHeight, nWidth, CV_8UC3);  
        }  
    
    
        //拷贝数据  
    
    
        uchar* pucRow;                                  //指向数据区的行指针  
        uchar* pucImage = (uchar*)cimage.GetBits();     //指向数据区的指针  
        int nStep = cimage.GetPitch();                  //每行的字节数,注意这个返回值有正有负  
    
    
        for (int nRow = 0; nRow < nHeight; nRow++)  
        {  
            pucRow = (mat.ptr<uchar>(nRow));  
            for (int nCol = 0; nCol < nWidth; nCol++)  
            {  
                if (1 == nChannels)  
                {  
                    pucRow[nCol] = *(pucImage + nRow * nStep + nCol);  
                }  
                else if (3 == nChannels)  
                {  
                    for (int nCha = 0 ; nCha < 3; nCha++)  
                    {  
                        pucRow[nCol * 3 + nCha] = *(pucImage + nRow * nStep + nCol * 3 + nCha);  
                    }             
                }  
            }     
        }  
    }  
    // VS默认工程是Unicode编码(宽字节),有时需要ANSI,即单字节,实现宽到单的转化  
    string MatCImage::CString2StdString(const CString& cstr)  
    {     
        CT2A str(cstr);  
        return string(str.m_psz);  
    }  
    
    // 显示图像到指定窗口  
    void MatCImage::DisplayImage(CWnd* m_pMyWnd,const CImage& image)  
    {  
    
        CDC *m_pDC = m_pMyWnd->GetDC();//获取窗口所拥有的设备上下文,用于显示图像  
        m_pMyWnd->UpdateWindow();  
    
        CRect rc;  
    //    m_pMyWnd->GetWindowRect(&rc);  
    
        /*InvalidateRect(m_pMyWnd->m_hWnd,&rc,true);*/  
        int nwidth = rc.Width();  
        int nheight = rc.Height();  
    
        int fixed_width = min(image.GetWidth(),nwidth);  
        int fixed_height = min(image.GetHeight(),nheight);  
    
        double ratio_w = fixed_width / (double)image.GetWidth();  
        double ratio_h = fixed_height / (double)image.GetHeight();  
        double ratio = min(ratio_w,ratio_h);  
    
        int show_width = (int)(image.GetWidth() * ratio);  
        int show_height = (int)(image.GetHeight() * ratio);  
    
        int offsetx = (nwidth - show_width) / 2;  
        int offsety = (nheight - show_height) / 2;  
    
        ::SetStretchBltMode(m_pDC->GetSafeHdc(),COLORONCOLOR);//设置位图的伸缩模式  
        image.StretchBlt(m_pDC->GetSafeHdc(),offsetx,offsety,show_width,show_height,  
            0,0,image.GetWidth(),image.GetHeight(),SRCCOPY);  
    }  
    
    
    void MatCImage::DisplayImageEx(CWnd* pWnd, const CImage& image)  
    {  
        CDC *m_pDC = pWnd->GetDC();//获取窗口所拥有的设备上下文,用于显示图像  
        pWnd->UpdateWindow();  
    
        CRect rc;  
        //客户区大小  
        //CRect rc1;  
        pWnd->GetWindowRect(&rc);  
    
    
        //ScreenToClient(&rc);  
    
        ::SetStretchBltMode(m_pDC->GetSafeHdc(),COLORONCOLOR);//设置位图的伸缩模式  
        image.StretchBlt(m_pDC->GetSafeHdc(),0,0,rc.Width()-1,rc.Height()-1,  
            0,0,image.GetWidth(),image.GetHeight(),SRCCOPY);  
    }  
    
    // 格式转换,AWX云图转到可以显示的opencv支持的格式  
    Mat MatCImage::AWX2Mat(CString filePath)  
    {  
        CFile fp;  
        Mat   mat;  
        fp.Open(filePath,CFile::modeRead);  
        ULONGLONG flength = fp.GetLength();  
    
        if (2475700 == flength)  
        {  
            mat.create(1300,1900,CV_8UC1);  
        }  
        else if (1444803 == flength)  
        {  
            mat.create(1201,1201,CV_8UC1);  
        }  
    
        LONGLONG size = mat.rows * mat.cols;  
        LONGLONG sizebuff = fp.Seek(-size, CFile::end);  
    
        uchar *pSource = new uchar[size];  
        fp.Read(pSource,size);  
        fp.Close();  
    
        for (int i = 0; i<mat.rows; i++)  
        {  
            uchar * ps = mat.ptr<uchar>(i);  
            for (int j = 0 ; j < mat.cols; j++)  
            {  
                ps[j] = *(pSource + i*mat.cols + j);  
            }  
        }  
        delete pSource;  
    
    
    
        return mat;  
    }  
  • 相关阅读:
    C#中的async和await
    Windows 10 error code 0x80072efd
    Winform中调用js函数
    Windows 10 x64 安装 Visual Basic 6.0 SP6
    用谷歌浏览器来当手机模拟器
    Windows 10 解决 0x80070021 错误
    正则匹配所有中英文标点
    本地网站部署注意细节
    电信光猫 路由+拨号混合设置 备忘
    Restful 支持 自定义序列化
  • 原文地址:https://www.cnblogs.com/zhulinhaibao/p/7206286.html
Copyright © 2011-2022 走看看