1. 程式人生 > >Opencv影象處理之詳解掩膜mask

Opencv影象處理之詳解掩膜mask

1.在OpenCV中我們經常會遇到一個名字:Mask(掩膜)。很多函式都使用到它,那麼這個Mask到底什麼呢?

2.如果我們想要裁剪影象中任意形狀的區域時,應該怎麼辦呢? 
答案是,使用掩膜(masking)。 
我們先看一下掩膜的基礎。影象的位運算。

影象基本運算


影象的基本運算有很多種,比如兩幅影象可以相加、相減、相乘、相除、位運算、平方根、對數、絕對值等;影象也可以放大、縮小、旋轉,還可以擷取其中的一部分作為ROI(感興趣區域)進行操作,各個顏色通道還可以分別提取及對各個顏色通道進行各種運算操作。總之,對於影象可以進行的基本運算非常的多,只是挑了些常用的操作詳解。
  1. void add(InputArray src1, InputArray src2, OutputArray dst,InputArray mask=noArray()
    , int dtype
    =-1);//dst = src1 + src2
  2. void subtract(InputArray src1, InputArray src2, OutputArray dst,InputArray mask=noArray(), int dtype=-1);//dst = src1 - src2
  3. void multiply(InputArray src1, InputArray src2,OutputArray dst, double scale=1, int dtype=-1);//dst = scale*src1*src2
  4. void divide(InputArray src1, InputArray src2, OutputArray dst,double
    scale=1, int dtype=-1)
    ;//dst = scale*src1/src2
  5. void divide(double scale, InputArray src2,OutputArray dst, int dtype=-1);//dst = scale/src2
  6. void scaleAdd(InputArray src1, double alpha, InputArray src2, OutputArray dst);//dst = alpha*src1 + src2
  7. void addWeighted(InputArray src1, double alpha, InputArray src2,double
    beta, double gamma, OutputArray dst, int dtype=-1)
    ;//dst = alpha*src1 + beta*src2 + gamma
  8. void sqrt(InputArray src, OutputArray dst);//計算每個矩陣元素的平方根
  9. void pow(InputArray src, double power, OutputArray dst);//src的power次冪
  10. void exp(InputArray src, OutputArray dst);//dst = e**src(**表示指數的意思)
  11. void log(InputArray src, OutputArray dst);//dst = log(abs(src))

上述的基本操作中都屬於將基礎數學運算應用於影象畫素的處理中,下面將著重介紹

  1. bitwise_and、bitwise_or、bitwise_xor、bitwise_not這四個按位操作函式。
  2. void bitwise_and(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray());//dst = src1 & src2
  3. void bitwise_or(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray());//dst = src1 | src2
  4. void bitwise_xor(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray());//dst = src1 ^ src2
  5. 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=0,0|1=0,0|0=0
bitwise_xor是對二進位制資料進行“異或”操作,即對影象(灰度影象或彩色影象均可)每個畫素值進行二進位制“異或”操作,1^1=0,1^0=1,0^1=1,0^0=0
bitwise_not是對二進位制資料進行“非”操作,即對影象(灰度影象或彩色影象均可)每個畫素值進行二進位制“非”操作,~1=0,~0=1

為了便於大家進一步理解,下面給出測試程式碼:

# opencv 影象的基本運算

# 匯入庫
import numpy as np
import argparse
import cv2

# 構建引數解析器
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Path to the image")
args = vars(ap.parse_args())

# 載入影象
image = cv2.imread(args["image"])
cv2.imshow("image loaded", image)

# 建立矩形區域,填充白色255
rectangle = np.zeros(image.shape[0:2], dtype="uint8")
cv2.rectangle(rectangle, (25, 25), (275, 275), 255, -1) # 修改這裡
cv2.imshow("Rectangle", rectangle)

# 建立圓形區域,填充白色255
circle = np.zeros(image.shape[0:2], dtype="uint8")
cv2.circle(circle, (150, 150), 150, 255, -1) # 修改
cv2.imshow("Circle", circle)


# 在此例(二值影象)中,以下的0表示黑色畫素值0, 1表示白色畫素值255
# 位與運算,與常識相同,有0則為0, 均無0則為1
bitwiseAnd = cv2.bitwise_and(rectangle, circle)
cv2.imshow("AND", bitwiseAnd)
cv2.waitKey(0)



# 非運算,非0為1, 非1為0
bitwiseNot = cv2.bitwise_not(circle)
cv2.imshow("NOT", bitwiseNot)
cv2.waitKey(0)

