[Python圖像處理] 三十五.OpenCV圖像處理入門、算數邏輯運算與圖像融合(推薦)

該系列文章是講解Python OpenCV圖像處理知識,前期主要講解圖像入門、OpenCV基礎用法,中期講解圖像處理的各種算法,包括圖像銳化算子、圖像增強技術、圖像分割等,後期結合深度學習研究圖像識別、圖像分類應用。希望文章對您有所幫助,如果有不足之處,還請海涵~

前面一篇文章介紹了數字圖像處理基礎知識,包括像素及常見圖像分類、OpenCV配置、常見數據類型、Numpy和Matplotlib繪製、幾何圖形繪製等。這篇文章將介紹OpenCV圖像處理入門知識、算數邏輯運算與圖像融合,萬字長文整理,希望對您有所幫助。同時,該部分知識均爲作者查閱資料撰寫總結,並且開設成了收費專欄,爲小寶賺點奶粉錢,感謝您的擡愛。當然如果您是在讀學生或經濟拮据,可以私聊我給你每篇文章開白名單,或者轉發原文給你,更希望您能進步,一起加油喔~

前文參考:
[Python圖像處理] 一.圖像處理基礎知識及OpenCV入門函數
[Python圖像處理] 二.OpenCV+Numpy庫讀取與修改像素
[Python圖像處理] 三.獲取圖像屬性、興趣ROI區域及通道處理
[Python圖像處理] 四.圖像平滑之均值濾波、方框濾波、高斯濾波及中值濾波
[Python圖像處理] 五.圖像融合、加法運算及圖像類型轉換
[Python圖像處理] 六.圖像縮放、圖像旋轉、圖像翻轉與圖像平移
[Python圖像處理] 七.圖像閾值化處理及算法對比
[Python圖像處理] 八.圖像腐蝕與圖像膨脹
[Python圖像處理] 九.形態學之圖像開運算、閉運算、梯度運算
[Python圖像處理] 十.形態學之圖像頂帽運算和黑帽運算
[Python圖像處理] 十一.灰度直方圖概念及OpenCV繪製直方圖
[Python圖像處理] 十二.圖像幾何變換之圖像仿射變換、圖像透視變換和圖像校正
[Python圖像處理] 十三.基於灰度三維圖的圖像頂帽運算和黑帽運算
[Python圖像處理] 十四.基於OpenCV和像素處理的圖像灰度化處理
[Python圖像處理] 十五.圖像的灰度線性變換
[Python圖像處理] 十六.圖像的灰度非線性變換之對數變換、伽馬變換
[Python圖像處理] 十七.圖像銳化與邊緣檢測之Roberts算子、Prewitt算子、Sobel算子和Laplacian算子
[Python圖像處理] 十八.圖像銳化與邊緣檢測之Scharr算子、Canny算子和LOG算子
[Python圖像處理] 十九.圖像分割之基於K-Means聚類的區域分割
[Python圖像處理] 二十.圖像量化處理和採樣處理及局部馬賽克特效
[Python圖像處理] 二十一.圖像金字塔之圖像向下取樣和向上取樣
[Python圖像處理] 二十二.Python圖像傅里葉變換原理及實現
[Python圖像處理] 二十三.傅里葉變換之高通濾波和低通濾波
[Python圖像處理] 二十四.圖像特效處理之毛玻璃、浮雕和油漆特效
[Python圖像處理] 二十五.圖像特效處理之素描、懷舊、光照、流年以及濾鏡特效
[Python圖像處理] 二十六.圖像分類原理及基於KNN、樸素貝葉斯算法的圖像分類案例
[Python圖像處理] 二十七.OpenGL入門及繪製基本圖形(一)
[Python圖像處理] 二十八.OpenCV快速實現人臉檢測及視頻中的人臉
[Python圖像處理] 二十九.MoviePy視頻編輯庫實現抖音短視頻剪切合並操作
[Python圖像處理] 三十.圖像量化及採樣處理萬字詳細總結(推薦)
[Python圖像處理] 三十一.圖像點運算處理兩萬字詳細總結(灰度化處理、閾值化處理)
[Python圖像處理] 三十二.傅里葉變換(圖像去噪)與霍夫變換(特徵識別)萬字詳細總結
[Python圖像處理] 三十三.圖像各種特效處理及原理萬字詳解(毛玻璃、浮雕、素描、懷舊、流年、濾鏡等)
[Python圖像處理] 三十四.數字圖像處理基礎與幾何圖形繪製萬字詳解(推薦)
[Python圖像處理] 三十五.OpenCV圖像處理入門、算數邏輯運算與圖像融合(推薦)



































