opencv圖像處理機器學習真實項目教程(python實現)3圖像處理基礎

来源:https://www.cnblogs.com/testing-/archive/2023/12/21/17916995.html
-Advertisement-
Play Games

Qt 是一個跨平臺C++圖形界面開發庫,利用Qt可以快速開發跨平臺窗體應用程式,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實現圖形化開發極大的方便了開發效率,本章將重點介紹`QStringListModel`字元串映射組件的常用方法及靈活運用。`QStringListModel` 是 ... ...


3 圖像處理基礎

在本章中,我們將介紹圖像處理中的各種操作,首先是基於平移的操作,如旋轉和調整大小。讀者將學習如何使用 OpenCV 旋轉和調整圖像大小,以及如何控制生成圖像的大小和方向。本章接著介紹了圖像的算術運算,如加法、減法和除法。本章繼續以圖像運算為主題,介紹圖像的位運算,如 AND、OR 和 XOR。最後,本章討論了圖像的通道和可以表示圖像的各種色彩空間。

主要內容:

  • 圖像的幾何變換

    • 圖像平移
    • 旋轉
    • 縮放
    • 翻轉
    • 剪切
    • 裁剪
  • 圖像算術運算

    • 加法
    • 減法
    • 乘法
    • 除法
  • 圖像的位運算

    • AND
    • OR
    • XOR
    • NOT
  • 通道和色彩空間

3.1 幾何變換

圖像變換能讓我們以多種方式修改圖像。它們在電腦視覺中起著至關重要的作用,使我們能夠改變圖像的大小或方向,以完成各種電腦視覺任務。這些操作被廣泛用於電腦視覺任務中,並將成為我們所有電腦視覺應用的基本組成部分。這些變換在物體識別、圖像分割和麵部識別等電腦視覺應用中至關重要。

從技術角度講,圖像處理涉及將圖像點的坐標從一個坐標系轉換到另一個坐標系。利用各種變換函數,可以將原始圖像中的像素坐標映射到變換後圖像中的新坐標,從而產生不同類型的變換。

3.1.1 圖像平移

圖像平移是在水平和垂直方向上移動圖像的過程。通過圖像平移,我們可以在 x 軸和 y 軸上按指定的量移動圖像。

要執行圖像平移,需要對圖像應用平移矩陣,將原始坐標映射到新的移動坐標。

圖像平移是一種簡單而有效的技術,可與其他圖像處理技術相結合,以實現所需的結果。它有多種用途,例如將兩幅圖像對齊或在全景拍攝中拼接圖像。在創建用於訓練深度學習模型的數據集時,圖像轉換也常用於增強數據。

圖像轉換可以通過對輸入圖像應用仿射變換來實現。仿射變換是一種應用於圖像的線性變換,它可以改變圖像的大小和長寬,同時保留物體的位置和形狀。仿射變換的一個重要特點是保留線條的平行性。

我們使用 OpenCV 中的 cv2.warpAffine 函數來應用仿射變換:


cv2.warpAffine(src, M, dsize, dst, flags=INTER_LINEAR,borderMode=BORDER_CONSTANT, borderValue=0)

參數

  • src:應用變換的源圖像。

  • M:變換矩陣。

  • dsize:輸出圖像的大小: 輸出圖像的大小。

  • dst:dst 是可選的輸出圖像,用於存儲變換結果。dst 圖像的大小和類型必須與輸入圖像 src 相同。如果未提供 dst 圖像,OpenCV 函數將創建與輸入圖像大小和類型相同的輸出圖像,並將其作為輸出返回。

  • 標誌(Flags): 這是一個可選參數,用於指定要使用的插值方法。

  • borderMode:邊框模式: 指定如何處理超出圖像邊界的像素。預設值為 cv2.BORDER_CONSTANT。

  • borderValue(邊框值): 僅用於 cv2.BORDER_CONSTANT 模式,指定用於填充圖像的常量值。預設值為 0。


import cv2
import numpy as np

img = cv2.imread("../img/dog.jpg")

# Define the translation matrix
tx = 50   # x-direction
ty = 100  # y-direction
M = np.float32([[1, 0, tx], [0, 1, ty]])

# Apply the translation to the image
rows, cols, _ = img.shape
translated_img = cv2.warpAffine(img, M, (cols, rows))

cv2.imshow("Original Image", img)
cv2.imshow("Translated Image", translated_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

3.1.2旋轉

圖像旋轉是將圖像繞其中心點旋轉一個角度的過程。它是圖像處理中廣泛使用的操作,可用於各種圖像處理應用中。

有兩種方法可以執行圖像旋轉,雖然一種方法就足夠了,但為了全面瞭解這一主題,有必要討論這兩種方法。

第一種是使用cv2.rotate 函數進行圖像旋轉。使用該函數的缺點是,它只能將圖像按順時針或逆時針方向旋轉90度。它不允許我們選擇任意角度旋轉圖像cv2.rotate函數的實現方式如下

cv2.rotate(src, rotateCode, dst)

參數

  • src:要進行變換的源圖像。
  • rotateCode:旋轉代碼: 該參數指定圖像旋轉的方向和角度。rotateCode 的可能值有
    • cv2.ROTATE_90_CLOCKWISE: 按順時針方向將圖像旋轉 90 度。
    • cv2.ROTATE_90_COUNTERCLOCKWISE:按順時針方向旋轉圖像 90 度: 按逆時針方向將圖像旋轉 90 度。
    • cv2.ROTATE_180: 將圖像旋轉 180 度。
  • dst:dst 是可選的輸出圖像,用於存儲轉換結果。dst 圖像的大小和類型必須與輸入圖像 src 相同。如果未提供 dst 圖像,OpenCV 函數將創建與輸入圖像大小和類型相同的輸出圖像,並將其作為輸出返回。
import cv2

img = cv2.imread('../img/dog.jpg')

# Rotate clockwise by 90 degrees
rot_img_90cw = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)