# 或運算,有1則為1, 全為0則為0
bitwiseOr = cv2.bitwise_or(rectangle, circle)
cv2.imshow("OR", bitwiseOr)
cv2.waitKey(0)

# 異或運算,不同為1, 相同為0
bitwiseXor = cv2.bitwise_xor(rectangle, circle)
cv2.imshow("XOR", bitwiseXor)
cv2.waitKey(0)


可以看到,原圖是一張星空夜景圖。

效果如下:




為了便於展示,後面我只擷取部分割槽域效果:



掩膜(mask)


在有些影象處理的函式中有的引數裡面會有mask引數,即此函式支援掩膜操作,首先何為掩膜以及有什麼用,如下:


數字影象處理中的掩膜的概念是借鑑於PCB製版的過程,在半導體制造中,許多晶片工藝步驟採用光刻技術,用於這些步驟的圖形“底片”稱為掩膜(也稱作“掩模”),其作用是:在矽片上選定的區域中對一個不透明的圖形模板遮蓋,繼而下面的腐蝕或擴散將隻影響選定的區域以外的區域。
影象掩膜與其類似,用選定的影象、圖形或物體,對處理的影象(全部或區域性)進行遮擋,來控制影象處理的區域或處理過程。 
數字影象處理中,掩模為二維矩陣陣列,有時也用多值影象,影象掩模主要用於:
①提取感興趣區,用預先製作的感興趣區掩模與待處理影象相乘,得到感興趣區影象,感興趣區內影象值保持不變,而區外影象值都為0。 
②遮蔽作用,用掩模對影象上某些區域作遮蔽,使其不參加處理或不參加處理引數的計算,或僅對遮蔽區作處理或統計。 
③結構特徵提取,用相似性變數或影象匹配方法檢測和提取影象中與掩模相似的結構特徵。 
④特殊形狀影象的製作。

在所有影象基本運算的操作函式中,凡是帶有掩膜(mask)的處理函式,其掩膜都參與運算(輸入影象運算完之後再與掩膜影象或矩陣運算)。

掩膜例項

如開篇所提問題2,要對一幅圖進行摳圖(裁剪)操作,這就要用到Mask了,那麼就以摳圖為例,解釋Mask在裡面的作用。同樣以上圖為例,從原圖中裁剪小樹。

我們利用OR結果(其他結果也行),修改調整後,

程式碼如下:

# opencv 影象的基本運算

# 匯入庫
import numpy as np
import argparse
import cv2

# 構建引數解析器
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Path to the image")
args = vars(ap.parse_args())

# 載入影象
image = cv2.imread(args["image"])
cv2.imshow("image loaded", image)

# 建立矩形區域,填充白色255
rectangle = np.zeros(image.shape[0:2], dtype="uint8")
cv2.rectangle(rectangle, (360, 348), (660, 570), 255, -1) # 修改這裡
cv2.imshow("Rectangle", rectangle)

# 建立圓形區域,填充白色255
circle = np.zeros(image.shape[0:2], dtype="uint8")
cv2.circle(circle, (520, 455), 140, 255, -1) # 修改
cv2.imshow("Circle", circle)

''' 
# 在此例(二值影象)中,以下的0表示黑色畫素值0, 1表示白色畫素值255
# 位與運算,與常識相同,有0則為0, 均無0則為1
bitwiseAnd = cv2.bitwise_and(rectangle, circle)
cv2.imshow("AND", bitwiseAnd)
cv2.waitKey(0)



# 非運算,非0為1, 非1為0
bitwiseNot = cv2.bitwise_not(circle)
cv2.imshow("NOT", bitwiseNot)
cv2.waitKey(0)



# 異或運算,不同為1, 相同為0
bitwiseXor = cv2.bitwise_xor(rectangle, circle)
cv2.imshow("XOR", bitwiseXor)
cv2.waitKey(0)
'''
# 或運算,有1則為1, 全為0則為0
bitwiseOr = cv2.bitwise_or(rectangle, circle)
cv2.imshow("OR", bitwiseOr)
cv2.waitKey(0)
# 使用mask
mask = bitwiseOr
cv2.imshow("Mask", mask)

# Apply out mask -- notice how only the person in the image is cropped out
masked = cv2.bitwise_and(image, image, mask=mask)
cv2.imshow("Mask Applied to Image", masked)
cv2.waitKey(0)

結果展示:




簡單說就是:

  1. 與或非異或運算與我們的常識類似。
  2. 掩膜操作就是兩幅影象(numpy陣列)的位運算操作。

附錄:C++ 版

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>

