天天看點

OPenCV操作ImageView.cpp

  1. // ImageView.cpp : implementation of the CImageView class
  2. //
  3. #include "stdafx.h"
  4. #include "Image.h"
  5. #include "ImageDoc.h"
  6. #include "ImageView.h"
  7. /////////begin/////////////////////////////////
  8. #include "cv.h"      // include core library interface
  9. #include "highgui.h" // include GUI library interface
  10. #pragma comment(lib, "cv" )
  11. #pragma comment(lib, "highgui" )
  12. #pragma comment(lib, "cxcore" )
  13. CString imgfilepath;
  14. IplImage* img=0; // Declare IPL/OpenCV image pointer
  15. ////////end/////////////////////////////////
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. /////////////////////////////////////////////////////////////////////////////
  22. // CImageView
  23. IMPLEMENT_DYNCREATE(CImageView, CView)
  24. BEGIN_MESSAGE_MAP(CImageView, CView)
  25.         //{{AFX_MSG_MAP(CImageView)
  26.         ON_COMMAND(ID_IMAGE_OPENFILE, OnImageOpenFile)
  27.         ON_COMMAND(ID_IMAGE_SOBEL, OnImageSobel)
  28.         ON_COMMAND(ID_IMAGE_LAPLACE, OnImageLaplace)
  29.         ON_COMMAND(ID_IMAGE_CANNY, OnImageCanny)
  30.         ON_COMMAND(ID_IMAGE_HISTGRAM, OnImageHistgram)
  31.         ON_COMMAND(ID_IMAGE_RESIZE, OnImageResize)
  32.         ON_COMMAND(ID_IMAGE_ROTATION, OnImageRotation)
  33.         ON_COMMAND(ID_IMAGE_EROSION, OnImageErosion)
  34.         ON_COMMAND(ID_IMAGE_OPEN, OnImageOpen)
  35.         ON_COMMAND(ID_IMAGE_HOUGH_LINE, OnImageHoughLine)
  36.         ON_COMMAND(ID_IMAGE_HOUGH_CIRCLE, OnImageHoughCircle)
  37.         //}}AFX_MSG_MAP
  38.         // Standard printing commands
  39.         ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
  40.         ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
  41.         ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
  42. END_MESSAGE_MAP()
  43. // CImageView construction/destruction
  44. CImageView::CImageView()
  45. {
  46.         // TODO: add construction code here
  47. }
  48. CImageView::~CImageView()
  49. BOOL CImageView::PreCreateWindow(CREATESTRUCT& cs)
  50.         // TODO: Modify the Window class or styles here by modifying
  51.         //  the CREATESTRUCT cs
  52.         return CView::PreCreateWindow(cs);
  53. // CImageView drawing
  54. void CImageView::OnDraw(CDC* pDC)
  55.         CImageDoc* pDoc = GetDocument();
  56.         ASSERT_VALID(pDoc);
  57.         // TODO: add draw code for native data here
  58. // CImageView printing
  59. BOOL CImageView::OnPreparePrinting(CPrintInfo* pInfo)
  60.         // default preparation
  61.         return DoPreparePrinting(pInfo);
  62. void CImageView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  63.         // TODO: add extra initialization before printing
  64. void CImageView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  65.         // TODO: add cleanup after printing
  66. // CImageView diagnostics
  67. void CImageView::AssertValid() const
  68.         CView::AssertValid();
  69. void CImageView::Dump(CDumpContext& dc) const
  70.         CView::Dump(dc);
  71. CImageDoc* CImageView::GetDocument() // non-debug version is inline
  72.         ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CImageDoc)));
  73.         return (CImageDoc*)m_pDocument;
  74. #endif //_DEBUG
  75. // CImageView message handlers
  76. void CImageView::OnImageOpenFile()
  77.         // TODO: Add your command handler code here
  78.                 CFileDialog dlg(TRUE, _T("*.bmp"), "",
  79.                OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY,
  80.                "image files (*.bmp; *.jpg) |*.bmp;*.jpg|AVI files (*.avi) |*.avi|All Files (*.*)|*.*||",NULL);
  81.         char title[]= {"Open Image"};
  82.         dlg.m_ofn.lpstrTitle= title;
  83.         if (dlg.DoModal() == IDOK)
  84.         {
  85.                 imgfilepath= dlg.GetPathName();
  86.                 if (img!=0)
  87.                         cvReleaseImage( &img );
  88.                 img = cvvLoadImage( imgfilepath ); // load image
  89.         cvvNamedWindow( "Original Image", 1 );  // create a window
  90.         cvvShowImage( "Original Image", img );  // display the image on window
  91.         }
  92. void CImageView::OnImageSobel()
  93.     //定義的變量
  94.         IplImage* pImage= NULL; // 聲明IplImage 變量
  95.         IplImage* pImgSobelgray= NULL;// 聲明IplImage 變量,用于灰階圖像Sobel變換
  96.         IplImage* pImg8u= NULL;// 聲明IplImage 變量,用于圖像格式轉換
  97.         IplImage* pImg8uSmooth= NULL;// 聲明IplImage 變量,用于存儲平滑後的圖像
  98.         IplImage* pImgColor= NULL;// 聲明IplImage 變量,用于Sobel變換
  99.         IplImage* pImgSobelcolor= NULL;// 聲明IplImage 變量,用于彩色圖像Sobel變換
  100.     IplImage* pImgPlanes[3] = { 0, 0, 0 };
  101.         //将已讀入系統的圖像複制一份
  102.         pImage=cvCloneImage( img );
  103.         //建立和原始圖像一樣圖像記憶體區,圖像元素的位深度設為IPL_DEPTH_8U
  104.         //即無符号8位整型
  105.         pImg8u = cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U, 1);
  106.         pImg8uSmooth = cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U, 1);
  107.         //對灰階圖像進行Sobel變換
  108.         //将彩色圖像轉換為灰階圖像
  109.         cvCvtColor(pImage, pImg8u, CV_BGR2GRAY);
  110.         //對圖像進行高斯濾波
  111.         cvSmooth( pImg8u, pImg8uSmooth,CV_GAUSSIAN,3,0,0);
  112.         //建立一新圖像記憶體區,圖像元素的位深度設為IPL_DEPTH_16S有符号16位整型
  113.         //因為cvSobel函數要求目标圖像必須是16-bit圖像
  114.         pImgSobelgray = cvCreateImage(cvGetSize(pImage),IPL_DEPTH_16S, 1);
  115.         //計算一階 x方向的圖像差分,可根據需要設定參數
  116.         cvSobel(pImg8uSmooth, pImgSobelgray,0,1,3);
  117.         //将圖像格式再轉換回來,用于顯示
  118.     cvConvertScaleAbs(pImgSobelgray,pImg8u,1,0 ) ;
  119.         //建立視窗,顯示圖像
  120.         cvvNamedWindow( "Sobel gray Image", 1 );  
  121.     cvvShowImage( "Sobel gray Image", pImg8u  );
  122.         //對彩色圖像進行Sobel變換
  123.         //建立3個圖像記憶體區,分别存儲圖像3個通道,圖像元素的位深度設為IPL_DEPTH_8U
  124.         int i;
  125.     for( i = 0; i < 3; i++ )
  126.         pImgPlanes[i] = cvCreateImage( cvSize(pImage ->width, pImage ->height), 8, 1 );
  127.     //建立一新圖像記憶體區,圖像元素的位深度設為IPL_DEPTH_16S有符号16位整型
  128.         pImgSobelcolor = cvCreateImage( cvSize(pImage ->width, pImage ->height), IPL_DEPTH_16S, 1 );
  129.      //要求輸出圖像是 16 位有符号的
  130.     pImgColor = cvCreateImage( cvSize(pImage ->width, pImage ->height), 8, 3 );
  131.         //将彩色圖像分成3 個單通道圖像
  132.     cvCvtPixToPlane(pImage, pImgPlanes[0], pImgPlanes[1], pImgPlanes[2], 0 );
  133.         for( i = 0; i < 3; i++ )
  134.     {
  135.         //分别對每通道圖像進行Sobel變換
  136.                 cvSobel( pImgPlanes[i], pImgSobelcolor,0,1,3 );
  137.                 //轉化為8位的圖像
  138.         cvConvertScaleAbs(pImgSobelcolor, pImgPlanes[i], 1, 0 );  
  139.     }
  140.         //将各通道圖像進行合并
  141.         cvCvtPlaneToPix( pImgPlanes[0], pImgPlanes[1], pImgPlanes[2], 0, pImgColor);
  142.         cvvNamedWindow( "Sobel color Image", 1 );  
  143.     cvvShowImage( "Sobel color Image", pImgColor);  
  144.         //等待按鍵
  145.         cvWaitKey(0);
  146.         //鎖毀視窗
  147.         cvDestroyWindow( " Sobel gray Image " );       
  148.         cvDestroyWindow( " Sobel color Image " );      
  149.         //将程式開始定義的變量釋放
  150.         cvReleaseImage( & pImage);     
  151.         cvReleaseImage( & pImgSobelgray);
  152.         cvReleaseImage( & pImgSobelcolor);
  153.         cvReleaseImage( & pImg8u);     
  154.         cvReleaseImage( & pImg8uSmooth);
  155. void CImageView::OnImageLaplace()
  156.         //定義的變量
  157.         IplImage* pImage= NULL;// 聲明IplImage 變量
  158.         IplImage* pImgLaplace= NULL;// 聲明IplImage 變量,用于Laplace變換
  159.         pImg8uSmooth= cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U, 1);
  160.         cvCvtColor(pImage,pImg8u, CV_BGR2GRAY);
  161.         //對灰階圖像進行高斯濾波
  162.         //此函數和cvSobel函數一樣要求目标圖像必須是16-bit圖像
  163.         //如果給8-bit目标圖像會報錯
  164.         pImgLaplace = cvCreateImage(cvGetSize(img),IPL_DEPTH_16S, 1);
  165.         cvLaplace(pImg8uSmooth, pImgLaplace,3);
  166.     //将圖像格式再轉換回來,用于顯示
  167.         cvConvertScaleAbs(pImgLaplace,pImg8u,1,0 ) ;
  168.         cvvNamedWindow( "laplace gray Image", 1 );  
  169.         cvvShowImage( "laplace gray Image", pImg8u  );  
  170.         //銷毀視窗
  171.         cvDestroyWindow( " laplace gray Image " );     
  172.         cvReleaseImage( & pImgLaplace);
  173.         //cvReleaseImage( & pImg8uSmooth);
  174. void CImageView::OnImageCanny()
  175.         IplImage* pImgCanny= NULL;// 聲明IplImage 變量,用于灰階圖像Canny變換
  176.         pImgCanny = cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U, 1);
  177.         //對灰階圖像進行Canny變換
  178.         //cvCanny的源圖像必須是灰階圖像
  179.         cvCanny(pImg8uSmooth,pImgCanny, 100, 200, 3 );
  180.         cvConvertScaleAbs(pImgCanny,pImg8u,1,0 ) ;
  181.         cvvNamedWindow( "Canny Image", 1 );  
  182.         cvvShowImage( "Canny Image", pImg8u);  
  183.         cvDestroyWindow( " Canny Image " );    
  184.         cvReleaseImage( & pImgCanny);
  185. void CImageView::OnImageHistgram()
  186.         int hist_size = 255; //直方圖的針數
  187.         float range_0[]={0,256}; //第0維數值的變化範圍
  188.         float* ranges[] = { range_0 };//第1維數值的變化範圍
  189.         int i, bin_w; //下标号
  190.         float max_value = 0, min_value = 0; //直方圖數值的max和min
  191.         int min_idx = 0, max_idx = 0; //對應上述max和min數值時的下标号
  192.         double mean = 0, variance = 0; //用于存放平均值(mean)和變化量(variance)的變量
  193.         IplImage* pImgGray= NULL;// 聲明IplImage 變量
  194.         //将已讀入系統的圖像一份
  195.         pImgGray = cvCreateImage(cvSize(pImage->width,pImage->height),
  196.                         IPL_DEPTH_8U, 1);
  197.         //轉換成灰階圖像
  198.         cvCvtColor(pImage, pImgGray, CV_BGR2GRAY);
  199.         //建立一個矩形區域
  200.         CvRect rect = cvRect(0, 0, 500, 600 );
  201.         //把矩形作用于圖像以建立一個感興趣區(region of interest, ROI)
  202.         cvSetImageROI(pImgGray, rect);    // 設定 ROI
  203.         //建立一個圖像用來存放直方圖
  204.         IplImage* histImage = cvCreateImage(cvSize(320,200), 8, 1);
  205.         //建立一個指定尺寸的直方圖,用于存放從圖像獲得的資訊
  206.         CvHistogram* hist =
  207.                 cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);
  208.         //計算直方圖并作用到hist變量
  209.         cvCalcHist( &pImgGray, hist, 0, NULL );
  210.         //得到直方圖中的最大最小值及其标号
  211.         cvGetMinMaxHistValue( hist, &min_value, &max_value, &min_idx, &max_idx);
  212.         //縮放這些針值以容入圖像内
  213.         cvScale( hist->bins, hist->bins, ((double)histImage->height)/max_value, 0 );
  214.         //設所有直方圖的數值為255
  215.         cvSet( histImage, cvScalarAll(255), 0 );
  216.         //建立一個比例因子以沿寬度縮放
  217.         bin_w = cvRound((double)histImage->width/hist_size);
  218.         for( i = 0; i < hist_size; i++ ) {
  219.                 //把直方圖畫到圖像中
  220.                 cvRectangle( histImage, cvPoint(i*bin_w, histImage->height),
  221.                         cvPoint((i+1)*bin_w,
  222.                         histImage->height - cvRound(cvGetReal1D(hist->bins,i))),
  223.                         cvScalarAll(0), -1, 8, 0 );
  224.                 //得到目前數值
  225.                 float* bins = cvGetHistValue_1D(hist,i);
  226.                 //增加均值
  227.                 mean += bins[0];
  228.         //      std::cout<< bins[0] << " " << bins[1] << std::endl;
  229.         //均值計算完畢
  230.         mean /= hist_size;
  231.         //有了均值後就可以計算變化量了(variance)
  232.                 variance += pow((bins[0] - mean),2);
  233.         //變化量計算完畢
  234.         variance /= hist_size;
  235. //      std::cout << "Histogram Mean: " << mean << std::endl;
  236. //      std::cout << "Variance: " << variance << std::endl;
  237. //      std::cout << "Standard Deviation: " << sqrt(variance) << std::endl;
  238.         cvNamedWindow("Original", 0);
  239.         cvShowImage("Original", pImage );
  240.         cvNamedWindow("Gray", 0);
  241.         cvShowImage("Gray", pImgGray );
  242.         cvNamedWindow("Histogram", 0);
  243.         cvShowImage("Histogram", histImage );
  244.         CvFont *pfont=new CvFont;
  245.         cvInitFont(pfont,CV_FONT_HERSHEY_SIMPLEX  ,0.8f,0.8f,0,2);
  246.         CString Result="Histogram Mean: ";
  247.         CString str; str.Format("%f", mean);
  248.         Result+=str+"\n";
  249.         cvPutText(histImage,Result,cvPoint(80,80),pfont,CV_RGB(255,0,0));
  250.         delete pfont;
  251.         cvReleaseImage(&histImage);
  252.         cvReleaseImage(&pImgGray);
  253.         cvDestroyWindow("Original");
  254.         cvDestroyWindow("Gray");
  255.         cvDestroyWindow("Histogram");
  256. void CImageView::OnImageResize()
  257.         IplImage* pImgNew= NULL;// 聲明IplImage 變量
  258.         CFileDialog dlg(TRUE, _T("*.bmp"), "",
  259.             OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY,
  260.         char title[]= {"Open Image again"};
  261.                 if (pImgNew!=0)
  262.                         cvReleaseImage( &pImgNew );
  263.                 //載入第二幅圖像
  264.                 pImgNew = cvvLoadImage( imgfilepath );
  265.                 //建立視窗,顯示第二幅圖像
  266.                 cvvNamedWindow( "Second Image", 1 );  
  267.                         cvvShowImage( "Second Image", pImgNew );  
  268.         //縮放圖像,使其尺寸與第二幅圖像相等
  269.         cvResize( pImage, pImgNew, CV_INTER_NN );
  270.         //建立視窗,顯示縮放後的幅圖像
  271.         cvvNamedWindow( "Resized Image", 1 );  
  272.         cvvShowImage( "Resized Image", pImgNew );  
  273.         cvReleaseImage(&pImage);
  274.         cvReleaseImage(&pImgNew);
  275.         cvDestroyWindow("Second Image");
  276.         cvDestroyWindow("Resized Image");
  277. void CImageView::OnImageRotation()
  278.         int angle = 30; //旋轉30度
  279.         int opt = 0;     // 1: 加縮放
  280.                                 // 0:  僅僅旋轉
  281.         double factor; //縮放因子
  282.         IplImage* pImgRotation= NULL;// 聲明IplImage 變量
  283.         pImgRotation=cvCloneImage( img );
  284.         //建立M矩陣
  285.         float m[6];
  286.                         // Matrix m looks like:
  287.                         //
  288.                         // [ m0  m1  m2 ] ===>  [ A11  A12   b1 ]
  289.                         // [ m3  m4  m5 ]       [ A21  A22   b2 ]
  290.         CvMat M = cvMat( 2, 3, CV_32F, m );
  291.         int w = img->width;
  292.         int h = img->height;
  293.         if(opt) // 旋轉加縮放
  294.                                 factor = (cos(angle*CV_PI/180.) + 1.0)*2;
  295.         else //  僅僅旋轉
  296.                                 factor = 1;
  297.         m[0] = (float)(factor*cos(-angle*CV_PI/180.));
  298.         m[1] = (float)(factor*sin(-angle*CV_PI/180.));
  299.         m[3] = -m[1];
  300.         m[4] = m[0];
  301.         // 将旋轉中心移至圖像中間
  302.         m[2] = w*0.5f;
  303.         m[5] = h*0.5f;
  304.         //  dst(x,y) = A * src(x,y) + b
  305.         cvZero(pImgRotation);
  306.         cvGetQuadrangleSubPix( pImage, pImgRotation, &M);
  307.         //建立視窗,顯示圖像  
  308.         cvNamedWindow( "Rotation Image", 1 );
  309.         cvShowImage( "Rotation Image", pImgRotation );
  310.         cvReleaseImage(&pImgRotation);
  311.         cvDestroyWindow("Rotation Image");
  312. void CImageView::OnImageErosion()
  313.         IplImage* pImgErode= NULL;// 聲明IplImage 變量
  314.         IplImage* pImgDilate= NULL;// 聲明IplImage 變量
  315.         pImgErode=cvCloneImage( img );
  316.         pImgDilate=cvCloneImage( img );
  317.         //對輸入圖像使用預設的3×3 長方形結構元素進行腐蝕
  318.         cvErode( pImgErode, pImgErode, 0, 2 );
  319.         //對輸入圖像使用預設的3×3 長方形結構元素進行膨脹
  320.         cvDilate( pImgDilate, pImgDilate, 0, 2 );
  321.         cvNamedWindow("Erosion", 0);
  322.         cvShowImage("Erosion", pImgErode );
  323.         cvNamedWindow("Dilation", 0);
  324.         cvShowImage("Dilation", pImgDilate );
  325.         cvReleaseImage(&pImgErode);
  326.         cvReleaseImage(&pImgDilate);
  327.         cvDestroyWindow("Erosion");
  328.         cvDestroyWindow("Dilation");
  329. void CImageView::OnImageOpen()
  330.         IplImage* pImgOpen= NULL;// 聲明IplImage 變量
  331.         IplImage* pImgClose= NULL;// 聲明IplImage 變量
  332.         IplConvKernel* pKernel =NULL;// 聲明IplConvKernel 變量
  333.         pImgOpen=cvCloneImage( img );
  334.         pImgClose=cvCloneImage( img );
  335.         //建立立結構元素
  336.         pKernel = cvCreateStructuringElementEx(15,15,8,8,CV_SHAPE_ELLIPSE,NULL);
  337.         //進行開運算
  338.         cvErode(pImgOpen,pImgOpen,pKernel,1);
  339.     cvDilate(pImgOpen,pImgOpen,pKernel,1);  
  340.         //進行閉運算
  341.     cvDilate(pImgClose,pImgClose,pKernel,1);  
  342.         cvErode(pImgClose,pImgClose,pKernel,1);
  343.         cvNamedWindow("Open", 0);
  344.         cvShowImage("Open", pImgOpen );
  345.         cvNamedWindow("Close", 0);
  346.         cvShowImage("Close", pImgClose );
  347.         cvReleaseImage(&pImgOpen);
  348.         cvReleaseImage(&pImgClose);
  349.         cvDestroyWindow("Open");
  350.         cvDestroyWindow("Close");
  351. void CImageView::OnImageHoughLine()
  352.         CvMemStorage* storage = NULL;// 聲明storage 變量,用于存儲檢測到的線段
  353.     CvSeq* lines = NULL;   //聲明lines變量,用于存儲直線的輪廓
  354.         //将已讀入系統的圖像複制兩份,一份作為背景圖像
  355.         //建立記憶體空間
  356.         storage = cvCreateMemStorage(0);
  357.         //利用Canny變換找出圖像邊緣
  358.     cvCanny( pImg8u, pImgCanny, 50, 500, 3 );
  359.         //Hough線變換
  360.     lines = cvHoughLines2( pImgCanny, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 80, 30, 10 );
  361.         //在原圖上畫紅直線
  362.         for( i = 0; i < lines->total; i++ )
  363.         CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
  364.         cvLine( pImage, line[0], line[1], CV_RGB(255,0,0), 3, 8 );
  365.     cvNamedWindow( "Hough Line Transform", 1 );
  366.     cvShowImage( "Hough Line Transform", pImage);
  367.         cvDestroyWindow( " Hough Line Transform " );   
  368. void CImageView::OnImageHoughCircle()
  369.     CvSeq* circles = NULL;
  370.     if(img->nChannels != 1)
  371.          cvCvtColor( pImage, pImg8u, CV_BGR2GRAY );
  372.     else
  373.          cvCopy(pImage, pImg8u);
  374.     //平滑化
  375.     cvSmooth( pImg8u, pImg8u, CV_GAUSSIAN, 7, 7 );
  376.         //Hough圓變換
  377.     circles = cvHoughCircles( pImg8u, storage, CV_HOUGH_GRADIENT, 2, pImg8u->height/4, 250, 55 );
  378.         // 畫出識别出的圓
  379.         for( i = 0; i < circles->total; i++ )
  380.                   float* p = (float*)cvGetSeqElem( circles, i );
  381.                   cvCircle(pImage, cvPoint(cvRound(p[0]),cvRound(p[1])), cvRound(p[2]), CV_RGB(255,0,0), 3, 8, 0 );
  382.     cvNamedWindow( "Hough Circle Transform", 1 );
  383.     cvShowImage( "Hough Circle Transform", pImage);
  384.         cvDestroyWindow( " Hough Circle Transform " );