本文主要講解Python調用OpenCV中的函數實現圖像處理的基礎知識,包括讀取和顯示圖像、修改和保存圖像、獲取圖像屬性及通道、圖像類型轉換、獲取圖像ROI區域、圖像加法運算和圖像融合處理等知識。

一.OpenCV基礎操作

1.讀取顯示圖像

在第34篇文章中我們講解了OpenCV顯示圖像的過程,它主要調用imread()和imshow()函數實現。OpenCV讀取圖像調用imread()函數,它將從指定的文件加載圖像並返回矩陣,如果無法讀取圖像(因爲缺少文件、權限不正確、格式不支持或圖像無效等),則返回空矩陣(Mat::data==NULL)。OpenCV中顯示圖像調用imshow()函數,它將在指定窗口中顯示一幅圖像,窗口自動調整爲圖像大小。同時,在顯示圖像過程中,通常還會調用兩個操作窗口的函數,它們分別是waitKey()和destroyAllWindows()。

下面是第一個示例程序,主要用於讀取和加載經典的“Lena”圖像。

# -*- coding:utf-8 -*-
# By: Eastmount CSDN 2021-01-26
import cv2

#讀取圖片
img = cv2.imread("Lena.png")

#顯示圖像
cv2.imshow("Demo", img)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出結果如圖所示:

在這裏插入圖片描述


2.OpenCV讀取修改像素

OpenCV中讀取圖像的像素值可以直接通過遍歷圖像的位置實現,如果是灰度圖像則返回其灰度值,如果是彩色圖像則返回藍色(B)、綠色(G)、紅色(G)三個分量值。其示例如下:

  • 灰度圖像:返回值 = 圖像[位置參數]
    如:test=img[88,42]

  • 彩色圖像:返回值 = 圖像[位置元素, 0 | 1 | 2 ]獲取BGR三個通道像素
    如:blue=img[88,142,0] green=img[88,142,1] red=img[88,142,2]

當需要修改圖像中的像素時,則定位指定像素並直接賦新像素值即可,彩色圖像需要依次給三個分量賦值。如下代碼所示。

# -*- coding:utf-8 -*-
# By: Eastmount CSDN 2021-01-26
import cv2

#讀取圖片
img = cv2.imread("Lena.png")

#讀取像素
test = img[88,142]
print("讀取的像素值:", test)

#修改像素
img[88,142] = [255, 255, 255]
print("修改後的像素值:", test)

#分別獲取BGR通道像素
blue = img[88,142,0]
print("藍色分量", blue)
green = img[88,142,1]
print("綠色分量", green)
red = img[88,142,2]
print("紅色分量", red)

#顯示圖像
cv2.imshow("Demo", img)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

讀取的像素值及修改後的像素值結果如圖所示。

在這裏插入圖片描述

下面代碼是將100到200行、150到250列的像素區域設置爲白色的效果。

# -*- coding:utf-8 -*-
# By: Eastmount CSDN 2021-01-26
import cv2

#讀取圖片
img = cv2.imread("Lena.png")

#該區域設置爲白色
img[100:200, 150:250] = [255,255,255]

#顯示圖像
cv2.imshow("Demo", img)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

下圖是最終顯示的效果圖,它將img[100:200, 150:250] 區域顯示爲白色。

在這裏插入圖片描述

前面是直接讀取和修改圖像像素的方法,下面講解通過Numpy庫讀取像素和修改像素的方法。讀取像素調用item()函數實現,修改像素調用itemset()實現,其原型如下所示。

使用Numpy進行像素讀取,調用方式如下:

  • 返回值 = 圖像.item(位置參數)
    例如:blue = img.item(78, 100, 0)

使用Numpy的itemset函數修改像素,調用方式如下:

  • 圖像.itemset(位置, 新值)
    例如:img.itemset((88,99), 255)

實現代碼如下所示。

# -*- coding:utf-8 -*-
# By: Eastmount CSDN 2021-01-26
import cv2
import numpy

#讀取圖片
img = cv2.imread("Lena.png")
print(type(img))

#Numpy讀取像素
print(img.item(78, 100, 0))
print(img.item(78, 100, 1))
print(img.item(78, 100, 2))

#Numpy修改像素
img.itemset((78, 100, 0), 100)
img.itemset((78, 100, 1), 100)
img.itemset((78, 100, 2), 100)
print(img.item(78, 100, 0))
print(img.item(78, 100, 1))
print(img.item(78, 100, 2))

輸出結果如圖所示,原始圖像BGR像素值爲88、84、196,修改後的像素值爲100、100、100。

在這裏插入圖片描述


3.創建複製保存圖像

