【總結】OpenCV-Python常用API(二)—— 圖像基本處理

1. 尺寸調整

1.1 函數簡述和原型

通過該函數可以對圖像進行放大或縮小處理。官方文檔:https://docs.opencv.org/3.4.2/da/d54/group__imgproc__transform.html#ga47a974309e9102f5f08231edc7e7529d

dst = cv2.resize(src, dsize[, fx[, fy[, interpolation]]])

1.2 參數

  • src:要處理的圖像數據;
  • dsize:目的大小,一個二元元組,分別爲處理後圖像的寬和高,即(width, height);
  • fx:x方向(寬度方向)縮放的倍數,當dsize不爲None時,其值必須爲目標圖像寬度/原圖像寬度;
  • fy:y方向(高度方向)縮放的倍數,當dsize不爲None時,其值必須爲目標圖像寬度/原圖像寬度;
  • interpolation:插值方法flag,常用的有如下幾種:
    • cv2.INTER_AREA:重採樣插值法,常在縮小圖片時使用;
    • cv2.INTER_CUBIC:雙三次插值法,常在放大圖片時使用,質量較好但速度較慢;
    • cv2.INTER_LINEAR:雙線性插值法,常在放大圖片時使用,質量一般但速度較快;

1.3 返回值

  • dst:返回的即爲縮放後的圖片數據;

1.4 用法舉例

img = cv2.imread(r".\image.jpg", cv2.IMREAD_COLOR)

# 縮小圖片,僅使用dsize參數
shrinkImg = cv2.resize(img, (int(cols/2), int(rows/2)), interpolation=cv2.INTER_AREA)

# 放大圖片,x方向(寬度)和y方向(高度)均放大兩倍,使用fx和fy參數,則dsize參數必須爲None
enlargeImg = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_LINEAR)

2. 圖像二值化

2.1 函數簡述和原型

通過該函數可以對圖像進行二值化處理,處理後的圖片非黑即白,這是一種非常常用的圖像處理手段。官方文檔:https://docs.opencv.org/3.4.2/d7/d1b/group__imgproc__misc.html#gae8a4a146d1ca78c626a53577199e9c57

retval, dst = cv2.threshold(src, thresh, maxval, type)

2.2 參數

  • src:要處理的圖像數據,爲單通道灰度圖像;
  • thresh:double類型,閾值;
  • maxval:double類型,二值化後的最大值,僅在cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV兩種二值化時有用;
  • type:二值化類型flags,常用的有如下幾種:
    • cv2.THRESH_BINARY:像素灰度值大於閾值時,取最大值,否則取0(黑色)。主要用於提取高亮部分,但所有細節均丟失;
    • cv2.THRESH_BINARY_INV:像素灰度值大於閾值時,取0(黑色),否則取最大值,實際上就是THRESH_BINARY取反的效果。主要用於提取暗部,但所有細節丟失;
    • cv2.THRESH_TRUNC:像素灰度值大於閾值時,直接減小到閾值,其餘部分不變,即僅將高亮部分丟失所有細節;
    • cv2.THRESH_TOZERO:像素灰度值未超過閾值時直接取0(黑色),超過閾值的保留原值,即僅保留高亮部分所有細節;
    • cv2.THRESH_TOZERO_INV:像素灰度值超過閾值的直接取0,未超過閾值的保留原值,即僅保留低於閾值部分所有細節,直接抹黑高亮,類似cv2.THRESH_TRUNC,但抹平高亮部分比trunk更厲害;
    • cv2.THRESH_OTSU:二值化時閾值往往需要通過經驗來判斷,但還有一種OSTU方法,可以尋找最佳的閾值。以上各種二值化方法直接加上該flag即表示閾值通過OSTU法自動計算;

2.3 返回值

  • retval:布爾類型,是否成功二值化處理圖像;
  • dst:二值化後的圖片數據;

2.4 用法舉例

img = cv2.imread(r'.\image.jpg', cv2.IMREAD_GRAYSCALE)

# 直接簡單二值閾值分割,灰度小於等於127則爲0(純黑色),大於127則爲255(純白色)
ret1, thBi = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)

# Otsu法(大津法——最大類間方差法)計算全局最佳閾值,因此第二個參數可以忽略
ret2, thOtsu = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

2.5 實例展示

下圖展示了幾種不同的二值化類型的差異,均以127爲閾值,最大值均爲255(白色):
二值化模式

3. 圖像自適應二值化

3.1 函數簡述和原型

