OpenCV學習——圖像特效

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()
    
    圖片14

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()
    
    圖片15
  • 彩色圖-顏色反轉
    # 彩色圖-顏色反轉
    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()
    
    圖片16

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()

圖片17

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()

圖片18

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()

圖片19

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()
    
    圖片20
  • 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()
    
    圖片21

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()

圖片22

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()

原圖
油畫圖

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