由於在OpenCV2中沒有CreateImage函數,如果需要創建圖像,則需要使用Numpy庫函數實現。如下述代碼,調用np.zeros()函數創建空圖像,創建的新圖像使用Numpy數組的屬性來表示圖像的尺寸和通道信息,其中參數img.shape表示原始圖像的形狀,np.uint8表示類型。

  • emptyImage = np.zeros(img.shape, np.uint8)

例如img.shape爲(500, 300, 3),它表示500×300像素的圖像,3表示這是一個RGB圖像。同時,可以複製原有圖像來獲取一幅新圖像,調用copy()函數。

  • emptyImage2 = img.copy()

下列代碼實現了圖像的創建和複製功能。

# -*- coding:utf-8 -*-
# By: Eastmount CSDN 2021-01-26
import cv2
import numpy as np

#讀取圖片
img = cv2.imread("Lena.png")

#創建空圖像
emptyImage = np.zeros(img.shape, np.uint8)

#複製圖像
emptyImage2 = img.copy()

#顯示圖像
cv2.imshow("Demo1", img)
cv2.imshow("Demo2", emptyImage)
cv2.imshow("Demo3", emptyImage2)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

最終輸出結果如圖所示,Demo1表示原始圖像,Demo2表示創建的空白圖像,Demo3表示複製的圖像。

在這裏插入圖片描述

在OpenCV中,輸出圖像到文件使用的函數爲imwrite(),其函數原型如下:

  • retval = imwrite(filename, img[, params])
    – filename表示要保存的路徑及文件名
    – img表示圖像矩陣
    – params表示特定格式保存的參數編碼,默認值爲空。
    – 對於JPEG圖片,params參數(cv2.IMWRITE_JPEG_QUALITY)表示圖像的質量,用0-100的整數表示,默認值爲95。
    – 對於PNG圖片,該參數(cv2.IMWRITE_PNG_COMPRESSION)表示的是壓縮級別,從0到9,壓縮級別越高,圖像尺寸越小,默認級別爲3。
    – 對於PPM、PGM、PBM圖片,該參數表示一個二進制格式的標誌(cv2.IMWRITE_PXM_BINARY)。注意,該類型爲Long,必須轉換成int。





下面是一個調用imwrite()函數輸出圖像到指定的文件的代碼。

# -*- coding:utf-8 -*-
# By: Eastmount CSDN 2021-01-26
import cv2
import numpy as np

#讀取圖像
img = cv2.imread("Lena.png")

#顯示圖像
cv2.imshow("Demo", img)

#保存圖像
cv2.imwrite("dst1.jpg", img, [int(cv2.IMWRITE_JPEG_QUALITY), 5])  
cv2.imwrite("dst2.jpg", img, [int(cv2.IMWRITE_JPEG_QUALITY), 100])  
cv2.imwrite("dst3.png", img, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])  
cv2.imwrite("dst4.png", img, [int(cv2.IMWRITE_PNG_COMPRESSION), 9])

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

原始圖像“Lena.jpg”爲222KB,調用imwrite()函數輸出保存的圖像共四張,如圖所示,其中“dst1.jpg”被壓縮,大小爲4.90KB,“dst2.jpg”圖像大小爲99.1KB,“dst3.png”大小爲499KB,“dst4.png”大小爲193KB。

在這裏插入圖片描述


二.獲取圖像屬性及通道

本小節將詳細講解獲取圖像屬性、圖像通道處理及圖像遍歷三個知識點。

1.圖像屬性

圖像最常見的屬性包括三個:圖像形狀(shape)、像素大小(size)和圖像類型(dtype)。

(1)shape
通過shape關鍵字獲取圖像的形狀,返回包含行數、列數、通道數的元組。其中灰度圖像返回行數和列數,彩色圖像返回行數、列數和通道數。

# -*- coding:utf-8 -*-
import cv2
import numpy

#讀取圖片
img = cv2.imread("Lena.png")

#獲取圖像形狀
print(img.shape)

#顯示圖像
cv2.imshow("Demo", img)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

最終輸出結果如圖所示,(413L,412L,3L),它表示該圖像共413行、412列像素,包括3個通道。

在這裏插入圖片描述

(2)size
通過size關鍵字獲取圖像的像素數目,其中灰度圖像返回行數×列數,彩色圖像返回行數×列數×通道數。下述代碼就是獲取“Lena.jpg”圖像的大小。

# -*- coding:utf-8 -*-
import cv2
import numpy

#讀取圖片
img = cv2.imread("Lena.png")

#獲取圖像形狀
print(img.shape)

#獲取像素數目
print(img.size)

輸出結果如圖所示,包含510468個像素,即爲413×412×3。

在這裏插入圖片描述

