文章目錄
OpenCV學習——圖像基礎與幾何變換
0. 版本信息
產品 | 版本 |
---|---|
Python | 3.7 |
Anaconda | 4.8.3 |
Jupyter | 6.0.3 |
OpenCV | 3.4.2 |
1. 導包
import cv2
import numpy as np
print(cv2.__version__)
2. 圖像基礎
2.1 圖片的讀取、展示、保存
- 讀取圖片並展示
# 讀取相對路徑爲./test03.jpg的圖片 img = cv2.imread("./test03.jpg", 1) # 展示圖片到名爲picture的窗口 cv2.imshow("picture", img) # 等待按鍵,如果按下的是q,那麼關閉所有窗口 if cv2.waitKey() == ord("q"): cv2.destroyAllWindows() # cv2.destroyWindow("picture") # 關閉某個名稱的窗口
- 保存與壓縮圖片
# jpg 設置保存圖片的質量,有損壓縮 img = cv2.imread("test03.jpg", 1) cv2.imwrite("test03_copy_0.jpg", img, [cv2.IMWRITE_JPEG_QUALITY, 0]) cv2.imwrite("test03_copy_10.jpg", img, [cv2.IMWRITE_JPEG_QUALITY, 10]) cv2.imwrite("test03_copy_50.jpg", img, [cv2.IMWRITE_JPEG_QUALITY, 50]) cv2.imwrite("test03_copy_80.jpg", img, [cv2.IMWRITE_JPEG_QUALITY, 80])
# png 無損壓縮,透明度,壓縮比 0-10 值越低,壓縮率越低 img = cv2.imread("test03.jpg", 1) cv2.imwrite("test03_copy_0.png", img, [cv2.IMWRITE_PNG_COMPRESSION, 0]) cv2.imwrite("test03_copy_3.png", img, [cv2.IMWRITE_PNG_COMPRESSION, 3]) cv2.imwrite("test03_copy_5.png", img, [cv2.IMWRITE_PNG_COMPRESSION, 5]) cv2.imwrite("test03_copy_8.png", img, [cv2.IMWRITE_PNG_COMPRESSION, 8]) cv2.imwrite("test03_copy_10.png", img, [cv2.IMWRITE_PNG_COMPRESSION, 10])
2.2 圖片的基本信息
- 圖片的維度(包含高度、寬度、像素點的三個通道值)
print(img.shape)
(512, 820, 3)
- OpenCV中一個像素點的表示方式(BGR)
# 獲取其中的一個像素點 # opencv中表示的方式爲 BGR (即第一個是藍色通道的值,第二個是綠色通道的值,第三個是紅色通道的值) print(img[100, 150])
[203 109 36]
- 其他信息
# 每個元素的數據類型 uint8 即0-255 print(img.dtype) # 圖像大小 height * width * channels print(img.size)
uint8 1259520
2.3 修改圖片像素點的顏色信息
- 修改像素點
# 方式1 修改爲黑色 img[90, 160] = [0, 0, 0] print(img[90, 160]) # 方式2 性能更好,但需要一個一個設置 # 紅色 img.itemset((90, 170, 0), 0) img.itemset((90, 170, 1), 0) img.itemset((90, 170, 2), 255) print(img[90, 170])
[0 0 0] [ 0 0 255]
- 畫一條線
# 畫一條線 for i in range(0, 300): img[100, i] = [0, 0, 255] cv2.imshow("picture", img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
2.3 拆分與合併顏色三通道
- 拆分與合併顏色三通道
# 拆分通道 b, g, r = cv2.split(img) # 合併三通道 img = cv2.merge((b, g, r)) # 只有單通道的值,此時是灰度圖 print(b)
[[163 163 162 ... 173 173 173] [164 164 163 ... 175 175 175] [165 165 164 ... 174 175 175] ... [ 42 39 39 ... 51 52 52] [ 49 41 38 ... 66 67 66] [ 41 38 38 ... 96 95 95]]
- 對應通道的灰度圖
# 單獨展示藍色通道的值(灰度圖) cv2.imshow('blue', b) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows() # 獲取某個區域紅色通道對應的灰度圖 red_flower_img = img[180:310, 50:180][:, :, 2] cv2.imshow("red_flower", red_flower_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
- 修改某塊區域爲只顯示藍色通道
for i in range(0, 400): for j in range(0, 400): img.itemset((i, j, 1), 0) img.itemset((i, j, 2), 0) cv2.imshow('blue', img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
3. 繪圖
3.1 線段、三角形、矩形、圓形、扇形、任意多邊形
img = np.zeros((500, 500, 3), np.uint8)
# 畫線段
# img, 起點, 終點, 顏色
cv2.line(img, (50, 50), (200, 200), (255, 0, 0))
# img, 起點, 終點, 顏色, 寬度
cv2.line(img, (100, 100), (300, 100), (0, 255, 0), 10)
# img, 起點, 終點, 顏色, 寬度, 線條類型
cv2.line(img, (100, 150), (300, 150), (0, 255, 0), 10, cv2.LINE_AA)
# 畫三角形
points = [(400, 300), (300, 360), (240, 240)]
cv2.line(img, points[0], points[1], (0, 0, 255))
cv2.line(img, points[1], points[2], (0, 0, 255))
cv2.line(img, points[2], points[0], (0, 0, 255))
# 畫矩形
# img, 左上角, 右下角, 顏色, 是否填充
cv2.rectangle(img, (360, 150), (460, 200), (100, 0, 0), -1)
# 畫圓
# img, 圓心, 半徑, 顏色, 粗細
cv2.circle(img, (200, 360), (30), (0, 100, 0), 3)
# 扇形
# img, 中心, 軸長, 偏轉角度, 起始, 結束, 顏色, 填充
cv2.ellipse(img, (200, 400), (50, 80), 0, 0, 90, (0, 0, 100), -1)
# 任意多邊形
points = np.array([[270, 180], [220, 190], [330, 150], [310, 240]])
print(points.shape)
points = points.reshape((-1, 1, 2))
print(points.shape)
print(points)
cv2.polylines(img, [points], True, (255, 255, 255))
cv2.imshow("img", img)
if cv2.waitKey() == ord("q"):
cv2.destroyAllWindows()
3.2 文字、圖片
img = cv2.imread("./test03.jpg", 1)
height, width, channels = img.shape
# 畫文字
cv2.rectangle(img, (100, 110), (300, 150), (255, 255, 255), 2)
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, "Sun Flower", (110, 140), font, 1, (0, 0, 0), 1)
# 複製、畫圖
img2 = cv2.imread("./test03.jpg", 1)[150:400, 50:300]
height2, width2, channels2 = img2.shape
for i in range(0, height2):
for j in range(0, width2):
img[i, 400 + j] = img2[i, j]
cv2.imshow("img", img)
if cv2.waitKey() == ord("q"):
cv2.destroyAllWindows()
4. 圖像的幾何變換
4.1 圖像截取
flower_img = img[180:310, 50:180]
cv2.imshow("flower", flower_img)
if cv2.waitKey() == ord("q"):
cv2.destroyAllWindows()
4.2 圖像縮放
- 方式1
# 獲取到高度、寬度的一半的值 img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape dst_height = int(height / 2) dst_width = int(width / 2) # 進行縮放 dst_img = cv2.resize(img, (dst_width, dst_height)) # 注意先傳width,再傳height cv2.imshow("dst_img", dst_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
- 方式2
# 手動實現縮放 img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape dst_height = int(height / 2) dst_width = int(width / 2) # 縮放 dst_img = np.zeros((dst_height, dst_width, 3), np.uint8) print(dst_img.shape) for i in range(0, dst_height): for j in range(0, dst_width): new_i = int(i * (height / dst_height)) new_j = int(j * (width / dst_width)) dst_img[i, j] = img[new_i, new_j] cv2.imshow("dst_img", dst_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
- 方式3
# Affine img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape # 縮放 mat_scale = np.float32([[0.5, 0, 0], [0, 0.5, 0]]) dst_img = cv2.warpAffine(img, mat_scale, (int(width / 2), int(height / 2))) cv2.imshow("dst_img", dst_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
4.3 圖像移動
- 方式1
img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape # Affine,水平右移100,垂直下移200 matShift = np.float32([[1, 0, 100], [0, 1, 200]]) dst_img = cv2.warpAffine(img, matShift, (width, height)) cv2.imshow("dst_img", dst_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
- 方式2
# 手動實現移動,右移100 img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape dst_img = np.zeros(img.shape, np.uint8) for i in range(0, height): for j in range(0, width - 100): dst_img[i, j + 100] = img[i, j] cv2.imshow("dst_img", dst_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
4.4 圖像鏡像
img = cv2.imread("./test03.jpg", 1)
height, width, channels = img.shape
dst_img = np.zeros((height * 2, width, channels), np.uint8)
for i in range(0, height):
for j in range(0, width):
dst_img[i, j] = img[i, j] # 原圖
dst_img[height * 2 - i - 1, j] = img[i, j] # 反轉鏡像
cv2.imshow("dst_img", dst_img)
if cv2.waitKey() == ord("q"):
cv2.destroyAllWindows()
4.5 圖像旋轉
- 平面旋轉
img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape # 旋轉矩陣 # 參數:中心點,旋轉角度,縮放係數 mat_rotate = cv2.getRotationMatrix2D((width / 2, height / 2), 45, 0.5) dst_img = cv2.warpAffine(img, mat_rotate, (width, height)) cv2.imshow("dst_img", dst_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
- 空間旋轉
img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape # 左上角、左下角、右上角 mat_src = np.float32([[0, 0], [0, height - 1], [width - 1, 0]]) mat_dst = np.float32([[60, 60], [150, height - 150], [width - 250, 220]]) mat_affine = cv2.getAffineTransform(mat_src, mat_dst) dst_img = cv2.warpAffine(img, mat_affine, (width, height)) cv2.imshow("dst_img", dst_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()