【opencv實踐】圖像醃膜Mask的常規操作你真的信手拈來嗎?

在這裏插入圖片描述
我對圖像醃膜的含義一直有些模糊,今天寫了幾行代碼,證明了我這模糊的印象倒是正確的。今天借一個給圖片添加水印的小例子,給大家總結一些圖像醃膜的常規操作。

首先先了解一下圖像醃膜的定義:。。。

額,找了一圈好像並沒有啥特別正式的官方定義/我記得曾在書上看到過來着~

其實醃膜可以抽象爲一個黑白相間的圖,或者膜,黑色的像素值爲0,白色爲1。將這個膜和你原本的圖像重合到一起,黑色區域被忽略,僅剩下白色區域,就是這樣。

就像把白色區域的圖像摳出來一樣,”摳圖“就是醃膜Mask最常乾的事。

廢話少說,咱們開始咱們的小實踐吧。

一:普通加水印:圖像加和

先看一下今天要處理的水印圖,一張白底紅字的logo圖:

在這裏插入圖片描述
然後再看一下我們的底圖:
在這裏插入圖片描述
我們要吧logo,也就是水印加到左上角去,首先我們想到的就是在左上角掏個和logo圖片一樣大小的ROI區域出來,然後直接將logo添加到ROI區域裏,來看代碼:

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
  Mat srcImage, logoImage, dstImage;
  srcImage = imread("1.jpg");//讀取底圖
  logoImage = imread("logo1.jpg");//讀入logo圖片
  //【1】ROI區域與原圖直接混合
  Mat imgROI = srcImage(Rect(20, 20, logoImage.cols, logoImage.rows));  //Rect方法定義ROI,注意寬是:cols;高是rows。
  logoImage.copyTo(imgROI);//將logo圖片拷貝到img的ROI上(注意copyTo函數要求兩圖像大小和類型都相同,否則無效)
  imshow("混合後", srcImage);
  waitKey(0);
  return 0;
}

運行效果如下:
在這裏插入圖片描述
可以看到白色的底並不是我們想要的,所以就需要用到醃膜的相關摳圖,將五個紅色的字”摳“出來。

二:摳圖操作加水印

首先我們要完成的操作就是將這五個字識別出來,也就是摳出來,對於我們這個logo自然很簡單啦,只需要轉灰度,然後閾值化操作一下就可以了:

1,我們先定義一個醃膜Mask,然後將logo圖像轉爲灰度圖像存入到Mask中:

 Mat mask;//定義醃膜
  cvtColor(logoImage, mask, COLOR_BGR2GRAY);//將logo轉成灰度圖

處理後得到如下灰度圖:
在這裏插入圖片描述
2,對醃膜Mask這個圖像矩陣進行取反操作:


bitwise_not(mask, mask);//對mask圖像取反,白色(255)變成黑色(0)

對於上面操作我們需要多加解釋一下。

圖像的基本運算有很多種,比如兩幅圖像可以相加相減、相乘、相除、位運算、平方根、對數、絕對值等;

圖像也可以放大、縮小、旋轉,還可以截取其中的一部分作爲ROI(感興趣區域)進行操作,各個顏色通道還可以分別提取及對各個顏色通道進行各種運算操作。

所以我們自然可以對圖像進行與,或,非,異或等操作啦。

//bitwise_and、bitwise_or、bitwise_xor、bitwise_not這四個按位操作函數。
void bitwise_and(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray());//dst = src1 & src2
void bitwise_or(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray());//dst = src1 | src2
void bitwise_xor(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray());//dst = src1 ^ src2
void bitwise_not(InputArray src, OutputArray dst,InputArray mask=noArray());//dst = ~src
  • bitwise_and:對二進制數據進行“與”操作,即對圖像(灰度圖像或彩色圖像均可)每個像素值進行二進制“與”操作,1&1=1,1&0=0,0&1=0,0&0=0
  • bitwise_or:對圖像(灰度圖像或彩色圖像均可)每個像素值進行二進制“或”操作,1|1=1,1|0=1,0|1=1,0|0=0
  • bitwise_xor:對圖像(灰度圖像或彩色圖像均可)每個像素值進行二進制“異或”操作,1 ^ 1=0,1 ^ 0=1,0 ^ 1=1,0 ^ 0=0
  • bitwise_not:對圖像(灰度圖像或彩色圖像均可)每個像素值進行二進制“非”操作,~1=0, ~ 0=1