(3)dtype
通過dtype關鍵字獲取圖像的數據類型,通常返回uint8。

# -*- coding:utf-8 -*-
import cv2
import numpy

#讀取圖片
img = cv2.imread("Lena.png")

#獲取圖像形狀
print(img.shape)

#獲取像素數目
print(img.size)

#獲取圖像數據類型
print(img.dtype)

輸出結果如下所示:

(413L, 412L, 3L)
510468
uint8

2.圖像通道處理

OpenCV通過split()函數和merge()函數實現對圖像通道的處理,包括通道分離和通道合併。

(1)split()函數
OpenCV讀取的彩色圖像由藍色(B)、綠色(G)、紅色(R)三原色組成,每一種顏色可以認爲是一個通道分量,如圖所示。

在這裏插入圖片描述

split()函數用於將一個多通道數組分量成三個單通道,其函數原型如下所示:

  • mv = split(m[, mv])
    – m表示輸入的多通道數組
    – mv表示輸出的數組或vector容器

下面的代碼是獲取彩色“Lena”圖像三個顏色通道並分別顯示。

# -*- coding:utf-8 -*-
# By: Eastmount CSDN 2021-01-26
import cv2
import numpy

#讀取圖片
img = cv2.imread("Lena.png")

#拆分通道
b, g, r = cv2.split(img)

#b = img[:, :, 0]
#g = img[:, :, 1]
#r = img[:, :, 2]

#顯示原始圖像
cv2.imshow("B", b)
cv2.imshow("G", g)
cv2.imshow("R", r)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

顯示結果如圖所示,它展示了B、G、R三個通道的顏色分量。也可以獲取不同通道顏色,核心代碼爲:

  • b = cv2.split(a)[0]
  • g = cv2.split(a)[1]
  • r = cv2.split(a)[2]

在這裏插入圖片描述

(2)merge()函數
該函數是split()函數的逆向操作,將多個數組合成一個通道的數組,從而實現圖像通道的合併,其函數原型如下:
dst = merge(mv[, dst])
– mv表示輸入的需要合併的數組,所有矩陣必須有相同的大小和深度
– dst表示輸出的具有與mv[0]相同大小和深度的數組



下列代碼實現了圖像三個顏色通道的合。

# -*- coding:utf-8 -*-
# By: Eastmount CSDN 2021-01-26
import cv2
import numpy as np

#讀取圖片
img = cv2.imread("Lena.png")

#拆分通道
b, g, r = cv2.split(img)

#合併通道
m = cv2.merge([b, g, r])
cv2.imshow("Merge", m)
           
#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

顯示結果如圖所示,它將拆分的B、G、R三個通道的顏色分量進行了合併,接着顯示合併後的圖像。

在這裏插入圖片描述

同時,可以調用該函數提取圖像的不同顏色,比如提取B顏色通道,G、B通道設置爲0。代碼如下所示:

# -*- coding:utf-8 -*-
# By: Eastmount CSDN 2021-01-26
import cv2
import numpy as np

#讀取圖片
img = cv2.imread("Lena.png")
rows, cols, chn = img.shape

#拆分通道
b = cv2.split(img)[0]

#設置g、r通道爲0
g = np.zeros((rows,cols), dtype=img.dtype)
r = np.zeros((rows,cols), dtype=img.dtype)

#合併通道
m = cv2.merge([b, g, r])
cv2.imshow("Merge", m)
           
#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

此時顯示的圖像爲藍色通道,如圖所示,其他顏色的通道方法也類似。

在這裏插入圖片描述


三.圖像算數與邏輯運算

本小節主要講解圖像的算法運算與邏輯運算,包括圖像加法、圖像減法、圖像與運算、圖像或運算、圖像異或運算與圖像非運算。

1.圖像加法運算

圖像加法運算主要有兩種方法。第一種是調用Numpy庫實現,目標圖像像素爲兩張圖像的像素之和;第二種是通過OpenCV調用add()函數實現。本小節主要講解第二種方法,其函數原型如下:

  • dst = add(src1, src2[, dst[, mask[, dtype]]])
    – src1表示第一張圖像的像素矩陣
    – src2表示第二張圖像的像素矩陣
    – dst表示輸出的圖像,必須和輸入圖像具有相同的大小和通道數
    – mask表示可選操作掩碼(8位單通道數組),用於指定要更改的輸出數組的元素。
    – dtype表示輸出數組的可選深度




注意,當兩幅圖像的像素值相加結果小於等於255時,則輸出圖像直接賦值該結果,如120+48賦值爲168;如果相加值大於255,則輸出圖像的像素結果設置爲255,如(255+64) 賦值爲255。下面的代碼實現了圖像加法運算。

