1. 程式人生 > >OpenCv影象疊加時png圖片的透明部分無法透明的解決辦法

OpenCv影象疊加時png圖片的透明部分無法透明的解決辦法

        這一個月以來都在做虛擬現實的大作業,我們組想要做一個在攝像頭讀入的視訊流中進行人臉識別並且在五官上新增物體這樣一個程式。
        當然人臉識別什麼的就用了網上現有的一些程式,我們要做的就是在畫面中載入圖片於特定的座標上。
        關於如何疊加圖片我參考了下面兩篇文章,如果想做加水印、圖片疊加相關程式碼的建議先看這個裡面已經講解的蠻清楚了: 
        http://www.cnblogs.com/mfryf/archive/2012/03/08/2385304.html 
        http://www.tuicool.com/articles/EvyEfq


        ***但是***存在一個問題,在第一篇文章下面的回覆中也有人提到了,用背景透明的png影象的時候不能實現透明的效果,透明的部分現實的是白色的,png影象是用photoshop挖去背景得到的。經過我到處查資料什麼的得出,這個結果的可能原因應該是版本的問題。2.4之後的opencv的imread函式不能顯示第四個通道了(?這個結論存疑,我也是在別的文章中看到的)。
        然而我想cvshowimage()是可以顯示四個通道的吧,但是iplimage和mat格式互相轉換還有函式不通用也是有一些困難,這個嘗試就失敗了。
參考了很多地方的文章和程式碼都沒有能夠解決這個問題的辦法,一時間有些頭大了感覺可能這個作業沒法達到需要的效果了……不過還好看別人的文章受到一些啟發,就算版本不一樣會存在一些問題,利用掩模的話應該也是可以解決的吧?然後抱著試一試的想法實驗了下寫了個小程式(基於上面文章中的程式碼改動了一下)。
        掩模mask是單通道影象,並且只有黑和白(兩個值0和1),0就是不顯示,1就是顯示。因此我考慮將png影象轉化成灰度圖進行二值化處理來得到掩模影象。由於背景已經是白色的了,所以直接設定一個閾值吧就設成254(因為不知道咋設定成255的樣子)。但是這個閾值分割的結果是保留了背景部分,目標部分的值都是0了,所以再進行一下反色的處理,255減一下就好。
        設定感興趣區域的時候發現了一個問題(大概在大大的眼中並不算問題的問題OTL),就是因為logo圖片也是有尺寸的,所以rect()中的座標設定的時候要計算到logo的尺寸,否則就會超過原圖片的邊界,出現記憶體溢位r6010 abort()has been called 的問題。
        其實想一想不用非得png格式的影象好像各種格式的影象也都可以這樣處理了吧……
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <cv.h>
using namespace cv;


int main(){
    Mat image = imread("1.jpg");
    Mat logo = imread("2.png");
    Mat mask = imread("2.png",0); //注意要是灰度圖才行
    threshold(mask,mask,254,255,CV_THRESH_BINARY);
    Mat mask1 = 255 - mask; //掩模反色
    //imshow("img",mask1);
    Mat imageROI;
    imageROI = image(Rect(480,320,logo.cols,logo.rows));
    logo.copyTo(imageROI,mask1);
    namedWindow("result");
    imshow("result",image);
    imwrite("result.jpg",image);
    waitKey();
    return 0;

}

        處理完的結果就是下面這個樣子,當然我不是按照水印的做法來做的的,沒有改變透明度什麼的……寫這個東西就是記錄一下解決問題的思路,其實程式碼還有想法都是可以完善的,主要是網上都沒有關於這個問題的解決辦法(也可能是我沒找到)所以趕緊寫下來省得以後忘記了……/(ㄒoㄒ)/~~
image:

logo: 
 
result: 



    1619