using namespace std;
using namespace cv;

int main()
{
    Mat image, mask;
    Rect r1(100, 100, 250, 300);
    Mat img1, img2, img3, img4;
    image = imread("lol17.jpg");
    mask = Mat::zeros(image.size(), CV_8UC1);
    mask(r1).setTo(255);
    img1 = image(r1);
    image.copyTo(img2, mask);

    image.copyTo(img3);
    img3.setTo(0, mask);


    imshow("Image sequence", image);
    imshow("img1", img1);
    imshow("img2", img2);
    imshow("img3", img3);
    imshow("mask", mask);

    waitKey();
    return 0;
}

原始圖:


注意程式中的這兩句關於Mask的操作。

mask = Mat::zeros(image.size(), CV_8UC1); 
mask(r1).setTo(255);  //r1是設定好的感興趣區域

解釋一下上面兩句的操作。

  • 第一步建立與原圖一樣大小的mask影象,並將所有畫素初始化為0,因此全圖成了一張全黑色圖。
  • 第二步將mask圖中的r1區域的所有畫素值設定為255,也就是整個r1區域變成了白色。

這樣就能得到Mask影象了。


注意這句,哪個影象拷貝到哪個影象?

image.copyTo(img2, mask);

當然是原始圖image拷貝到目的圖img2上。
其實拷貝的動作完整版本是這樣的:

原圖(image)與掩膜(mask)進行與運算後得到了結果圖(img2)。

何為圖與掩膜的與運算?

其實就是原圖中的每個畫素和掩膜中的每個對應畫素進行與運算。比如1 & 1 = 1;1 & 0 = 0;

比如一個3 * 3的影象與3 * 3的掩膜進行運算,得到的結果影象就是:

說白了,mask就是點陣圖啊,來選擇哪個畫素允許拷貝,哪個畫素不允許拷貝。如果mask畫素的值是非0的,我就拷貝它,否則不拷貝。

因為我們上面得到的mask中,感興趣的區域是白色的,表明感興趣區域的畫素都是非0,而非感興趣區域都是黑色,表明那些區域的畫素都是0。一旦原圖與mask圖進行與運算後,得到的結果圖只留下原始圖感興趣區域的影象了。也正如下圖所示。

image.copyTo(img2, mask);

如果想要直接摳出目標區域,直接這樣寫就OK了:

img1 = image(r1);


參考文獻:

1.https://www.cnblogs.com/skyfsm/p/6894685.html

相關推薦

Opencv影象處理mask

1.在OpenCV中我們經常會遇到一個名字:Mask(掩膜)。很多函式都使用到它,那麼這個Mask到底什麼呢?2.如果我們想要裁剪影象中任意形狀的區域時,應該怎麼辦呢? 答案是,使用掩膜(masking)。 我們先看一下掩膜的基礎。影象的位運算。影象基本運算影象的基本運算有很

OpenCV探索路(十三):mask

ret 如果 拷貝 ace 設置 之路 動作 與運算 區域 在OpenCV中我們經常會遇到一個名字:Mask(掩膜)。很多函數都使用到它,那麽這個Mask到底什麽呢? 一開始我接觸到Mask這個東西時,我還真是一頭霧水啊,也對無法理解Mask到底有什麽用。經過查閱大量資料後

mask

comm opencv2 遮蓋 proc 變量 匹配 num 數字圖像 處理 什麽是掩膜(mask) 數字圖像處理中的掩膜的概念是借鑒於PCB制版的過程,在半導體制造中,許多芯片工藝步驟采用光刻技術,用於這些步驟的圖形“底片”稱為掩膜(也稱作“掩模”),其作用是:在矽片上

影象處理函式——padarray(matlab)

轉自殘雪飛月 功能:填充影象或填充陣列。 用法:B = padarray(A,padsize,padval,direction)        A為輸入影象,B為填充後的影象,padsize給出了給出了填充的行數和列數,通常用[r c]來表示。padval和directio

c++ opencv 圖片處理中畫素 實現

#include<opencv2/opencv.hpp>#include<iostream>#include<math.h>using namespace cv;int main(int argc, char** argv){Mat src

python for OpenCV影象處理模板匹配以及分水嶺演算法

首先看些效果如下: 具體程式碼如下: if __name__ == '__main__': from muban import Ui_Form else: from muban.muban import Ui_

opencv影象處理滑鼠事件(矩形roi繪圖)

為滿足影象處理要求,博主寫此簡易程式碼有如下作用: 1、根據感興趣區域做深度學習標籤; 2、提取感興趣區域進行目標跟蹤; 3、對感興趣區域進行進一步操作。 具體程式碼如下: //Author: s