#coding:utf-8
import cv2  
import numpy as np  
 
#讀取圖片
img = cv2.imread("Lena.png")

#圖像各像素加100
m = np.ones(img.shape, dtype="uint8")*100

#OpenCV加法運算
result = cv2.add(img, m)

#顯示圖像
cv2.imshow("original", img)
cv2.imshow("result", result)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出如圖所示,左邊爲原始圖像,右邊爲像素值增加100像素後的圖像,輸出圖像顯示更偏白。

在這裏插入圖片描述


2.圖像減法運算

圖像減法運算主要調用subtract()函數實現,其原型如下所示:

  • dst = subtract(src1, src2[, dst[, mask[, dtype]]])
    – src1表示第一張圖像的像素矩陣
    – src2表示第二張圖像的像素矩陣
    – dst表示輸出的圖像,必須和輸入圖像具有相同的大小和通道數
    – mask表示可選操作掩碼(8位單通道數組),用於指定要更改的輸出數組的元素。
    – dtype表示輸出數組的可選深度




實現代碼詳見如下:

#coding:utf-8
# By: Eastmount CSDN 2021-01-26
import cv2  
import numpy as np  
 
#讀取圖片 
img = cv2.imread("Lena.png")

#圖像各像素減50
m = np.ones(img.shape, dtype="uint8")*50

#OpenCV減法運算
result = cv2.subtract(img, m)

#顯示圖像
cv2.imshow("original", img)
cv2.imshow("result", result)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出如圖所示,左邊爲原始圖像,右邊爲像素值減少50像素後的圖像,輸出圖像顯示更偏暗。

在這裏插入圖片描述


3.圖像與運算

與運算是計算機中一種基本的邏輯運算方式,符號表示爲“&”,其運算規則爲:0&0=0、0&1=0、1&0=0、1&1=1。圖像的與運算是指兩張圖像(灰度圖像或彩色圖像均可)的每個像素值進行二進制“與”操作,實現圖像裁剪。

  • dst = bitwise_and(src1, src2[, dst[, mask]])
    – src1表示第一張圖像的像素矩陣
    – src2表示第二張圖像的像素矩陣
    – dst表示輸出的圖像,必須和輸入圖像具有相同的大小和通道數
    – mask表示可選操作掩碼(8位單通道數組),用於指定要更改的輸出數組的元素。



下面代碼是通過圖像與運算實現圖像剪裁的功能。

#coding:utf-8
# By: Eastmount CSDN 2021-01-26
import cv2  
import numpy as np  
 
#讀取圖片 
img = cv2.imread("Lena.png", cv2.IMREAD_GRAYSCALE)

#獲取圖像寬和高
rows, cols = img.shape[:2]
print(rows, cols)

#畫圓形
circle = np.zeros((rows, cols), dtype="uint8")
cv2.circle(circle, (int(rows/2.0), int(cols/2)), 80, 255, -1)
print(circle.shape)
print(img.size, circle.size)

#OpenCV圖像與運算
result = cv2.bitwise_and(img, circle)

#顯示圖像
cv2.imshow("original", img)
cv2.imshow("circle", circle)
cv2.imshow("result", result)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出如圖所示,原始圖像與圓形進行與運算之後,提取了其中心輪廓。同時輸出圖像的形狀爲256×256,圖像大小爲65536個像素。注意,兩張進行與運算的圖像大小和類型必須一致。

在這裏插入圖片描述


4.圖像或運算

邏輯或運算是指如果一個操作數或多個操作數爲 true,則邏輯或運算符返回布爾值 true;只有全部操作數爲false,結果纔是 false。圖像的或運算是指兩張圖像(灰度圖像或彩色圖像均可)的每個像素值進行二進制“或”操作,實現圖像裁剪。其函數原型如下所示:

  • dst = bitwise_or(src1, src2[, dst[, mask]])
    – src1表示第一張圖像的像素矩陣
    – src2表示第二張圖像的像素矩陣
    – dst表示輸出的圖像,必須和輸入圖像具有相同的大小和通道數
    – mask表示可選操作掩碼(8位單通道數組),用於指定要更改的輸出數組的元素。



下面代碼是通過圖像或運算實現圖像剪裁的功能。

#coding:utf-8
# By: Eastmount CSDN 2021-01-26
import cv2  
import numpy as np  
 
#讀取圖片 
img = cv2.imread("Lena.png", cv2.IMREAD_GRAYSCALE)

#獲取圖像寬和高
rows, cols = img.shape[:2]
print(rows, cols)

#畫圓形
circle = np.zeros((rows, cols), dtype="uint8")
cv2.circle(circle, (int(rows/2), int(cols/2)), 80, 255, -1)
print(circle.shape)
print(img.size, circle.size)