該函數是上述二值化函數的改進版。很多時候一張灰度圖像的亮度並不是在各處都一致,因此在使用上述函數進行二值化時,即使使用OSTU法,計算出來的二值化閾值也不一定在一副圖像的不同區域都是最佳的。因此OpenCV還提供了自適應的二值化函數,通過該函數可以對圖像的不同區域動態計算並應用不同的閾值進行二值化。官方文檔:https://docs.opencv.org/3.4.2/d7/d1b/group__imgproc__misc.html#ga72b913f352e4a1b1b397736707afcde3

dst = cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)

3.2 參數

  • src:要處理的圖像數據,爲單通道灰度圖像;
  • maxValue:double類型,二值化後的最大值;
  • adaptiveMethod:動態計算閾值的方法,有以下兩種:
    • cv2.ADAPTIVE_THRESH_MEAN_C:計算區域內的平均值減去C;
    • cv2.ADAPTIVE_THRESH_GAUSSIAN_C:計算區域內的高斯均值減去C;
  • thresholdType:二值化類型flags,在該函數中僅能使用cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV兩種
  • blockSize:動態化計算閾值時所使用的區域的大小,類似卷積時的卷積核大小,需要爲奇數;
  • C:計算區域內的均值後減去的常量,最後作爲閾值;

3.3 返回值

  • dst:二值化後的圖片數據;

3.4 用法舉例

img = cv2.imread(r'.\image.jpg', cv2.IMREAD_GRAYSCALE)

# 計算11*11區域內的均值,再減去4(最後一個參數C)作爲閾值
th2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, 
							cv2.THRESH_BINARY, 11, 4)
# 計算17*17區域內的高斯均值,再減去6(最後一個參數C)作爲閾值
th3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
							cv2.THRESH_BINARY, 17, 6)

3.5 實例展示

對比簡單二值化和自適應二值化對某張圖像的應用如下:
二值化比較

4. 圖像繪製

4.1 函數簡述和原型

OpenCV提供了一系列圖像繪製的API,可以在圖像上進行各種基本繪製,如繪製直線、箭頭、各種形狀、添加文字等。官方文檔:https://docs.opencv.org/3.4.2/d6/d6e/group__imgproc__draw.html

# 在圖片上繪製直線
cv2.line(img, pt1, pt2, color[, thickness[, lineType[, shift]]])

# 在圖片上繪製箭頭
cv2.arrowedLine(img, pt1, pt2, color[, thickness[, line_type[, shift[, tipLength]]]])

# 在圖片上繪製一個直立的矩形(即沒有任何旋轉)
cv2.rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]])

# 在圖片上繪製圓形
cv2.circle(img, center, radius, color[, thickness[, lineType[, shift]]])

# 根據圓心、長軸長度、長軸方向、弧長夾角在圖片上繪製部分橢圓
cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType[, shift]]])
# 在圖片上繪製某個矩形的內切橢圓
cv2.ellipse(img, box, color[, thickness[, lineType]])

# 繪製多條線段,可以閉合形成多邊形
cv2.polylines(img, pts, isClosed, color[, thickness[, lineType[, shift]]])

# 繪製一個實心的多邊形
cv2.fillPoly(img, pts, color[, lineType[, shift[, offset]]])

# 在圖片上添加文字
cv2.putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]])