# Rotate counterclockwise by 90 degrees
rot_img_90ccw = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)

# Rotate by 180 degrees
rot_img_180 = cv2.rotate(img, cv2.ROTATE_180)

cv2.imshow('Original', img)
cv2.imshow('Rotated 90 CW', rot_img_90cw)
cv2.imshow('Rotated 90 CCW', rot_img_90ccw)
cv2.imshow('Rotated 180', rot_img_180)
cv2.waitKey(0)
cv2.destroyAllWindows()

我們使用的另一種圖像旋轉方法是使用前面討論過的cv2.warpAffine函數。這種方法允許我們選擇任意角度和中心點來旋轉圖像。

我們使用另一個函數cv2.getRotationMatrix2D來生成用於cv2.warpAffine函數的旋轉矩陣。雖然自行創建圖片平移矩陣很簡單,但使用專用函數來創建旋轉矩陣還是很有幫助的:

cv2.getRotationMatrix2D(center=None, angle, scale=1)

參數

  • center: 圖像旋轉的中心點(x,y)。預設值為None。如果未指定中心點,函數將使用圖像的中心點。
  • angle:角度: 旋轉角度(度)。正值表示逆時針方向,負值表示順時針方向。
  • scale:縮放比例: 縮放參數用於按繫數縮放圖像的大小。預設值為 1,表示輸出圖像與輸入圖像大小相同。

讓我們試著用一些代碼來實現旋轉:

import cv2
import numpy as np

img = cv2.imread('../img/dog.jpg')
rows, cols = img.shape[:2]

# Get rotation matrices.
M1 = cv2.getRotationMatrix2D((100,100), 30, 1)

M2 = cv2.getRotationMatrix2D((cols/2,rows/2), 45, 2)

M3 = cv2.getRotationMatrix2D((cols/2,rows/2), -90, 1)

#new values for the output
scale = 2
new_cols = int(cols * scale)
new_rows = int(rows * scale)

# Create output image with the new size
rotated2 = cv2.warpAffine(img, M2, (new_cols, new_rows))

# Perform rotation
rotated1 = cv2.warpAffine(img, M1, (cols, rows))
rotated2 = cv2.warpAffine(img, M2, (cols, rows))
rotated3 = cv2.warpAffine(img, M3, (cols, rows))

cv2.imshow('Original Image', img)
cv2.imshow('Rotated Image 1', rotated1)
cv2.imshow('Rotated Image 2', rotated2)
cv2.imshow('Rotated Image 3', rotated3)
cv2.waitKey(0)
cv2.destroyAllWindows()

3.1.3縮放

圖像縮放是圖像處理中的一項常見任務,它允許我們根據需要調整圖像大小。在調整圖像大小時,重要的是要保持圖像的縱橫比,以避免產生扭曲的圖像。

我們使用 cv2.resize() 函數來調整 OpenCV 圖像的大小:

cv2.resize(src, dst, dsize, fx=0, fy=0, interpolation=cv2.INTER_LINEAR)

參數

  • src:應用變換的源圖像。
  • dst:dst 是可選的輸出圖像,用於存儲變換結果。dst 圖像的大小和類型必須與輸入圖像 src 相同。如果未提供 dst 圖像,OpenCV 函數將創建與輸入圖像大小和類型相同的輸出圖像,並將其作為輸出返回。
  • dsize: 調整大小後輸出圖像的尺寸。
  • fx: 沿水平軸的縮放因數。
  • fy: 沿垂直軸的縮放因數。

如果未指定 dsize,系統將自動使用縮放因數 fx 和 fy 計算出 dsize。

dsize = (int(src.shape[1] * fx), int(src.shape[0] * fy))
  • interpolation: 插值是指應用幾何變換後估算新像素值的技術。該參數可使用以下值:
    • cv2.INTER_NEAREST:最近鄰插值。
    • cv2.INTER_LINEAR:雙線性插值。
    • cv2.INTER_CUBIC:對 4×4 像素鄰域進行雙三次插值。
    • cv2.INTER_AREA:使用像素麵積關係重新採樣。這是縮小圖像時推薦的插值方法。
    • cv2.INTER_LANCZOS4: 在 8x8 像素鄰域上進行 Lanczos 插值。
import cv2

img = cv2.imread('../img/dog.jpg')

# Resize the image to half its size
resized_img = cv2.resize(img, (0,0), fx=0.5, fy=0.5)

# Resize the image to a specific width and height
resized_img = cv2.resize(img, (640, 480))

