Try   HackMD

Python Opencv 常用功能

  • 讀取格式為 BGR

讀取圖片

參數 用法
cv2.IMREAD_COLOR 正常顏色
cv2.IMREAD_GRAYSCALE 灰色
cv2.IMREAD_UNCHANGED 正常顏色(包含透明度)
img = cv2.imread('./test.jpg')

img = cv2.imread('./test.jpg', cv2.IMREAD_GRAYSCALE)

寫入圖片

參數 用法
[cv2.IMWRITE_JPEG_QUALITY, 90] 設定 JPEG 圖片品質為 90(可用值為 0 ~ 100)
[cv2.IMWRITE_PNG_COMPRESSION, 5] 設定 PNG 壓縮層級為 5(可用值為 0 ~ 9)
# 寫入 img 到 './test.jpg' 檔案中,會依據傳入的副檔名而不同
cv2.imwrite('./test.jpg', img)

# 設定 JPEG 圖片品質為 90(可用值為 0 ~ 100)
cv2.imwrite('./test.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 90])

縮放圖片

| 參數 | 說明 | | cv2.INTER_AREA | 常用在縮小圖片 | | cv2.INTER_CUBIC | 常用在放大圖片、4x4像素鄰域的雙三次插值 | | cv2.INTER_NEAREST | 最近鄰插值 | | cv2.INTER_LINEAR | 雙線性插值(默認) | | cv2.INTER_LANCZOS4 | 8x8像素鄰域的Lanczos插值 |

# cv2.resize(img, (w, h))
img = cv2.resize(img, (20, 40), cv2.INTER_AREA)

顯示圖片

  • 後面必須要加上cv2.waitKey(0) 才會暫停且顯示圖片
# 顯示在名為 'My Image' 的視窗中
cv2.imshow('My Image', img)

顯示視窗

# 等待任意按鍵按下
cv2.waitKey(0)

# 等待 q 按下後跳出
if cv2.waitKey(1) & 0xFF == ord('q'):
  break

讓視窗可以自由縮放大小

# 讓 'My Image' 視窗可以自由縮放大小
cv2.namedWindow('My Image', cv2.WINDOW_NORMAL)

關閉圖片視窗

# 關閉 'My Image' 的圖片視窗
cv2.destroyWindow('My Image')

# 關閉所有視窗
cv2.destroyAllWindows()

圖片通道拆分

# 拆分成 B, G, R 通道
B, G, R = cv2.split(img)

圖片通道合併

# 合併 B, G, R 通道
merged_img = cv2.merge([B, G, R])

整張圖填滿同一個顏色

# 整張圖填滿 100
img.fill(100)

畫直線

# 畫直線,從 (0, 0) 到 (255, 255) 寬度 5px
cv2.line(img, (0, 0), (255, 255), (0, 0, 255), 5)

畫方框

# cv2.rectangle(影像, 頂點座標, 對向頂點座標, 顏色, 線條寬度)

cv2.rectangle(img, (20, 60), (120, 160), (0, 255, 0), 2)

# 線寬 -1 == 填滿顏色
cv2.rectangle(img, (20, 60), (120, 160), (0, 255, 0), -1)

畫圓形

# cv2.circle(影像, 圓心座標, 半徑, 顏色, 線條寬度)

cv2.circle(img, (90, 210), 30, (0, 255, 255), 3)

畫橢圓形

# cv2.ellipse(影像, 中心座標, 軸長, 旋轉角度, 起始角度, 結束角度, 顏色, 線條寬度)

# 傾斜 45 度的紫色橢圓形
cv2.ellipse(img, (180, 200), (25, 55), 45, 0, 360, (205, 0, 255), 2)

寫文字

字型參數 用法
cv2.FONT_HERSHEY_SIMPLEX
cv2.FONT_HERSHEY_PLAIN
cv2.FONT_HERSHEY_DUPLEX
cv2.FONT_HERSHEY_COMPLEX
cv2.FONT_HERSHEY_TRIPLEX
cv2.FONT_HERSHEY_COMPLEX_SMALL
cv2.FONT_HERSHEY_SCRIPT_SIMPLEX
cv2.FONT_HERSHEY_SCRIPT_COMPLEX
# cv2.putText(影像, 文字, 座標, 字型, 大小, 顏色, 線條寬度, 線條種類)

cv2.putText(img, text, (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 1, cv2.LINE_AA)

模糊降噪

# 平均模糊
# cv2.blur(gray, (kernel_size, kernel_size))
cv2.blur(gray, (3, 3))

# 高斯模糊
# cv2.GaussianBlur(gray, (kernel_size, kernel_size), 0)
cv2.GaussianBlur(gray, (3,3), 0)

# 中值模糊
# cv2.medianBlur(gray, kernel_size)
cv2.medianBlur(gray, 3)

# 雙向模糊、雙邊濾波器
# cv2.bilateralFilter(gray, color,pace,pace)
# color σ即顏色空間的標準差,愈大代表在計算時需要考慮更多的顏色
# pace σ即坐標空間的標準差,這個參數與Guassian filter使用的相同,數值越大,代表越遠的像素有較的權值
cv2.bilateralFilter(gray, 5, 21, 21)

圖片規一化

| 參數 | 說明 | | cv2.NORM_MINMAX | 陣列的數值被平移或縮放到一個指定的範圍,線性歸一化 | | cv2.NORM_INF | 切比雪夫距離、絕對值的最大值 | | cv2.NORM_L1 | 曼哈頓距離、絕對值的和 | | cv2.NORM_L2 | 歐幾里德距離|

# cv2.normalize(img, shape, min, max, cv2.NORM_MINMAX)

# Method 1
# 創建與 img 相同大小的 zero,歸一化後的圖片為 out
zero = np.zeros(shape=img.shape)
out = cv2.normalize(img, zero, 0, 1, cv2.NORM_MINMAX)

# Method 2
# 傳入 img 本身的話,結果會覆蓋回 img
cv2.normalize(img, img, 0, 1, cv2.NORM_MINMAX)

直方圖均衡化

# 必須為單一通道(灰階)才可以進行均衡化
cv2.equalizeHist(gray)

圖片 and、or、not

cv2.bitwise_and(X, Y)

cv2.bitwise_or(X, Y)

cv2.bitwise_not(X)

閥值

參數
cv2.THRESH_BINARY
cv2.THRESH_BINARY_INV
cv2.THRESH_TRUNC
cv2.THRESH_TOZERO
cv2.THRESH_TOZERO_INV
cv2.THRESH_MASK
cv2.THRESH_OTSU
cv2.THRESH_TRIANGLE
# 返回的 ret 為閥值
ret, img = cv2.threshold(img, 100, 150, cv2.THRESH_TRIANGLE)

ret1, img1 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

轉換成 HSV 格式

cv2.cvtColor(reimg, cv2.COLOR_BGR2HSV)

根據 HSV 取出某特定顏色的 mask

mask = cv2.inRange(img_hsv, (h_min, s_min, v_min), (h_max, s_max, v_max))

腐蝕

kernel_Ero = np.ones((3,1),np.uint8)
imgEro = cv2.erode(mask, kernel_Ero, iterations=1)

膨脹

kernel_Dia = np.ones((3,5),np.uint8)
imgDia = cv2.dilate(mask, kernel_Dia, iterations=3)

霍夫曼直線檢測

lines = cv2.HoughLines(canny, 1, np.pi / 180, 50)

for line in lines:
    rho, theta = line[0]
    a = np.cos(theta)
    b = np.sin(theta)

    x0 = a * rho
    y0 = b * rho
    x1 = int(x0 + 1000 * (-b))
    y1 = int(y0 + 1000 * a)
    x2 = int(x0 - 1000 * (-b))
    y2 = int(y0 - 1000 * a)
    cv2.line(img_rgb, (x1, y1), (x2, y2), (0, 0, 255), 2)

邊緣偵測

# cv2.Canny(blur_gray, low_threshold, high_threshold)
cv2.Canny(gray, 100, 255)

邊緣檢測[劃出最小矩形]

_,contouts,hie = cv2.findContours(imgDia,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)

for i in contouts:
    # 邊緣內面積像素點
    acc = cv2.contourArea(i)

    # 轉換出左上角x, y, width, height
    x,y,w,h = cv2.boundingRect(i)
    cv2.rectangle(img, (x, y), (int(x + w), int(y + h)), (0, 255, 255), 2)

    ## 劃出最小矩形(使用cv2.findContours)
    # center[(x, y), (h, w), angle of rotation]
    # 可以從 rect裡看出矩形旋轉的角度
    rect = cv2.minAreaRect(i)

    # box.shape=(4, 2)
    box = cv2.boxPoints(rect)  
    box = np.int0(box)
    cv2.drawContours(img, [box], 0, (0,0,255), 2)