4.2 參數

  • img:要進行繪製的圖像;
  • pt1, pt2:在繪製直線、箭頭時,二者分別表示起點座標和終點座標;在繪製直立矩形時,二者分別表示矩形左上角和右下角的座標位置;
  • tipLength:double類型,默認值爲0.1,表示箭頭相對於箭頭直線長度的大小比例;
  • center:一個二元組,在繪製圓形和橢圓形時,表示圓心的座標;
  • radius:int類型,繪製圓形時表示圓的半徑;
  • axes:一個二元組,繪製部分橢圓形時分別表示橢圓在水平和豎直方向上的軸的長度,兩個軸較大的爲長軸,旋轉後兩個軸也不一定與x軸和y軸平行;
  • angle:double類型,繪製部分橢圓時表示橢圓的旋轉角度,順時針方向;
  • startAngle,endAngle:double類型,繪製部分橢圓時分別表示弧的起始位置/終止位置與圓心連線相對於(旋轉前)水平方向軸的夾角,順時針方向,當startAngle=0, endAngle=360時則表示將整個橢圓繪製出來;
  • box:繪製橢圓時的外切矩形,不一定是直立的矩形。可以通過一個三元組定義出來,元素分別爲矩形中心座標(二元組)、矩形寬高(二元組)、矩形順時針旋轉角度(float);
  • pts:使用polylines函數繪製多條線段時,各個頂點的座標,一個n*2的矩陣;使用fillPloly繪製填充多邊形時,由於可以同時填充多個多邊形,故需要是一個list,每個元素爲一個n*2的矩陣(表示一個n邊形);
  • isClosed:bool類型,繪製多條線段時是否閉合形成多邊形;
  • offset:一個二元組,在繪製填充多邊形時表示所有多邊形在x方向和y方向平移的距離,默認爲(0,0);
  • text:要添加的文本內容,字符串;
  • org:一個二元組,表示文本左下角所在位置的座標;
  • fontFace:字體類型,常用有如下幾種:
    • cv2.FONT_HERSHEY_SIMPLEX:普通字體;
    • cv2.FONT_HERSHEY_PLAIN:小號字體;
    • cv2.FONT_HERSHEY_SCRIPT_SIMPLEX:手寫體;
  • fontScale:double類型,字體大小;
  • bottomLeftOrigin:bool類型,默認值爲false,表示是否以圖片左下角作爲原點;
  • color:顏色,對於單通道灰度圖像,爲一個0-255之間的值;對於BGR彩色圖像,則爲一個三元組,值分別爲藍色、綠色和紅色的分量;
  • thickness:int類型,默認值爲1,表示繪製線段的寬度,若爲負數,如cv2.FILLED時,表示填充要繪製的形狀。注意使用polylines繪製多邊形時無法填充,填充多邊形必須使用fillPoly函數;
  • lineType:線段的類型,當thickness=cv2.FILLED時,該參數往往忽略。主要由以下幾種類型:
    • cv2.LINE_4:表示線段爲4鄰接線段;
    • cv2.LINE_8:表示線段爲8鄰接線段;
    • cv2.LINE_AA:表示線段爲抗鋸齒(antialiased)繪製;
  • shift:int類型,默認值爲0,各種座標中小數的位數,往往不需要設置(座標常常均以像素爲單位,爲整數);

4.3 返回值

上述函數均是對圖像進行原地修改的函數,故返回值爲None。

4.4 用法舉例

# 創建一個500*500的黑色畫布
canvas = np.zeros((500, 500, 3), dtype=np.uint8)

# 繪製一條紅色直線
cv2.line(canvas, (50, 50), (200, 50), color=(0, 0, 255), thickness=2, lineType=cv2.LINE_AA)

# 繪製一個黃色箭頭
cv2.arrowedLine(canvas, (250, 50), (450, 50), color=(0, 255, 255), thickness=2, line_type=cv2.LINE_AA, tipLength=0.3)

# 繪製一個白色矩形
cv2.rectangle(canvas, (50, 100), (200, 150), color=(255, 255, 255), thickness=2, lineType=cv2.LINE_AA)

# 繪製一個填充藍色的圓形
cv2.circle(canvas, (300, 125), 50, color=(255, 0, 0), thickness=cv2.FILLED)

# 繪製一個綠色橢圓形的上半部分
cv2.ellipse(canvas, (125, 220), (25, 50), 0, 180, 360, color=(0, 255, 0), thickness=3, lineType=cv2.LINE_AA)
# 在圖片上繪製某個矩形的內切橢圓
box = ((350, 220), (100, 50), 45.0)
cv2.ellipse(canvas, box, color=(0, 0, 255), thickness=3, lineType=cv2.LINE_AA)

# 繪製一個黃色的六邊形
center_x = 125
center_y = 330
pts = np.array([[center_x, center_y - 60], [center_x + 52, center_y - 30],
                [center_x + 52, center_y + 30], [center_x, center_y + 60],
                [center_x - 52, center_y + 30], [center_x - 52, center_y - 30]], np.int32)
cv2.polylines(canvas, pts=[pts], isClosed=True, color=(0, 255, 255), thickness=5, lineType=cv2.LINE_AA)

# 繪製兩個紅色的實心六邊形
center_x = 300
center_y = 330
pts1 = np.array([[center_x, center_y - 60], [center_x + 52, center_y - 30],
                [center_x + 52, center_y + 30], [center_x, center_y + 60],
                [center_x - 52, center_y + 30], [center_x - 52, center_y - 30]], np.int32)
center_x = 420
center_y = 330
pts2 = np.array([[center_x, center_y - 60], [center_x + 52, center_y - 30],
                [center_x + 52, center_y + 30], [center_x, center_y + 60],
                [center_x - 52, center_y + 30], [center_x - 52, center_y - 30]], np.int32)
cv2.fillPoly(canvas, [pts1, pts2], color=(0, 0, 255), lineType=cv2.LINE_AA)

# 在圖片上添加文字
cv2.putText(canvas, "Hello OpenCV!", (30, 470), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=2, color=(255, 255, 255), thickness=2, lineType=cv2.LINE_AA)

cv2.imshow('drawing', canvas)

4.5 實例展示

上述代碼的輸出如下圖:
圖像繪製

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