#OpenCV圖像或運算
result = cv2.bitwise_or(img, circle)

#顯示圖像
cv2.imshow("original", img)
cv2.imshow("circle", circle)
cv2.imshow("result", result)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出如圖所示,原始圖像與圓形進行或運算之後,提取了圖像除中心原形之外的像素值。

在這裏插入圖片描述


5.圖像異或運算

邏輯異或運算(xor)是一個數學運算符,數學符號爲“⊕”,計算機符號爲“xor”,其運算法則爲:如果a、b兩個值不相同,則異或結果爲1;如果a、b兩個值相同,異或結果爲0。圖像的異或運算是指兩張圖像(灰度圖像或彩色圖像均可)的每個像素值進行二進制“異或”操作,實現圖像裁剪。其函數原型如下所示:

  • dst = bitwise_xor(src1, src2[, dst[, mask]])
    – src1表示第一張圖像的像素矩陣
    – src2表示第二張圖像的像素矩陣
    – dst表示輸出的圖像,必須和輸入圖像具有相同的大小和通道數
    – mask表示可選操作掩碼(8位單通道數組),用於指定要更改的輸出數組的元素。



圖像異或運算的實現代碼如下所示。

#coding:utf-8
# By: Eastmount CSDN 2021-01-26
import cv2  
import numpy as np  
 
#讀取圖片 
img = cv2.imread("Lena.png", cv2.IMREAD_GRAYSCALE)

#獲取圖像寬和高
rows, cols = img.shape[:2]
print(rows, cols)

#畫圓形
circle = np.zeros((rows, cols), dtype="uint8")
cv2.circle(circle, (int(rows/2), int(cols/2)), 80, 255, -1)
print(circle.shape)
print(img.size, circle.size)

#OpenCV圖像異或運算
result = cv2.bitwise_xor(img, circle)

#顯示圖像
cv2.imshow("original", img)
cv2.imshow("circle", circle)
cv2.imshow("result", result)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

原始圖像與圓形進行異或運算之後輸出如圖所示。

在這裏插入圖片描述


6.圖像非運算

圖像非運算就是圖像的像素反色處理,它將原始圖像的黑色像素點轉換爲白色像素點,白色像素點則轉換爲黑色像素點,其函數原型如下:

  • dst = bitwise_not(src1, src2[, dst[, mask]])
    – src1表示第一張圖像的像素矩陣
    – src2表示第二張圖像的像素矩陣
    – dst表示輸出的圖像,必須和輸入圖像具有相同的大小和通道數
    – mask表示可選操作掩碼(8位單通道數組),用於指定要更改的輸出數組的元素。



圖像非運算的實現代碼如下所示。

#coding:utf-8
import cv2  
import numpy as np  
 
#讀取圖片 
img = cv2.imread("Lena.png", cv2.IMREAD_GRAYSCALE)

#OpenCV圖像非運算
result = cv2.bitwise_not(img)

#顯示圖像
cv2.imshow("original", img)
cv2.imshow("result", result)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

原始圖像非運算之後輸出如圖所示。

在這裏插入圖片描述


四.圖像融合處理

圖像融合通常是指將2張或2張以上的圖像信息融合到1張圖像上,融合的圖像含有更多的信息,能夠更方便人們觀察或計算機處理。如圖所示,它將兩張不清晰的圖像融合得到更清晰的圖。

在這裏插入圖片描述

圖像融合是在圖像加法的基礎上增加了係數和亮度調節量,它與圖像的主要區別如下:

  • 圖像加法:目標圖像 = 圖像1 + 圖像2
  • 圖像融合:目標圖像 = 圖像1 × 係數1 + 圖像2 × 係數2 + 亮度調節量

在OpenCV中,圖像融合主要調用addWeighted()函數實現,其原型如下。需要注意的是,兩張融合圖像的像素大小必須一致,參數gamma不能省略。

  • dst = cv2.addWeighted(scr1, alpha, src2, beta, gamma)
  • dst = src1 * alpha + src2 * beta + gamma

下面的代碼是將兩張圖片進行圖像融合,兩張圖片的係數均爲1。

#encoding:utf-8
# By: Eastmount CSDN 2021-01-26
import cv2  
import numpy as np  
import matplotlib.pyplot as plt
 
#讀取圖片
src1 = cv2.imread('lena-hd.png')
src2 = cv2.imread('na.png')

#圖像融合
result = cv2.addWeighted(src1, 1, src2, 1, 0)

#顯示圖像
cv2.imshow("src1", src1)
cv2.imshow("src2", src2)
cv2.imshow("result", result)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出結果如圖所示,它將src1圖像和src2圖像按比例係數進行了融合,生成目標結果圖result。