opencv影象處理輪廓外背景顏色改變

自行學習弄得簡單程式碼,使用了影象中的輪廓發現以及提取,再繪製出來,改變輪廓外的畫素 首先,標頭檔案,寫的比較多,沒用的可以自己去除 #include <opencv2/core/core.hpp> #include<openc

opencv影象處理常見濾波器

影象平滑 Smoothing, also called blurring, is a simple and frequently used image processing operation. 平滑,也叫模糊. 本質就是把某點的畫素值轉換為其及其周圍畫素值的不同權重的疊加.h(k,l)即為卷積核,或

OpenCV-影象處理(02、矩陣的操作)

1. 獲取影象畫素指標 CV_Assert(myImage.depth() == CV_8U); Mat.ptr(int i=0) 獲取畫素矩陣的指標,索引i表示第幾行,從0開始計行數。 獲得當前行指標const uchar* current= myImage.p

飛卡OpenCV影象處理賽道例項

普通寫法 程式碼 #include "cv.h" #include "highgui.h" #include <stdio.h> #include <string.h> #include <math.h> #include "

影象處理其他雜項(一)MeanShift的目標跟蹤演算法opencv c++程式碼 VS2015+opencv3.2

//#include "stdafx.h" //#include "cv.h" //#include "highgui.h" #include<opencv.hpp> #define u_char unsigned char #define DIST 0.5 #define

SQLto_date()以及關於日期處理

日期例子: SELECT TO_DATE('2006-05-01 19:25:34', 'YYYY-MM-DD HH24:MI:SS') FROM DUAL SELECT TO_DATE('2006-05-01 19:25', 'YYYY-MM-DD HH24:MI') FROM DUAL SELECT

微信JS-SDK影象介面開發

由於現在手頭的專案中有一個上傳證件照認證的功能(手機端),之前的思路是直接點選上傳,然後直接將圖片上傳到伺服器去,這篇文章有講到( http://www.cnblogs.com/it-cen/p/4535219.html ),但在微信裡開啟網頁去上傳,速度並不快,而且,假如我上傳一張2M大的圖片,也沒

OpenCV影象處理影象平滑

影象平滑演算法影象平滑與影象模糊是同一概念,主要用於影象的去噪。平滑要使用濾波器,為不改變影象的相位資訊,一般使用線性濾波器,其統一形式如下:其中h稱為濾波器的核函式,說白了就是權值。不同的核函式代表不同的濾波器,有不同的用途。在影象處理中,常見的濾波器包括:歸一化濾波器(H

Android非同步訊息處理機制

一、在子執行緒中更新UI概述 和許多其他的GUI 庫一樣,Android 的UI 也是執行緒不安全的。也就是說,如果想要更新應用程式裡的UI 元素,則必須在主執行緒中進行,否則就會出現異常。但是有些時候,我們必須在子執行緒裡去執行一些耗時任務,然後根據任務的執

Spring mvc請求處理流程(一)檢視解析

前言   Spring mvc框架相信很多人都很熟悉了,關於這方面的資料也是一搜一大把。但是感覺講的都不是很細緻,讓很多初學者都雲裡霧裡的。本人也是這樣,之前研究過,但是後面一段時間不用發現又忘記了。所以決定寫下來,以備後用。   本系列文基於spring-

c/c++預處理過程(二)條件編譯及預定義的巨集

未經博主同意不得私自轉載!不準各種形式的貼上複製本文及盜圖! 首先對於上篇文章中巨集定義的補充: (1)#define NAME"zhangyuncong" 程式中有"NAME"則,它會不會被替換呢? (2)#define 0x abcd 可以嗎?也就是說,可不可以用不是

視訊、圖形影象處理Opencv技術記錄(五)、Opencv教程影象處理(imgproc模組)平滑影象

目標 在本教程中,您將學習如何使用OpenCV函式應用各種線性濾鏡來平滑影象,例如: 理論 注意 下面的解釋屬於Richard Szeliski和LearningOpenCV的計算機視覺:演算法和應用一書 平滑,也稱為模糊,是一種簡單且經常使用的影象處理操作。

Android 開發多執行緒處理——Handler

    Android開發過程中為什麼要多執行緒     我們建立的Service、Activity以及Broadcast均是一個主執行緒處理,這裡我們可以理解為UI執行緒。但是在操作一 些耗時操作時,比如I/O讀寫的大檔案讀寫,資料庫操作以及網路下載需要很長時間,為了不