引用自:
https://blog.csdn.net/u011028345/article/details/77278467

爲什麼要對我們處理後得灰度圖進行取反操作呢?因爲我們開頭說過,在醃膜中黑色無效,白色有效,而我們得灰度圖的底色確實白色的,字確實黑色的,所以進行取反操作,結果如下:
在這裏插入圖片描述
3,對取反後的圖進行閾值化操作,摳出五個字:

threshold(mask, mask, 100, 255, THRESH_BINARY);//對mask進行二值化,將mask進一步處理

得到如下圖所示:
在這裏插入圖片描述
4,進行圖像融合

通過上面步驟,我們得到了如上圖所示的黑底白字的醃膜了,下面就把醃膜加入到圖像融合中去。

Mat imgROI = srcImage(Rect(20, 20, logoImage.cols, logoImage.rows));
 logoImage.copyTo(imgROI, mask); //將logo拷貝到imgROI上,掩碼爲不爲0的部分起作用,爲0的部分不起作用

可以看到copyTo方法中,有第二個參數mask,我們只需要傳給他就可以了,很多現成的函數接口都有圖像醃膜這個參數,現在你知道怎麼用了吧。

來看看效果圖:
在這裏插入圖片描述
是不是變成水印了呢?

三:添加非矩形的Mask區域

我們選取ROI區域一般都是用矩形,所以圈出來的區域都是矩形的,如何添加非矩形的呢?

首先我們讀取我們的logo圖片,爲了觀察方便我們換了如下一個logo:

Mat logo2Image = imread("logo2.jpg");//讀取logo2

在這裏插入圖片描述
需要強調的是,接下來我們的操作都是基於這張logo的大小來進行的:
1,在原圖開出logo大小的ROI區域:


Mat imgROI = srcImage(Rect(20, 20, logo2Image.cols, logo2Image.rows));

2,創建一個同logo一樣大的純黑的醃膜mask:

Mat mask = Mat::zeros(logo2Image.size(), CV_8UC1);

3,在黑色醃膜上畫出一個白色內填充的圓:

circle(mask, Point(mask.rows / 2, mask.cols / 2), 120, Scalar(255), -1, 8);

4,最後就還是一樣的操作,將logo複製到原圖ROI區域中去,並申明醃膜:


logo2Image.copyTo(imgROI, mask);//將logo拷貝到imgROI上,掩碼爲不爲0的部分起作用,爲0的部分不起作用

運行效果如下圖:
在這裏插入圖片描述
雖然有些醜,但好看又不能拿來找對象,所以就這樣叭。

到此,會添加圓形了,其他非規則的形狀就要通過關鍵點來進行確定了,我們只需要將上述步驟中的第三步:在黑色醃膜上畫圓變成畫不規則多邊形就行了,如下:

vector<vector<Point>> contour;
  vector<Point> pts;
  pts.push_back(Point(30, 45));
  pts.push_back(Point(100, 15));
  pts.push_back(Point(300, 145));
  pts.push_back(Point(330, 240));
  pts.push_back(Point(50, 250));
  contour.push_back(pts);
  drawContours(mask, contour, 0, Scalar::all(255), -1);

創建多個點,然後進行輪廓繪製就好了,drawContours這個函數最後傳的參數-1爲線寬,當爲正時爲寬度,爲負則爲向內填充,和畫圓函數類似。
在這裏插入圖片描述

THE END

今天就到這裏了,圖像醃膜這個東西我是看opencv-python的官方文檔時想起來的,然後就想總結一下關於它的一些常規操作,如果有想看官方中文文檔的可以自己去公衆號【行走的機械人】回覆【視覺電子書】,

我看的所有計算機視覺的書都在裏面了:
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章