#include <QCoreApplication> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp>
using namespace cv; int main() { Mat Valley = imread("/home/ttwang/Valley.jpg"); Mat ValleyLogo = imread("/home/ttwang/ValleyLogo.jpg"); namedWindow("[1] ValleyPic"); imshow("[1] ValleyPic",Valley); namedWindow("[2] ValleyLogo"); imshow("[2] ValleyLogo",ValleyLogo); Mat valleyROI;
/******************實現兩個圖像混合****************************/
valleyROI = Valley(Rect(800,350,ValleyLogo.cols,ValleyLogo.rows)); addWeighted(valleyROI,0.5,ValleyLogo,0.3,0.,valleyROI); namedWindow("valley+logo"); imshow("valley+logo",Valley); // imwrite("",Valley);
waitKey(0); return 0; }
二、創建滑動條:createTrackbar()函數 (利用滑動條實現兩幅圖的Alpha混合)
1 #include <QCoreApplication> //本人所用的IDE是QT,,終端編譯時不需要該聲明
2 #include <opencv2/core/core.hpp>
3 #include <opencv2/highgui/highgui.hpp>
4 #include <opencv2/imgproc/imgproc.hpp>
5 using namespace cv; 6
7 #define WINDOW_NAME "[Alpha]" //窗口名的宏定義
8
9 const int g_nMaxAlphaValue = 100; 10 int g_nAlphaValueSlider; 11 double g_dAlphaValue; 12 double g_dBetaValue; 13
14 Mat g_srcImage1; 15 Mat g_srcImage2; 16 Mat g_dstImage; 17 /**********響應滑動條的回調函數*************/
18 void on_Trackbar( int ,void*) 19 { 20 g_dAlphaValue = (double) g_nAlphaValueSlider/g_nMaxAlphaValue; 21 g_dBetaValue = (1.0 - g_dAlphaValue); 22 //根據Alpha beta的值進行線性混合
addWeighted(g_srcImage1,g_dAlphaValue,g_srcImage2,g_dBetaValue,0.0,g_dstImage); 23 imshow(WINDOW_NAME,g_dstImage); 24 } 25
26 int main() 27 { 28 g_srcImage1 = imread("/home/ttwang/11.jpg"); //兩幅圖的尺寸要相同,否則出現如下圖錯誤 29 g_srcImage2 = imread("/home/ttwang/12.jpg"); 30
31 g_nAlphaValueSlider = 70; 32 namedWindow(WINDOW_NAME,1); 33
34 char TrackbarName[50]; 35 sprintf(TrackbarName,"透明值 %d", g_nMaxAlphaValue); 36 createTrackbar(TrackbarName,WINDOW_NAME, &g_nAlphaValueSlider, g_nMaxAlphaValue,on_Trackbar); 37 on_Trackbar(g_nAlphaValueSlider,0); 38
39 waitKey(0); 40 return 0; 41
42 }
由於程序不是直接粘貼過來的,按該程序進行編譯時候,總出現錯誤,可以參考下面的鏈接 感謝分享
三、鼠標操作:SetMouseCallback()函數
#include <QCoreApplication> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace cv; #define WINDOW_NAME "[Program window]" //為窗口標題定義的宏 /******************全局函數的聲明********************/ void on_MouseHandle(int event,int x, int y, int flags, void* param); void DrawRectangle(cv::Mat& img, cv::Rect box); void ShowHelpText(); /******************全局變量聲明*********************/ Rect g_rectangle; bool g_bDrawingBox = false;//是否繪制 RNG g_rng(12345); int main() { g_rectangle = Rect(-1,-1,0,0); Mat srcImage(600,800,CV_8UC3),tempImage; srcImage.copyTo(tempImage); g_rectangle = Rect(-1,-1,0,0); srcImage = Scalar::all(0); //設置鼠標操作回調函數 namedWindow(WINDOW_NAME); setMouseCallback(WINDOW_NAME,on_MouseHandle,(void*)&srcImage); while(1) { srcImage.copyTo(tempImage); //復制源圖到臨時變量 if(g_bDrawingBox) DrawRectangle(tempImage,g_rectangle);//當繪制標識符為真,進行繪制 imshow(WINDOW_NAME,tempImage); if(waitKey(10) == 27) break; //按下Esc,程序退出 } return 0; } /*********鼠標回調函數,根據不同的鼠標事件進行不同的操作*******************/ void on_MouseHandle(int event, int x, int y, int flags, void *param) { Mat& image = *(cv::Mat*) param; switch (event) { //鼠標移動消息 case EVENT_MOUSEMOVE: { if(g_bDrawingBox)//如果是否進行繪制額標識符為真,則記錄下長和寬到RECT型變量中 { g_rectangle.width = x - g_rectangle.x; g_rectangle.height = y- g_rectangle.y; } } break; //左鍵按下消息 case EVENT_LBUTTONDOWN: { g_bDrawingBox = true; g_rectangle = Rect(x,y,0,0);//記錄起始點 } break; //左鍵抬起消息 case EVENT_LBUTTONUP: { g_bDrawingBox = false; //置標識符為false //對寬和高小於0的進行處理 if(g_rectangle.width < 0) { g_rectangle.x += g_rectangle.width; g_rectangle.width *= -1; } if(g_rectangle.height < 0) { g_rectangle.y += g_rectangle.height; g_rectangle.height *= -1; } //調用回調函數進行繪制 DrawRectangle( image, g_rectangle); } break; } } /********************自定義的矩形繪制函數DrawRectangle() ********************/ void DrawRectangle(cv::Mat& img, cv::Rect box) { rectangle(img,box.tl(),box.br(),Scalar(g_rng.uniform(0,255),g_rng.uniform(0,255),g_rng.uniform(0,255))); }
四章、OpenCV數據結構與基本繪圖
1. Mat M(2,2,CV_8UC3,Scalar(0,0,255)); //使用Mat()構造函數創建Mat對象
兩行兩列、CV_8UC3: CV_[位數][帶符號與否]C[通道數] Scalar是個short類型的向量,可以使用指定的值來初始化矩陣
2.Mat M; M.create(4,4,CV_8UC3); //使用create()函數創建Mat對象,,此方法不能為矩陣設初值
3.顏色的表示類:Scalar()是具有四個元素的數組,,第四個用不到,則不寫 格式如下:
Scalar(a, b, c)定義的RGB顏色值:紅色分量c 綠色分量b 藍色分量 a
4.尺寸的表示類: Size() 常用格式: Size(5,5)表示構造出的Size高度和寬度都為5
5.矩形的表示類: Rect類的成員有x,y,width,height,分別為左上角的坐標和矩形的寬、高
格式: Rect rect(0,0,200,400)
6.顏色空間轉換:cvtColor()函數 格式:cvtColor(InputArraysrc, OutputArray dst, int code, int dstCn=0)
第一個參數:輸入圖像;
第二個參數:輸出圖像;
第三個參數:顏色空間轉換的標識符; (詳見:P98)
第四個參數:目標圖像的通道數,若為0,則表示其取源圖像的通道數。
7.基本圖型的繪制涉及的函數: (通過例程學習 P100)
繪制直線的line函數
繪制橢圓的ellipse函數
繪制矩形的rectangle函數
繪制圓的circle函數
繪制填充的多邊形的fillPloy函數
第五章 core組件進階
1.計時函數: getTickCount()和getTickFrequency()
getTickCount()函數返回CPU自某個事件以來走過的時鍾周期數
getTickFrequency()函數返回CPU一秒鍾走過的周期數
顯然: 二者結合可以實現對某種圖像處理方法的計時
double time0 = static_cast<double>(getTickCount()); //記錄起始時間
time0= ((double)getTickCount() - time0)/getTickFrequency();////計算運行時間並輸出
cout<<"\t此方法運行時間為:"<<time0<<"秒"<<endl; //輸出運行時間
2.訪問圖像中像素的幾種方法 (簡單介紹,具體P110)
需要先明白以下知識:
(1) Mat類的公有成員變量cols和rows給出了圖像的寬和高
image.cols image.rows
(2) Mat類的成員函數channels()用於返回圖像的通道數;
灰度圖像通道數1,彩色圖像通道數為3 image.channels()
(4) 每一行的像素個數= image.cols*image.channels()
a.直接遍歷,使用Mat里的成員函數data
/*********只用於訪問連續空間********/ Mat mat (3000,4000,CV_8UC3) int es = mat.eleSize(); //定義步長,因為定義為3通道的,實質該值為3 int size = mat.rows*mat.cols*es; for(int i = 0; i < size; i += es) { mat.data[i] = 255; // B通道 mat.data[i+1] = 0; // G通道 mat.data[i+2] = 0; // R通道 }
b.直接訪問不連續空間
for (int row = 0; row < mat.rows; row++) { for (int col = 0; col < mat.cols; col++) { (&mat.data[row*mat.step])[col*es] = 0; (&mat.data[row*mat.step])[col*es + 1] = 0; (&mat.data[row*mat.step])[col*es + 2] = 255; } }
c.通過opencv ptr模板函數遍歷
1 for (int row = 0; row < mat.rows; row++) 2 { 3 for (int col = 0; col < mat.cols; col++) 4 { 5 Vec3b *c = mat.ptr<Vec3b>(row,col); 6 c->val[0] = 0;
8 c->val[1] = 255;
10 c->val[2] = 0; } 13 }
c.通過at遍歷
1 for (int row = 0; row < mat.rows; row++) 2 { 3 for (int col = 0; col < mat.cols; col++) 4 { 5 Vec3b &m = mat.at<Vec3b>(row, col); 6 m[0] = 0; 7 m[1] = 0; 8 m[2] = 255; 9 } 10 }
d.通過迭代器遍歷
1 auto it = mat.begin<Vec3b>(); //自動類型匹配auto
2 auto it_end = mat.end<Vec3b>(); 3 for (; it != it_end; it++) 4 { 5 (*it).val[0] = 0; 6 (*it).val[1] = 0; 7 (*it).val[2] = 255; 8 }
3.感興趣區域ROI /******表示方法一 Rect矩形區域*******/ Mat imageROI imageROI = image(Rect(500,250,logo.cols,logo.rows)); //image為已經載入好的圖片
/******表示方法二 Range指定感興趣的行和列********/
imageROI = image(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols)); //image為已經載入好的圖片
4.利用addWeighted可實現圖像線性混合 數學公式: dst = src1[I] * alpha + src2[I]*beta + gamma (P117)
5.分離顏色通道、多通道圖像混合 通道分離:split()函數,將一個3通道圖像轉換成3個單通道 通道合並:merge()函數 ###例程:(課本P127,以多通道混合-藍色分量部分為例) ###平台:QT5.7.1+OpenCV3.2.0 ###時間:2017年12月11日 /********建立QT控制台程序*********/ #include <QCoreApplication> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream>
using namespace std; using namespace cv; //全局函數聲明
bool MultiChannelBlending(); int main() { if(MultiChannelBlending()) { cout << endl << "\n運行成功,得到目標圖像" << endl; } waitKey(0); return 0; } /*********多通道混合的實現函數*********/
bool MultiChannelBlending() { Mat srcImage; Mat logoImage; vector<Mat> channels; /********** 藍色分量 *************/ Mat imageBlueChannel; logoImage = imread("/home/ttwang/Valley_logo.jpg",0);//一定要讀入會灰度圖像,不然addWeighted()會因為類型不匹配而報錯
srcImage = imread("/home/ttwang/Valley.jpg"); split(srcImage,channels); //將一個3通道圖像轉換成3個單通道
imageBlueChannel = channels.at(0); //將原圖的藍色通道引用返回給imageBlueChannel
addWeighted(imageBlueChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0,logoImage,0.5,0.,imageBlueChannel(Rect(500,250,logoImage.cols,logoImage.rows))); merge(channels,srcImage);//將三個單通道重新合並成一個三通道
namedWindow("src+LogoBlue"); imshow("src+LogoBlue",srcImage); /*******綠色分量 ******/ Mat imageGreenChannel; logoImage = imread("/home/ttwang/Valley_logo.jpg",0); srcImage = imread("/home/ttwang/Valley.jpg"); split(srcImage,channels); //將一個3通道圖像轉換成3個單通道
imageGreenChannel = channels.at(1); addWeighted(imageGreenChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0,logoImage,0.5,0.0,imageGreenChannel(Rect(500,250,logoImage.cols,logoImage.rows))); merge(channels,srcImage);//將三個單通道重新合並成一個三通道
namedWindow("src+LogoGreen"); imshow("src+LogoGreen",srcImage); /*******紅色分量 ******/ Mat imageRedChannel; logoImage = imread("/home/ttwang/Valley_logo.jpg",0); srcImage = imread("/home/ttwang/Valley.jpg"); split(srcImage,channels); //將一個3通道圖像轉換成3個單通道
imageRedChannel = channels.at(2); addWeighted(imageRedChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0,logoImage,0.5,0.0,imageRedChannel(Rect(500,250,logoImage.cols,logoImage.rows))); merge(channels,srcImage);//將三個單通道重新合並成一個三通道
namedWindow("src+LogoRed"); imshow("src+LogoRed",srcImage); return true; }
6.圖像對比度、亮度調整 公式: g(i,j)=a*f(i,j)+b; (opencv控制圖像對比度和亮度的理論公式) 參數a(a>0)通常被成為增益,控制圖像的對比度 參數b稱為偏置,控制圖像的亮度 訪問圖片中的像素:(使用三個for循環,語法:image.at<Vec3b>(y,x)[c]) 其中,y是像素所在的行,x是像素所在的列,c是B、G、 R(對應0、1、2)
7.離散傅里葉變換(詳細參照課本P135) 參考資料及函數說明,參照下面的鏈接: opencv2教程之離散型傅里葉變換