今天是這個系列《C++之 Opencv 入門到提高》的第六篇文章。這篇文章也不難,介紹如何影像的混合操作。影像本質上也是資料,既然是資料,我們就可以針對兩張或者多張圖片進行加、減、乘、除的操作,這些操作太生硬了,這種混和並不是我們想要的,針對混合有專門的介面實現,我們可以對比一下之間的差異。這都是基礎,為以後的學習做好鋪墊。雖然操作很簡單,但是背後有很多東西需要我們深究,才能做到知其然知其所以然。OpenCV 具體的簡介內容,我就不多說了,網上很多,大家可以自行腦補。
OpenCV 的官網地址:https://opencv.org/,元件下載地址:https://opencv.org/releases/。
OpenCV 官網學習網站:https://docs.opencv.ac.cn/4.10.0/index.html
我需要進行說明,以防大家不清楚,具體情況我已經羅列出來。
作業系統:Windows Professional 10(64位)
開發元件:OpenCV – 4.10.0
開發工具:Microsoft Visual Studio Community 2022 (64 位) - Current版本 17.8.3
開發語言:C++(VC16)
二、知識學習
介面很簡單,不用多說,仔細研究一下原理更有用。
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 #include <math.h> 4 5 using namespace std; 6 using namespace cv; 7 8 /// <summary> 9 /// 影像混合 10 /// 1、理論介紹 11 /// 2、相關API(addWeighted) 12 /// </summary> 13 /// <returns></returns> 14 int main6() 15 { 16 //1、理論介紹 17 //線性混合操作:g(x)=(1-a)f0(x)+af1(x) 其中 a 的取值範圍 0-1 之間。 18 // f0(x) 表示第一幅輸入影像,f1(x) 表示第二幅輸入影像,a 表示權重,表示第一幅圖佔的權重,或者是第二幅圖佔的權重,g(x)表示生成後的影像。 19 // Mat 影像是一個二維矩陣,就是具有行和列的資料陣列,如果我們針對兩張圖片的每個畫素點進行上述操作,最後就會得到混合後的影像。 20 21 //2、void addWeighted(InputArray src1, double alpha, InputArray src2,double beta, double gamma, OutputArray dst, int dtype = -1) 22 /* 23 函式 addWeighted 計算兩個陣列的加權和,如下所示: 24 \f[\texttt{ dst } (I) = \texttt{ saturate } (\texttt{ src1 } (I) * \texttt{ alpha } + \texttt{ src2 } (I) * \texttt{ beta } + \texttt{ gamma })\f] 25 其中 I 是陣列元素的多維索引。對於多通道陣列,每個通道都是獨立處理的。 26 該函式可以替換為矩陣表示式:dst = src1*alpha + src2*beta + gamma; 27 28 @note Saturation is not applied when the output array has the depth CV_32S.You may even get 29 result of an incorrect sign in the case of overflow. 30 @param src1 第一張輸入的影像陣列. 31 @param alpha 第一張輸入影像的 alpha 值. 32 @param src2 第二個輸入影像陣列的大小和通道號與 src1 相同。 33 @param beta 第二個輸入影像的 alpha 權重。 34 @param gamma 新增到每個 sum 的標量。 35 @param dst 輸出影像陣列,該陣列具有與 Input 影像陣列相同的大小和通道數. 36 @param dtype 輸出影像的可選深度:當兩個輸入影像具有相同的深度時,可以將 dtype 設定為-1,這相當於src1.depth()。 37 @sa add, subtract, scaleAdd, Mat::convertTo 38 */ 39 40 41 //注意:影像大小和型別必須一致。 42 Mat src1,src2; 43 src1 = imread("D:\\360MoveData\\Users\\Administrator\\Desktop\\TestImage\\guanyu.jpg",IMREAD_COLOR); 44 src2 = imread("D:\\360MoveData\\Users\\Administrator\\Desktop\\TestImage\\guanyu2.jpg", IMREAD_COLOR); 45 if (src1.empty()) 46 { 47 cout << "影像1載入失敗!!!" << endl; 48 return -1; 49 } 50 if (!src2.data) 51 { 52 cout << "影像2載入失敗!!!" << endl; 53 return -1; 54 } 55 56 if (src1.rows == src2.rows && src1.cols == src2.cols && src1.type() == src2.type()) 57 { 58 Mat dst = Mat::zeros(src1.size(),src1.type()); 59 double alpha = 0.1; 60 addWeighted(src1, alpha, src2, (1 - alpha), 0, dst); 61 //add(src1, src2, dst); 62 //multiply(src1, src2, dst); 63 64 imshow("原圖1", src1); 65 imshow("原圖2", src2); 66 namedWindow("混合視窗", WINDOW_AUTOSIZE); 67 imshow("混合視窗", dst); 68 } 69 else 70 { 71 cout << "影像1和影像2不同!!!" << endl; 72 } 73 74 waitKey(0); 75 76 return 0; 77 }
影像混合的效果:
原圖1:
原圖2:
混合圖:
仔細看背景,是有另外一張圖的。
影像相加的效果:
影像相乘的效果:
沒法看了,太亮了,相乘的結果就是接近255最大值,也就是接近白色了。
三、總結
這是 C++ 使用 OpenCV 的第六篇文章,其實也沒那麼難,感覺是不是還是很好入門的,那就繼續。初見成效,繼續努力。皇天不負有心人,不忘初心,繼續努力,做自己喜歡做的,開心就好。