C++之OpenCV入門到提高006:影像混合

可均可可發表於2024-12-06
一、介紹
    今天是這個系列《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 的第六篇文章,其實也沒那麼難,感覺是不是還是很好入門的,那就繼續。初見成效,繼續努力。皇天不負有心人,不忘初心,繼續努力,做自己喜歡做的,開心就好。

相關文章