在這裏插入圖片描述

同樣可以設置不同的融合比例,比如函數設爲cv2.addWeighted(src1, 0.6, src2, 0.8, 10),則輸出的結果如圖所示。

在這裏插入圖片描述


五.獲取圖像ROI區域

ROI(Region of Interest)表示感興趣區域,是指從被處理圖像以方框、圓形、橢圓、不規則多邊形等方式勾勒出需要處理的區域。可以通過各種算子(Operator)和函數求得感興趣ROI區域,被廣泛應用於熱點地圖、人臉識別、圖像分割等領域。如圖獲取Lena圖的臉部輪廓。

在這裏插入圖片描述

通過像素矩陣可以直接獲取ROI區域,如img[200:400, 200:400]。下面的代碼是獲取臉部ROI區域並顯示。

# -*- coding:utf-8 -*-
import cv2
import numpy as np

#讀取圖片
img = cv2.imread("Lena.png")

#定義200×200矩陣 3對應BGR
face = np.ones((200, 200, 3))

#顯示原始圖像
cv2.imshow("Demo", img)

#顯示ROI區域
face = img[150:350, 150:350]
cv2.imshow("face", face)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出結果如圖所示,它將Lena原圖的臉部提取出來。

在這裏插入圖片描述

同樣,如果想將提取的ROI區域融合至其他圖片,則使用賦值語句即可。下面代碼是將提取的Lena頭部輪廓融合至一幅新的圖像中。

# -*- coding:utf-8 -*-
# By: Eastmount CSDN 2021-01-26
import cv2
import numpy as np

#讀取圖片
img = cv2.imread("Lena.png")
test = cv2.imread("test.jpg")

#定義150×150矩陣 3對應BGR
face = np.ones((150, 150, 3))

#顯示ROI區域
face = img[170:320, 170:320]
cv2.imshow("Demo", face)

test[220:370, 220:370] = face
cv2.imshow("Result", test)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

運行結果如圖所示,它將提取的150×150臉部輪廓融合至新的圖像 [220:370, 220:370] 區域。

在這裏插入圖片描述


六.圖像類型轉換

在日常生活中,我們看到的大多數彩色圖像都是RGB類型,但是在圖像處理過程中,常常需要用到灰度圖像、二值圖像、HSV、HSI等顏色。圖像類型轉換是指將一種類型轉換爲另一種類型,比如彩色圖像轉換爲灰度圖像、BGR圖像轉換爲RGB圖像。OpenCV提供了200多種不同類型之間的轉換,其中最常用的包括3類,如下:

  • cv2.COLOR_BGR2GRAY
  • cv2.COLOR_BGR2RGB
  • cv2.COLOR_GRAY2BGR

OpenCV提供了cvtColor()函數實現這些功能。其函數原型如下所示:

  • dst = cv2.cvtColor(src, code[, dst[, dstCn]])
    – src表示輸入圖像,需要進行顏色空間變換的原圖像
    – dst表示輸出圖像,其大小和深度與src一致
    – code表示轉換的代碼或標識
    – dstCn表示目標圖像通道數,其值爲0時,則有src和code決定



該函數的作用是將一個圖像從一個顏色空間轉換到另一個顏色空間,其中,RGB是指Red、Green和Blue,一副圖像由這三個通道(channel)構成;Gray表示只有灰度值一個通道;HSV包含Hue(色調)、Saturation(飽和度)和Value(亮度)三個通道。在OpenCV中,常見的顏色空間轉換標識包括CV_BGR2BGRA、CV_RGB2GRAY、CV_GRAY2RGB、CV_BGR2HSV、CV_BGR2XYZ、CV_BGR2HLS等。

下面是調用cvtColor()函數將圖像進行灰度化處理的代碼。

#encoding:utf-8
import cv2  
import numpy as np  
import matplotlib.pyplot as plt
 
#讀取圖片
src = cv2.imread('Lena.png')

#圖像類型轉換
result = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)

#顯示圖像
cv2.imshow("src", src)
cv2.imshow("result", result)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出結果如圖所示,它將左邊的彩色圖像轉換爲右邊的灰度圖像,更多灰度轉化的算法參考第15和16篇文章。

在這裏插入圖片描述

同樣,可以調用 grayImage = cv2.cvtColor(src, cv2.COLOR_BGR2HSV) 核心代碼將彩色圖像轉換爲HSV顏色空間,如圖所示。

在這裏插入圖片描述

下面代碼對比了九種常見的顏色空間,包括BGR、RGB、GRAY、HSV、YCrCb、HLS、XYZ、LAB和YUV,並循環顯示處理後的圖像。