cv2.imshow('Original Image', img)
cv2.imshow('Resized Image', resized_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

圖像縮放也可以使用 cv2.warpAffine 函數來實現:

import cv2
import numpy as np

img = cv2.imread('cat.jpg')

# Define the new size
new_size = (400, 400)

# Compute the scaling factors for x and y axis
sx = new_size[0]/img.shape[1]
sy = new_size[1]/img.shape[0]

# Define the transformation matrix
M = np.float32([[sx, 0, 0], [0, sy, 0]])

# Apply the affine transformation
resized_img = cv2.warpAffine(img, M, new_size)

cv2.imshow('Original Image', img)
cv2.imshow('Resized Image', resized_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

代碼會產生以下輸出:

3.1.4翻轉

圖像翻轉用於水平或垂直翻轉圖像。我們可以使用 cv2.flip 函數來實現圖像翻轉:

cv2.flip(src, dst, flipCode=1)

參數

  • src: 要翻轉的源圖像
  • dst: 輸出變數
  • flipCode:翻轉代碼 指定如何翻轉數組的標誌。該參數可使用以下值。
    • '0': 垂直翻轉。圖像圍繞 x 軸翻轉。
    • '1': 水平翻轉。圖像圍繞 Y 軸翻轉
    • '-1': 圖像圍繞兩個軸翻轉
      預設值為 1:
import cv2

img = cv2.imread('../img/dog.jpg')

# Flip the image horizontally
x_flip = cv2.flip(img, 1)

# Flip the image vertically
y_flip = cv2.flip(img, 0)

# Flip the image on both axes
xy_flip = cv2.flip(img, -1)

cv2.imshow('Original Image', img)
cv2.imshow('Horizontal flip', x_flip)
cv2.imshow('Vertical flip', y_flip)
cv2.imshow('Both axes', xy_flip)
cv2.waitKey(0)
cv2.destroyAllWindows()

代碼產生的輸出如下,演示了圖像翻轉:

3.1.5 Shearing

圖像剪切是一種線性變換,它沿著圖像的一個軸扭曲圖像。當圖像沿 x 軸剪切時,圖像中的像素會水平移動。這會導致圖像在 x 軸方向上傾斜。同樣,當圖像沿 Y 軸剪切時,圖像中的像素會垂直移動,導致圖像在 Y 軸方向看起來傾斜。圖像剪切時不會保留平行線。

import cv2
import numpy as np

img = cv2.imread('../img/dog.jpg')

# shearing parameters
shear_factor_x = 0.2
shear_factor_y = 0.3

# Obtain shearing matrices
M_x = np.array([[1, shear_factor_x, 0],
                [0, 1, 0]])
M_y = np.array([[1, 0, 0],
                [shear_factor_y, 1, 0]])

# Apply shearing transformations
rows, cols = img.shape[:2]
sheared_img_x = cv2.warpAffine(img, M_x, (cols + int(rows * shear_factor_x), rows))
sheared_img_xy = cv2.warpAffine(sheared_img_x, M_y, (cols + int(rows * shear_factor_x), rows + int(cols * shear_factor_y)))

cv2.imshow("Original Image", img)
cv2.imshow("Sheared Image (X axis)", sheared_img_x)
cv2.imshow("Sheared Image (X and Y axis)", sheared_img_xy)
cv2.waitKey(0)
cv2.destroyAllWindows()

3.1.6 裁剪(cropping)

圖像裁剪是選擇圖像矩形部分的過程。裁剪可被視為一種幾何變換,通過去除源圖像的一部分來生成新圖像。在原始圖像中,選擇一個矩形的感興趣區域(ROI),只保留該區域中的像素,其餘像素將被丟棄。

import cv2

img = cv2.imread('../img/dog.jpg')

# Define ROI coordinates
x1, y1 = 10, 10 # top-left corner
x2, y2 = 200, 200 # bottom-right corner

# Crop image
cropped_img = img[y1:y2, x1:x2]

cv2.imshow("Original Image", img)
cv2.imshow("Cropped Image", cropped_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

3.2 算術運算

算術運算是圖像處理中的一個基本概念。這些運算涉及對圖像執行基本數學運算,以生成具有不同屬性的新圖像。這些運算對像素值進行處理,使我們能夠從圖像中提取有用的信息。

圖像上的算術運算可用於多種應用,如調整圖像的亮度或對比度。算術運算的另一個主要用途是將兩幅或多幅圖像混合在一起。

在圖像上可以執行多種類型的算術運算。一些基本的算術運算包括加法、減法、乘法和除法。

在圖像上執行算術運算的主要挑戰之一是像素值超出 0-255 的範圍。出現這種情況的原因可能是在圖像中加入或減去了一個較大的值,並可能導致信息丟失和圖像失真等重大問題。

剪切是一種用於解決像素值超出 0-255 有效範圍問題的技術。這包括將任何高於 255 的像素值設置為 255,將任何低於 0 的像素值設置為 0,確保所有像素值都在有效範圍內。另一種解決方案是使用纏繞法,即如果數值超過 255,則纏繞到 0,而不是超過 255。例如,如果數值為 270,在剪切的情況下會設置為 255,但在另一種情況下,會繞到 15。

選擇使用哪種技術最終取決於手頭圖像處理任務的具體需求。

我們首先討論圖像加法,以及在使用 cv2 進行圖像加法時,如何處理像素值溢出,以及在 NumPy 值上使用普通 Python 加法時,如何處理像素值溢出。

3.2.1 加法

圖像加法是一種基本算術運算,涉及將兩幅或多幅圖像的像素值相加以生成一幅圖像。圖像加法的主要優勢在於它允許我們執行更複雜的操作,如圖像混合或遮罩。圖像混合是將兩幅圖像以不同的比例進行組合,生成輸出圖像,而遮罩則是在圖像上疊加二進位遮罩,對選定的圖像區域進行處理。隨著本章的深入,我們將討論這些主題。

我們使用 cv2.add() 函數來使用 OpenCV 庫執行加法運算:

cv2.add(src1, src2, dst, mask, dtype)

參數:

  • src1 和 src2:要添加的源圖像。兩幅圖像的類型和大小應相同。
  • dst: 輸出變數。
  • mask: 屏蔽允許我們選擇需要執行操作的特定像素。如果留空,則對所有像素執行操作。
  • dtype: 輸出的數據類型。這是一個可選參數,如果留空,預設為輸入數據類型。

現在,我們將嘗試通過執行 cv2.add 函數來添加圖像。此外,我們還將比較在 NumPy 加法中如何處理溢出值:

import numpy as np
import cv2

# Initialize two sample 3x3 images
img1 = np.array([[10, 20, 30],
                 [40, 50, 60],
                 [70, 80, 90]], dtype=np.uint8)
img2 = np.array([[100, 200, 150],
                 [50, 250, 100],
                 [150, 200, 50]], dtype=np.uint8)

# Add the images
cv2_add = cv2.add(img1, img2)
print("cv2.add() result:\n", cv2_add)

# Add the images using numpy addition
numpy_add = img1 + img2
print("Numpy addition result:\n", numpy_add)

結果

cv2.add() result:
 [[110 220 180]
 [ 90 255 160]
 [220 255 140]]
Numpy addition result:
 [[110 220 180]
 [ 90  44 160]
 [220  24 140]]

接下來,我們將討論圖像的加權相加,這意味著每幅圖像對最終輸出的貢獻不同,而且這些貢獻並不相等,如前所述。

為此,我們使用 cv2.addWeighted() 函數:

cv2.addWeighted(src1, alpha=1.0, src2, beta=0.0, gamma=0.0, dst, dtype)

參數

  • src1 和 src2:要添加的源圖像。兩幅圖像的類型和大小應相同。
  • alpha: 第一幅圖像的權重: 第一幅圖像的權重。alpha 的取值範圍為 0 至 1,其中 0 表示第一幅圖像對輸出沒有貢獻,1 表示第一幅圖像對輸出的貢獻最大。預設值為 1。
  • beta: 第二幅圖像的權重。beta 的範圍介於 0 和 1 之間,與 alpha 參數類似。beta 的預設值為 0。
  • gamma:伽馬值: 一個標量值,可在計算加權和後添加到所有像素中。預設值為 0。
  • dst:輸出數組: 輸出數組。
  • dtype:數據類型: 輸出的數據類型。這是一個可選參數,如果留空,預設為輸入數據類型。
import cv2
import numpy as np

img1 = cv2.imread('image1.jpg')
img2 = cv2.imread('image2.jpg')

# Add the two images with different weights
result = cv2.addWeighted(img1, 0.7, img2, 0.3, 0)

cv2.imshow('Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

結果:

前面的代碼載入了兩幅圖像,並以不同的權重將其混合。阿爾法參數設置為 0.7,貝塔參數設置為 0.3,這意味著 img1 對最終輸出的貢獻率為 70%,而 img2 為 30%。gamma 值設置為 0,表示初始結果中不添加任何標量。

3.2.2 圖像減法

接下來,我們將討論圖像減法。我們在 OpenCV 中使用 cv2.subtract() 函數進行圖像減法。該函數與我們之前討論過的 cv2.add() 函數非常相似。

該函數將兩幅圖像作為輸入,然後從第一幅圖像中減去第二幅圖像的像素值。如前所述,減法產生的任何負值都將設為 0:

cv2.subtract(src1, src2, dst, mask, dtype)

參數

  • src1 和 src2:要相減的源圖像。兩幅圖像的類型和大小應相同。從 src1 圖像減去 src2 圖像。
  • dst: 輸出變數。
  • mask: 屏蔽允許我們選擇需要執行操作的特定像素。這是一個。如果留空,則對所有像素執行操作。
  • dtype(數據類型 輸出的數據類型。這是一個可選參數,如果留空,預設為輸入數據類型。

3.2.3 乘除

圖像的乘法運算是將一幅圖像的每個像素值與另一幅圖像的相應像素值相乘。同樣,圖像除法是將一個圖像的每個像素值與另一個圖像的相應像素值相除。

由於圖像乘法和除法的語法和文檔相似,我們將一併討論,並使用單個代碼實現它們,以求簡潔:

cv2.multiply(src1, src2, dst, scale=1.0, dtype)

cv2.divide(src1, src2, dst, scale=1.0, dtype)

參數:

  • src1 和 src2: 要相乘或相除的源圖像。
  • dst: 輸出變數。
  • scale:比例繫數: cv2.multiply()中的比例因數是一個標量值,與輸入圖像中相應像素值的乘積相乘。cv2.divide 中的 scale 參數用於將分子(源圖像)除以標量值。這是一個可選參數,預設值為 1.0。
  • dtype: 輸出的數據類型。這是一個可選參數,如果沒有輸入數據類型,則預設為輸入數據類型。

3.3 位運算

位運算可用於合併兩幅圖像,或提取和修改這些圖像的特定部分。雖然位運算看似低級簡單,但在圖像處理中卻是必不可少的。位wise 運算看起來與算術運算相似,但它們並不完全是算術運算。

算術運算通常涉及使用加、減、乘、除等數學運算來處理圖像中像素的數值。另一方面,位運算涉及對圖像中像素值的各個位進行操作。這些操作基於 AND、OR、XOR 和 NOT 的邏輯運算。

位運算是對這些像素值的二進位表示執行的。二進位操作既可以在二進位圖像上進行,也可以在灰度/彩色圖像上進行。二進位圖像的像素值為 0 和 1,因此對其進行位運算非常簡單。在灰度圖像中,像素值範圍為 0-255 的單通道,而對於彩色圖像,則有多個通道,每個通道單獨處理,然後合併。

四種主要的位操作是 AND、OR、XOR 和 NOT。我們將詳細討論這些操作,但由於它們的語法和文檔相似,為簡潔起見,我們將它們放在一起。

3.3.1 AND

比特 AND 是一種二進位操作,它將兩幅圖像進行邏輯 AND 運算。如果輸入圖像中的任何位為 0,則結果像素值為 0。

比特 AND 運算的主要用途是屏蔽。它可用於在圖像上應用二進位掩碼,以提取圖像的某些區域。位與運算還可用於對象跟蹤或圖像分割和圖像銳化等用途。此操作的語法為

cv2.bitwise_and(src1, src2, dst, mask)

3.3.2 OR

OR是一種二進位操作,它將兩幅圖像進行邏輯 OR 運算。如果輸入圖像的兩個位都為 0,則生成的像素值為 0。

位操作 OR 的主要用途是圖像混合;使用這種操作可以將兩幅圖像混合在一起。該操作也可用於圖像分割或許多其他用途,例如在圖像中添加隨機噪音。此操作的語法為

cv2.bitwise_or(src1, src2, dst, mask)

參考資料

3.3.3 XOR

位操作XOR是一種二進位操作,它將兩幅圖像進行邏輯 XOR(排他 OR)操作。如果輸入圖像上的兩個位都是 0 或 1,則生成的像素值為 0。

通過使用密鑰,XOR可用於圖像加密。它還可用於邊緣檢測和直方圖均衡化等用例,我們將在本書中進一步深入探討這一概念。此操作的語法為

cv2.bitwise_xor(src1, src2, dst, mask)

3.3.4 NOT

NOT是一種一元操作,它獲取單個圖像並對其執行邏輯 NOT 操作。該操作的結果是圖像的所有值都被反轉。在位操作 NOT 的過程中,所有對應於 0 的像素值都會被設置為 1,而所有對應於 1 的像素值都會被設置為 0。

這種操作的主要用途是圖像反轉。除此之外,它還可用於屏蔽和圖像閾值處理。此操作的語法為

cv2.bitwise_not(src, dst, mask)

參數

  • src1 和 src:用於位操作的源圖像。
  • dst: 輸出變數。
  • mask:掩碼: 這是可選的掩碼,用於指定應處理輸入圖像中的哪些像素。預設值為 "無",即使用全部圖像:
import cv2
import numpy as np

# Create two black and white images
img1 = np.zeros((400, 400), dtype=np.uint8)
img2 = np.zeros((400, 400), dtype=np.uint8)

# Draw a rectangle on img1
cv2.rectangle(img1, (50, 50), (350, 350), (255, 255, 255), -1)

# Draw a circle on img2
cv2.circle(img2, (200, 200), 150, (255, 255, 255), -1)

# Perform bitwise AND
bitwise_and = cv2.bitwise_and(img1, img2)

# Perform bitwise OR
bitwise_or = cv2.bitwise_or(img1, img2)

# Perform bitwise XOR
bitwise_xor = cv2.bitwise_xor(img1, img2)

# Perform bitwise NOT on img1
bitwise_not = cv2.bitwise_not(img1)

cv2.imshow('img1', img1)
cv2.imshow('img2', img2)
cv2.imshow('AND', bitwise_and)
cv2.imshow('OR', bitwise_or)
cv2.imshow('XOR', bitwise_xor)
cv2.imshow('NOT of img1', bitwise_not)
cv2.waitKey(0)
cv2.destroyAllWindows()

3.4通道和色彩空間

在 OpenCV 中,圖像以像素值矩陣的形式表示。圖像中的通道數就是用於表示圖像的矩陣數。例如,灰度圖像有一個通道,而彩色圖像通常有三個通道(紅、綠、藍)。通過圖像中的通道,我們可以分離圖像中的顏色成分,並分別處理它們以獲取更多信息。

色彩空間代表了一種用數學模型描述色彩的特定方式。根據色彩空間的不同,色值被定義為三原色的組合,以及這些三原色如何組合產生特定的顏色。到目前為止,我們一直在使用 RGB 色彩空間,這是一種使用紅、綠、藍三個通道組合來表示所有顏色的色彩模型。隨著本主題的深入,我們將探索常見的色彩空間。我們還將討論灰度圖像,灰度圖像雖然不屬於色彩空間,但在圖像處理中卻非常重要。

將色彩空間與現實生活中的例子進行比較,可以更好地解釋色彩空間。想象一下,一個畫家試圖為一幅畫混合和創造新的顏色。畫家可以通過選擇多種顏料管,並以不同的比例將它們混合在一起,產生多種顏色。顏料混合後可以產生不同的顏色,例如紅色和白色混合後產生粉紅色,黃色和藍色混合後產生綠色。同樣,不同的色彩空間可以讓我們改變色彩的亮度或飽和度,並使用不同的三原色組合創造出新的色彩。

我們將詳細討論最常用的色彩空間。我們首先討論 RGB 色彩空間。

3.4.1 紅綠藍(RGB)色彩空間

RGB 色彩空間包含表示圖像的紅色、藍色和綠色通道。圖像是通過將這三種顏色按所需數量相加來生成特定顏色的。要生成的每種顏色的強度決定了生成該特定顏色所需的紅、綠、藍三種顏色的數量。將這三種顏色組合起來,就可以生成圖像所需的各種顏色。

RGB 色彩空間中的每個通道都有從 0 到 255 不等的數值,用來描述特定顏色的強度。0 表示沒有顏色或完全黑暗,而 255 表示該顏色的最大強度或完全明亮。例如,在 RGB 色彩空間中,純紅色用 (255, 0, 0) 表示,其中紅色通道為最大值 (255),綠色和藍色通道均設置為 0。 同樣,純藍色用 (0,0,255) 表示,純綠色可以用 (0,255,0) 表示。

例如,純黃色用 (255,255,0)表示,即紅色通道的值為 255,綠色通道的值為 255,藍色通道的值為 0。

其他一些顏色的表示方法如下

如果我們想改變顏色,還可以訪問和操作每個單獨的值。在上表中,我們發現淺灰色表示為 (211,211,211)。如果我們減小這些值,顏色就會開始變深,從而呈現出更深的灰色。

同樣,如果我們減小橙色的紅色通道(255, 165, 0),例如,將其改為(200, 165, 0),顏色將變得不那麼強烈,並轉向紅色較少的色調,但仍保留其橙色特征。

這些值的另一個重要用途是,我們可以用它們來檢測圖像中的特定顏色或顏色範圍。我們可以利用圖像中每個像素的紅色值來查找紅色物體,如紅花。例如,如果圖像中的紅色值 (R) 大於某個特定的數字(比方說 200),我們就可以說這些像素很可能屬於紅色物體,我們就可以使用這種技術來檢測圖像中的紅色花朵。

RGB 色彩空間通常不被認為是直觀的,因為使用這種色彩空間很難再現色彩。按比例混合紅色、藍色和綠色可能不會產生預期的顏色,而且通常很難再現這三種顏色的精確組合。儘管有其局限性,RGB 色彩空間仍被廣泛應用於包括圖像處理在內的各種應用中,在我們的學習過程中也會經常用到它。

讓我們藉助一些代碼,嘗試將圖像的這些通道可視化:

import cv2

img = cv2.imread('../img/dog.jpg')

im1=img.copy()
im2=img.copy()
im3=img.copy()


im1[:,:,0]=0
im1[:,:,1]=0

im2[:,:,2]=0
im2[:,:,1]=0

im3[:,:,2]=0
im3[:,:,0]=0


cv2.imshow("Original Image",img)
cv2.imshow("Red channel",im1)
cv2.imshow("Blue channel",im2)
cv2.imshow("Green channel",im3)

cv2.waitKey(0)
cv2.destroyAllWindows()

前面的代碼分別顯示圖像的三個通道。首先,我們將 im1 中的紅色和綠色通道值設置為 0。同樣,我們也可以在 im2 和 im3 中將其他兩個通道的值設置為 0,從而輸出其他兩個通道的圖像。

RGB 是電腦製圖、數字成像和視頻製作中廣泛使用的色彩模型,用於在電視、電腦顯示器和移動設備等電子設備上顯示圖像。在 OpenCV 中,RGB 也被用於最常見的任務;但在本例中,通道被反轉,以創建 BGR 色彩空間。

3.4.2 藍綠紅(BGR)色彩空間

BGR 色彩空間是反轉的 RGB 色彩空間。這是 OpenCV 中最常用的色彩空間。與 RGB 色彩空間相比,除了通道的定位外,沒有其他區別。OpenCV 使用 BGR 的唯一原因是 BGR 曾被用作某些硬體和軟體系統的預設格式,而這一慣例也被沿用到 OpenCV 等一些現代圖像處理庫中。Matplotlib 使用 RGB 色彩空間,因此在嘗試使用 matplotlib 顯示 OpenCV 圖像之前,我們要確保更改圖像的色彩空間。

3.4.3 色相飽和度值(HSV Hue Saturation and Value)色彩空間

色相飽和度和值是該色彩空間的三個組成部分。讓我們更好地瞭解這三個通道:

  • 色相: 色調指的是我們感知到的純色。色調本質上是一種沒有添加任何白色或黑色的純色。因此,舉例來說,所有類型的藍色,無論是深藍還是淺藍,都具有相同的藍色色調。
    色相值的範圍從 0 度到 360 度,代表一整圈的顏色。紅色位於 0 度,綠色位於 120 度,藍色位於 240 度。OpenCV 的 HSV 色彩空間中的色調分量是一個從 0 到 255 的 uint8 值,但實際的色調範圍是 0 到 360 度。為了在 8 位整數中適應這一範圍,數值被縮減為 0-179,其中每個值對應一個特定的色調。

  • 飽和度: 飽和度表示顏色的強度。飽和度值以 0% 到 100% 的百分比表示。飽和度值為 100%,表示顏色完全飽和,即顏色強度達到最大。飽和度為 0% 則沒有顏色,是純白色像素。

  • 值: 值是在色調中加入白色或黑色的量。它代表顏色的明暗程度。也可以用百分比來表示,範圍從 0% 到 100%。0% 表示最暗的顏色(黑色),而 100% 表示最亮的顏色(白色)。

與 RGB 色彩空間不同,HSV 色彩空間不是基於三原色的簡單相加。與 RGB 或 BGR 色彩空間相比,HSV 色彩空間的優點是將色彩信息與亮度信息分開。這使得在不改變圖像亮度的情況下調整顏色變得更加簡單。

現在我們已經探索了兩種色彩空間,可以嘗試改變圖像的色彩空間。我們將使用 cv2.cvtColor 函數來改變圖像的色彩空間。

cvtColor()
cv2.cvtColor(src, code, dst, dstCn=0)

參數

  • src:要轉換的源圖像。

  • code: 表示要執行的轉換類型。該參數定義了圖像的當前色彩空間,並指定了圖像需要轉換到的理想色彩空間。.Code "有很多可能的選項。其中幾個如下:

    • cv2.COLOR_BGR2HSV:將圖像從 BGR 轉換為 HSV。
    • cv2.COLOR_BGR2GRAY:將圖像從 BGR 轉換為灰度。
    • cv2.COLOR_HSV2BGR:將圖像從 HSV 轉換為 BGR。
    • cv2.COLOR_BGR2RGB:將圖像從 BGR 轉換為 RGB。
  • dst: 輸出變數

  • dstCn: 這是輸出圖像的通道數。預設值為 0,與輸入圖像的通道數一致。

import cv2

img_bgr = cv2.imread('../img/dog.jpg')

# BGR to grayscale
img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

cv2.imshow("Original Image", img_bgr)
cv2.imshow('Grayscale Image', img_gray)
cv2.waitKey(0)
cv2.destroyAllWindows()

3.4.4 色相飽和亮度(HSL)色彩空間

HSL(Hue Saturation Lightness) 色相飽和亮度是圖像處理中使用的另一種色彩模型。該色彩空間與 HSV 色彩空間類似,但在計算亮度方面略有不同。

色相和飽和度通道與 HSV 色彩空間類似。不過,在該空間中,數值通道被亮度通道取代。HSL 中的 L 通道旨在模仿人類感知亮度的方式,與 HSV 中的 V 通道相比,它與人類感知亮度的方式聯繫更為緊密。相比之下,HSV 空間中的值通道代表 R、G 和 B 顏色分量的最大值:

  • 色調: 色調指的是我們感知到的純色。這與 HSV 通道的描述類似。
  • 飽和度: 飽和度表示顏色的強度。這也與 HSV 通道中的描述類似。
  • 亮度 明度是衡量顏色亮度或暗度的標準,0% 的明度表示黑色,100% 的明度表示白色。這對於使圖像變亮或變暗以及為圖像添加創意點綴都很有用。

增加亮度值會使顏色變亮,更接近白色,而減少亮度值則會使顏色變暗。當亮度值為 50%時,顏色保持原樣。亮度值低於 50%,顏色會變暗,高於 50%,顏色會變亮。

例如,我們將 HSL 色彩空間中的灰色表示為 HSL:色相 = 0°,飽和度 = 0%,明度 = 50%。

如果我們增加亮度值,灰色就會變淺,更接近白色,但仍可識別為灰色。同樣,如果我們降低亮度值,灰色會變得更暗,更接近黑色。

總的來說,HSL 和 HSV 色彩空間都有各自獨特的優勢,並可根據執行任務的不同情況發揮作用。是否使用它們在很大程度上取決於任務的具體要求。

3.4.5 LAB色彩空間

LAB 色彩空間的設計與人類視覺系統非常相似。該色彩空間模仿人眼感知色彩的方式,因此比其他任何色彩空間都更接近人眼。LAB 色彩空間也被稱為 CIE LAB 色彩空間,因為它是由國際照明委員會(CIE)於 1976 年開發的,旨在創建一個標準化的色彩模型。

LAB 色彩空間由三個維度組成:

  • L 通道(亮度): L 通道代表亮度維度。它描述圖像的亮度。數值範圍為 0 到 100,其中 0 表示亮度最低(黑色),100 表示亮度最高(白色)。
    • a 通道(綠色-紅色): 它定義了一側的純綠色和另一側的純紅色。該維度的值範圍為 -128 至 +127,定義了綠色和紅色通道之間的顏色。負值代表綠色的色調,隨著正值的增加,紅色的色調也由這些值來定義。
    • b 通道(藍-黃): 它在一側定義純藍色,在另一側定義純紅色。這個維度的值範圍為 -128 到 +127,定義了藍色和黃色通道之間的顏色。負值代表藍色的深淺,隨著正值的增加,黃色的深淺也由這些值來定義。

該色彩模型的設計方式使其不受任何特定設備或技術的影響,從而使其更加通用,適用於各個領域。

3.4.6 YCbCr 色彩空間

YCbCr 色彩空間是一種色彩編碼系統,它將色彩表示為亮度(luma)和兩個色差信號(chroma)的組合。這種色彩空間將亮度(亮度)和色度(色彩)信息分開,可以更有效地壓縮圖像。

YCbCr 色彩空間與 RGB 色彩空間類似,但它使用的是亮度(Y)、藍差(Cb)和紅差(Cr)分量,而不是紅、綠、藍分量。Y 表示圖像的亮度,而 Cb 和 Cr 表示色彩與亮度之間的差異。

  • Y 通道: 該通道表示色彩的亮度,有時也稱為亮度通道。
  • YCb 和 Cr 通道: 這些通道代表圖像的顏色信息。Cb 通道表示藍色差異,Cr 通道表示紅色差異。

3.4.7 灰度

灰度圖像只用一個通道表示,包含 0 到 255 的數值。該值表示像素上的光量。數值為 0 表示像素上沒有光,因此像素的顏色為黑色。而 255 表示最大值,其值為白色。介於兩者之間的所有值都是不同的灰度。

從技術上講,灰度並不是一種色彩空間,因為它是圖像的單通道表示,不包含任何色彩信息。

在本書的學習過程中,我們會多次將圖像轉換為灰度圖像進行處理。不過,有一點需要記住。在大多數將 RGB 轉換為灰度的標準演算法中,紅色、綠色和藍色通道的權重並不相等。這是因為人眼對綠光比對紅光或藍光更敏感,所以在轉換過程中通常會給綠光更多的權重。一種常用的方法是使用以下公式

灰度 = 0.2989 * 紅色 + 0.5870 * 綠色 + 0.1140 * 藍色

3.5 小結

本章討論了使用 OpenCV 進行圖像處理的幾個重要操作。我們從基於平移的操作(如旋轉和調整大小)開始,學習瞭如何操作圖像的大小和方向。然後,我們介紹了算術運算,包括加法、減法和除法,以及位運算,如 AND、OR 和 XOR。最後,我們深入學習了圖像通道和色彩空間,探索了圖像的各種表示方法,以幫助完成圖像處理任務。

釘釘或微信號: pythontesting 微信公眾號:pythontesting
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文將介紹如何用JS實現簡單的屏幕錄像機。 一、錄製準備 創建一個按鈕 <button id="recording-toggle">Start recording</button> 書寫JavaScript var RECORDING_ONGOING = false; var recordingTo ...
  • 記得更改完配置後,要重啟編輯器(如:VSCode)!!! 記得更改完配置後,要重啟編輯器(如:VSCode)!!! 記得更改完配置後,要重啟編輯器(如:VSCode)!!! 這個錯誤通常發生在你嘗試在一個不支持 ES6 模塊語法的環境中使用 import 關鍵字。 ESLint 預設使用的是 ES5 ...
  • 1. 可演進的API 1.1. 隨著需求的變化,你需要改變你的API,即代碼之間的共用介面 1.2. 改變API很容易,但很難做到正確 1.3. 保持API小巧 1.3.1. 小巧的API更易於理解和演進 1.3.2. 只添加即刻需要的API方法或欄位 1.3.3. 帶有許多欄位的API方法應該有合 ...
  • 今天給大家推薦2個視頻翻譯工具​,分別是: TransDuck YouTube中文配音 這兩款工具的核心功能非常類似,核心提供一個視頻語言翻譯的能力。比如:你要看一個英文視頻,它可以幫助你將這個英文視頻變為中文視頻,日文視頻或者韓文視頻等其他語言的視頻。這裡所說的語言翻譯可不只是字幕哦,而是音頻也都 ...
  • 說明: access_token: 服務端與客戶端通信,有時服務端需要知道客戶端的身份,就會用到access_token來用於驗證身份。 refresh_token: 但為了保證安全token會設置過期時間,如果直接過期,相當於用戶或調用端正在使用產品,突然間就退出登錄了,這種產品體驗很差,於是有了 ...
  • 根據上一篇博客可知,單純的通過求取最大面積而進行定位的局限性,因此我們接下來將通過cv2.moments()和cv2.HuMoments()這兩個方法來在更複雜的環境中去找到我們的目標區域。 cv2.moments(): 參數: array:表示輸入圖像的單通道數組。通常是灰度圖像,可以是8位或浮點 ...
  • 先上代碼: 1 def barcode(image): 2 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 3 blur = cv2.GaussianBlur(gray, (5, 5), cv2.RETR_EXTERNAL, cv2.CHAIN_APPR ...
  • 今日內容 1.什麼是編程 2.電腦組成原理 3.電腦操作系統 4.編程語言是什麼 什麼是編程 什麼是編程語言 編程語言是人與電腦交流的介質 什麼是編程? 編程:用編程語言寫出一個個文件,這堆文件會達到一個目的。 編程有什麼用? 讓電腦幫我們幹活 電腦組成原理 CPU中央處理器 1.幫我們控 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...