OpenCV學習——圖像特效
0. 版本信息
產品 | 版本 |
---|---|
Python | 3.7 |
Anaconda | 4.8.3 |
Jupyter | 6.0.3 |
OpenCV | 3.4.2 |
1. 導包
import cv2
import numpy as np
import random
import math
2. 灰度圖
- 直接讀取灰度圖
# 1是讀取彩色, 0是讀取灰度 gray_img = cv2.imread("./test03.jpg", 0) # gray_img = cv2.imread("./test03.jpg", 1) cv2.imshow("gray", gray_img) if cv2.waitKey(0) == ord("q"): cv2.destroyAllWindows()
- 顏色模式轉換
img = cv2.imread("./test03.jpg", 1) # 第二個參數是轉換方式 dst_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) cv2.imshow("dst_img", dst_img) if cv2.waitKey(0) == ord("q"): cv2.destroyAllWindows()
- 手動轉換1
# 原理:當BGR中 B=G=R , 那麼是灰度圖 img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape # 改變每個像素點 for i in range(0, height): for j in range(0, width): # 此處採用均值 img[i, j] = img[i, j].mean() cv2.imshow("img", img) if cv2.waitKey(0) == ord("q"): cv2.destroyAllWindows()
- 手動轉換2
# 原理:gray = R*0.299 + G*0.587 + B*0.114 img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape # 改變每個像素點 for i in range(0, height): for j in range(0, width): b, g, r = img[i, j] gray = int(b * 0.114) + int(g * 0.587) + int(r * 0.299) img[i, j] = np.uint8(gray) cv2.imshow("img", img) if cv2.waitKey(0) == ord("q"): cv2.destroyAllWindows()
3. 顏色反轉
- 灰度圖-顏色反轉
# 灰度圖-顏色反轉 gray_img = cv2.imread("./test03.jpg", 0) height, width = gray_img.shape # 改變每個像素點 for i in range(0, height): for j in range(0, width): gray_img[i, j] = 255 - gray_img[i, j] cv2.imshow("gray_img", gray_img) if cv2.waitKey(0) == ord("q"): cv2.destroyAllWindows()
- 彩色圖-顏色反轉
# 彩色圖-顏色反轉 img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape # 改變每個像素點 for i in range(0, height): for j in range(0, width): img[i, j] = 255 - img[i, j] cv2.imshow("img", img) if cv2.waitKey(0) == ord("q"): cv2.destroyAllWindows()
4. 馬賽克效果
img = cv2.imread("./test03.jpg", 1)
# 每10x10的範圍選取首個像素點作爲其他所有點的顏色
# step步長決定了馬賽克的粗細
step = 10
for i in range(180, 310, step):
for j in range(50, 180, step):
for y in range(0, step):
for x in range(0, step):
img[i + y, j + x] = img[i, j]
cv2.imshow("img", img)
if cv2.waitKey(0) == ord("q"):
cv2.destroyAllWindows()
5. 毛玻璃效果
img = cv2.imread("./test03.jpg", 1)
height, width, channels = img.shape
# 對於每個點隨機取其右下10x10範圍的一個點
# mm是取值範圍,越大越廣
mm = 10
for i in range(0, height):
for j in range(0, width):
# 隨機取點
r = int(random.random() * mm)
r_i, r_j = i + r, j + r
# 處理越界點
if r_i >= height:
r_i = height - 1
elif r_i < 0:
r_i = 0
if r_j >= width:
r_j = width - 1
elif r_j < 0:
r_j = 0
# 修改像素點
img[i, j] = img[r_i, r_j]
cv2.imshow("img", img)
if cv2.waitKey(0) == ord("q"):
cv2.destroyAllWindows()
6. 圖片融合
# 圖片融合
# dst = src1 * a + src2 * (1 - a)
img1 = cv2.imread("./test03.jpg", 1)
img2 = cv2.imread("./test02.jpg", 1)
# 融合係數
a = 0.3
# ROI 選取300x300的興趣區域
img1_roi = img1[100:400, 100:400]
img2_roi = img2[200:500, 200:500]
# 開始融合
# 方式1
# img = cv2.addWeighted(img1_roi, 0.3, img2_roi, 0.7, 0)
# 方式2
img = np.zeros((300, 300, 3), np.uint8)
for i in range(0, 300):
for j in range(0, 300):
img[i, j] = img1_roi[i, j] * a + img2_roi[i, j] * (1 - a)
cv2.imshow("img", img)
if cv2.waitKey(0) == ord("q"):
cv2.destroyAllWindows()
7. 邊緣檢測
- canny邊緣檢測
img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape # 1 gray gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 2 gauss 高斯濾波 gauss_img = cv2.GaussianBlur(gray_img, (3, 3), 0) # 3 canny canny_img = cv2.Canny(gauss_img, 50, 50) cv2.imshow("canny_img", canny_img) if cv2.waitKey(0) == ord("q"): cv2.destroyAllWindows()
- sobel邊緣檢測
img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape # 灰度gray gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 1. 算子模板 卷積核 y_core = [[1, 2, 1], [0, 0, 0], [-1, -2, -1]] x_core = [[1, 0, -1], [2, 0, -2], [1, 0, -1]] # 開始處理 dst_img = np.zeros((height, width, 1), np.uint8) for i in range(0, height - 2): for j in range(0, width - 2): # 2. 圖片卷積 x y # 將當前點右下3x3的範圍與卷積核相乘,再求和 gradient_y = 0 gradient_x = 0 for m in range(0, 3): for n in range(0, 3): gradient_y += gray_img[i + m, j + n] * y_core[m][n] gradient_x += gray_img[i + m, j + n] * x_core[m][n] # gradient gradient = math.sqrt(gradient_y ** 2 + gradient_x ** 2) # 3. 閾值判決 dst_img[i, j] = 255 if gradient > 50 else 0 cv2.imshow("dst_img", dst_img) if cv2.waitKey(0) == ord("q"): cv2.destroyAllWindows()
8. 浮雕效果
# 讀取灰度圖
gray_img = cv2.imread("./test03.jpg", 0)
height, width = gray_img.shape
dst_img = np.zeros((height, width, 1), np.uint8)
for i in range(0, height):
for j in range(0, width - 1):
# 當前點和右邊一個點相減,再加150
new_pixel = int(gray_img[i, j]) - int(gray_img[i, j+1]) + 150
if new_pixel > 255:
new_pixel = 255
elif new_pixel < 0:
new_pixel = 0
dst_img[i, j] = new_pixel
cv2.imshow("dst_img", dst_img)
if cv2.waitKey(0) == ord("q"):
cv2.destroyAllWindows()
9. 油畫效果
# 讀取圖片
# img = cv2.imread("./test03.jpg", 1)[150:400, 50:300]
img = cv2.imread("C:\\Users\\Skey\\Pictures\\1\\timg2.jpg", 1)
height, width, channels = img.shape
# 灰度圖
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 將圖像分爲8x8的多個小塊,並統計小塊每個像素的灰度值
# 劃分灰度等級,例如0-255: 0-63, 64-127, ...
# 找出每個小塊中,每個等級的個數,找出最多的
# 用最多的的平均值替換原像素
dst_img = np.zeros((height, width, channels), np.uint8)
for i in range(0, height):
for j in range(0, width):
max_level_arr = []
levelMap = {} # k: 級別, v: 原始像素值的列表
for m in range(-4, 4):
for n in range(-4, 4):
# 處理越界
if i + m >= height or i + m < 0:
m = -m
if j + n >= width or j + n < 0:
n = -n
# 劃分等級 0-31, 32-63, ...
level = gray_img[i + m, j + n] // 32
if not level in levelMap.keys():
levelMap[level] = [img[i + m, j + n],]
else:
levelMap[level].append(img[i + m, j + n])
# 個數最多的級別
if len(levelMap[level]) > len(max_level_arr):
max_level_arr = levelMap[level]
# 取均值
size = len(max_level_arr)
b_sum, g_sum, r_sum = 0, 0, 0
for b, g, r in max_level_arr:
b_sum += b
g_sum += g
r_sum += r
dst_img[i, j] = [b_sum // size, g_sum // size, r_sum // size ]
cv2.imshow("dst_img", dst_img)
if cv2.waitKey() == ord("q"):
cv2.destroyAllWindows()