# -*- coding: utf-8 -*-
# By: Eastmount CSDN 2021-01-26
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#讀取原始圖像
img_BGR = cv2.imread('na.png')

#BGR轉換爲RGB
img_RGB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB)

#灰度化處理
img_GRAY = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2GRAY)

#BGR轉HSV
img_HSV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HSV)

#BGR轉YCrCb
img_YCrCb = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YCrCb)

#BGR轉HLS
img_HLS = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HLS)

#BGR轉XYZ
img_XYZ = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2XYZ)

#BGR轉LAB
img_LAB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2LAB)

#BGR轉YUV
img_YUV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YUV)

#調用matplotlib顯示處理結果
titles = ['BGR', 'RGB', 'GRAY', 'HSV', 'YCrCb', 'HLS', 'XYZ', 'LAB', 'YUV']  
images = [img_BGR, img_RGB, img_GRAY, img_HSV, img_YCrCb,
          img_HLS, img_XYZ, img_LAB, img_YUV]  
for i in range(9):  
   plt.subplot(3, 3, i+1), plt.imshow(images[i], 'gray')  
   plt.title(titles[i])  
   plt.xticks([]),plt.yticks([])  
plt.show()

其運行結果如圖所示:

在這裏插入圖片描述


七.總結

本文主要講解Python和OpenCV的圖像基礎處理,從讀取顯示圖像到讀取修改像素,從創建、複製、保存圖像到獲取圖像屬性合通道,再詳細講解了圖像算數與邏輯運算,包括圖像加法、減法、與運算、或運算、異或運算、非運算,最後講解了圖像融合和獲取圖像ROI區域及圖像類型轉換。本章知識爲後續的圖像處理、圖像識別、圖像變換打下紮實基礎。

時光嘀嗒嘀嗒的流失,這是我在CSDN寫下的第八篇年終總結,比以往時候來的更早一些。《敏而多思,寧靜致遠》,僅以此篇紀念這風雨兼程的一年,這感恩的一年。列車上只寫了一半,這兩天完成,思遠,思君O(∩_∩)O

在這裏插入圖片描述

2020年8月18新開的“娜璋AI安全之家”,主要圍繞Python大數據分析、網絡空間安全、人工智能、Web滲透及攻防技術進行講解,同時分享CCF、SCI、南核北核論文的算法實現。娜璋之家會更加系統,並重構作者的所有文章,從零講解Python和安全,寫了近十年文章,真心想把自己所學所感所做分享出來,還請各位多多指教,真誠邀請您的關注!謝謝。

在這裏插入圖片描述

(By:Eastmount 2021-01-26 晚上10點 http://blog.csdn.net/eastmount/ )


參考文獻,在此感謝這些大佬,共勉!

  • [1]岡薩雷斯. 數字圖像處理(第3版)[M]. 北京:電子工業出版社, 2013.
  • [2]毛星雲, 冷雪飛. OpenCV3編程入門[M]. 北京:電子工業出版社, 2015.
  • [3]Eastmount. [Python圖像處理] 一.圖像處理基礎知識及OpenCV入門函數[EB/OL]. (2018-08-16). https://blog.csdn.net/Eastmount/article/details/81748802.
  • [4]Eastmount. [Python圖像處理] 二.OpenCV+Numpy庫讀取與修改像素[EB/OL]. (2018-08-28). https://blog.csdn.net/eastmount/article/details/82120114.
  • [5]zangyu. OpenCV Python教程(1、圖像的載入、顯示和保存) [EB/OL]. (2016-08-24). https://www.cnblogs.com/zangyu/p/5802142.html.
  • [6]Jumping boy. python+OpenCV圖像處理(一)讀取、複製、顯示、保存[EB/OL]. (2018-05-25). https://blog.csdn.net/qq_40962368/article/details/80444144.
  • [7]Eastmount. [Python圖像處理] 五.圖像融合、加法運算及圖像類型轉換[EB/OL]. (2018-09-03). https://blog.csdn.net/Eastmount/article/details/82347501.
  • [8]jnulzl. openCV—Python(6)—— 圖像算數與邏輯運算[EB/OL]. (2015-07-29). https://blog.csdn.net/jnulzl/article/details/47129887.
  • [9]tengfei461807914. python opencv入門 圖像上的算術運算(7)[EB/OL]. (2017-07-20). https://blog.csdn.net/tengfei461807914/article/details/75514689.
  • [10]Eastmount. [Python圖像處理] 三.獲取圖像屬性、興趣ROI區域及通道處理[EB/OL]. (2018-08-29). https://blog.csdn.net/Eastmount/article/details/82177300.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章