1.將cv2.imread()
方法的第二引數設為0即可得到灰色影象
import cv2
import numpy as np
img0 = cv2.imread('img.jpg', 0)
img1 = cv2.imread('img.jpg', 1)
print(img0.shape)
print(img1.shape)
cv2.imshow('img0', img0)
cv2.waitKey(0)
(270, 360)
(270, 360, 3)
2.通過cv2.cvtColor
方法對影象進行灰度轉換
cv2.cvtColor(src, code, dst, dstCN):
-src: 目標影象
-code: 顏色轉換方式
-dst: 影象大小
-dstCN: 顏色通道大小
import cv2
import numpy as np
img = cv2.imread('img.jpg', 1)
dat = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY )
cv2.imshow('dat', dat)
cv2.waitKey(0)
原理
灰色影象的所有顏色通道的值相等,所以要想將彩色影象變為灰色影象,只需將他們顏色通道的值相等即可。
3.下面我們通過原始碼設定它們的顏色均值來使彩色影象變為灰色影象
import cv2
import numpy as np
img = cv2.imread('img.jpg', 1)
dat = np.zeros((img.shape[0], img.shape[1]), np.uint8)
for i in range(0, img.shape[0]):
for j in range(0, img.shape[1]):
(b, g, r) = img[i, j]
gray = (int(b) + int(g) +int(r)) / 3
dat[i, j] = np.uint(gray)
cv2.imshow('dat', dat)
cv2.waitKey(0)
4.通過設定 gray = r * 0.299 + g * 0.587 + b * 0.114
來變為灰色影象
import cv2
import numpy as np
img = cv2.imread('img.jpg', 1)
dat = np.zeros((img.shape[0], img.shape[1]), np.uint8)
for i in range(0, img.shape[0]):
for j in range(0, img.shape[1]):
(b, g, r) = img[i, j]
gray = int(b) * 0.114 + int(g) * 0.587 +int(r) * 0.299
dat[i, j] = np.uint(gray)
cv2.imshow('dat', dat)
cv2.waitKey(0)
將影象的顏色反轉也就是讓255減去當前的顏色值
下面我們來實現灰色影象的顏色反轉:
import cv2
import numpy as np
img = cv2.imread('img.jpg', 1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
dat = np.zeros((img.shape[0], img.shape[1]), np.uint8)
for i in range(gray.shape[0]):
for j in range(gray.shape[1]):
dat[i, j] = 255 - gray[i, j]
cv2.imshow('dat', dat)
cv2.waitKey(0)
彩色影象的顏色反轉也是一樣的道理:
import cv2
import numpy as np
img = cv2.imread('img.jpg', 1)
dat = np.zeros((img.shape[0], img.shape[1], img.shape[2]), np.uint8)
for i in range(img.shape[0]):
for j in range(img.shape[1]):
(b, g, r) = img[i, j]
dat[i, j] = (255 - b, 255 - g, 255 - r)
cv2.imshow('src', img)
cv2.imshow('dat', dat)
cv2.waitKey(0)
原理: 取一個指定大小的視窗,將該視窗填充為一個顏色
下面我們將視窗設定為10*10
來生成一個馬賽克影象
import cv2
import numpy as np
img = cv2.imread('img.jpg', 1)
height = img.shape[0]
width = img.shape[1]
for m in range(50, 150):
for n in range(100, 200):
if m % 10 == 0 and n % 10 == 0:
for i in range(10):
for j in range(10):
(b, g,r) = img[m, n]
img[m + i, n + j] = (b, g, r)
cv2.imshow('img', img)
cv2.waitKey(0)
原理: 將當前的畫素顏色隨機設定為視窗中的一個顏色
這裡我們設定視窗為8*8
來生成一個毛玻璃影象
import cv2
import random
import numpy as np
img = cv2.imread('img.jpg', 1)
height = img.shape[0]
width = img.shape[1]
dat = np.zeros(img.shape, np.uint8)
for m in range(height - 8):
for n in range(width - 8):
index = int(random.random() * 8)
(b, g, r) = img[m + index, n + index]
dat[m, n] = (b, g, r)
cv2.imshow('dat', dat)
cv2.waitKey(0)
圖片乘以比例係數相加得到倆張圖片的融合效果:
target = src1 * a +src2 * (1 - a)
cv2.addWeighted(src1, alpha, src2, beta, gamma):
-src1: 第一張影象
-alpha: 第一張影象的權重
-src2: 第二張影象
-beta: 第二張影象的權重
-gamma: 要新增的標量
import cv2
import numpy as np
img1 = cv2.imread('img3.jpg', 1)
img2 = cv2.imread("img2.png", 1)
dat = np.zeros(img1.shape, np.uint8)
dat = cv2.addWeighted(img1, 0.5, img2, 0.5, 0)
cv2.imshow('dat', dat)
cv2.waitKey(0)
canny
邊緣檢測:
首先,影象降噪。我們知道梯度運算元可以用於增強影象,本質上是通過增強邊緣輪廓來實現的,也就是說是可以檢測到邊緣的。但是,它們受噪聲的影響都很大。那麼,我們第一步就是想到要先去除噪聲,因為噪聲就是灰度變化很大的地方,所以容易被識別為偽邊緣。
第二步,計算影象梯度,得到可能邊緣。計算影象梯度能夠得到影象的邊緣,因為梯度是灰度變化明顯的地方,而邊緣也是灰度變化明顯的地方。當然這一步只能得到可能的邊緣。因為灰度變化的地方可能是邊緣,也可能不是邊緣。這一步就有了所有可能是邊緣的集合。
第三步,非極大值抑制。通常灰度變化的地方都比較集中,將區域性範圍內的梯度方向上,灰度變化最大的保留下來,其它的不保留,這樣可以剔除掉一大部分的點。將有多個畫素寬的邊緣變成一個單畫素寬的邊緣。即「胖邊緣」變成「瘦邊緣」。
第四步,雙閾值篩選。通過非極大值抑制後,仍然有很多的可能邊緣點,進一步的設定一個雙閾值,即低閾值(low),高閾值(high)。灰度變化大於high的,設定為強邊緣畫素,低於low的,剔除。在low和high之間的設定為弱邊緣。進一步判斷,如果其領域內有強邊緣畫素,保留,如果沒有,剔除。
這樣做的目的是隻保留強邊緣輪廓的話,有些邊緣可能不閉合,需要從滿足low和high之間的點進行補充,使得邊緣儘可能的閉合。
import cv2
import numpy
import random
img = cv2.imread('img.jpg', 1)
cv2.imshow('src', img)
# canny 1 gray 2 高斯 3 canny
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
imgG = cv2.GaussianBlur(gray, (3,3), 0)
dat = cv2.Canny(img, 50, 50)
cv2.imshow('dat', dat)
cv2.waitKey(0)
sobel運算元:
利用Sobel運算元對影象的每一個畫素進行折積運算得到影象梯度( x 方向和 y 方向),我們可以通過計算sqrt(a**2 + b**2)
來得到梯度幅值
(其中 a 和 b 分別為水平方向的梯度和豎直方向的梯度),判斷該值是否大於判決門限,如果大於則認為是邊緣
下面我們用原始碼來實現:
import cv2
import math
import numpy as np
import random
img = cv2.imread('img.jpg', 1)
cv2.imshow('src', img)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 轉換為灰色影象
dat = np.zeros((img.shape[0], img.shape[1], 1), np.uint8) #生成空模板
for i in range(img.shape[0] - 2):
for j in range(img.shape[1] - 2):
# 求梯度
gy = gray[i, j] + gray[i, j + 1] * 2 + gray[i,j + 2] - (gray[i + 2, j] + gray[i + 2, j + 1] * 2 + gray[i + 2, j + 2])
gx = gray[i, j] + gray[i + 1, j] * 2 + gray[i + 2, j] - (gray[i, j + 2] + gray[i + 1, j + 2] * 2 + gray[i + 2, j + 2])
#得到梯度幅值
grad = math.sqrt(gx*gx + gy*gy)
if grad > 50: # 判斷是否為邊緣
dat[i, j] = 255
else:
dat[i, j] = 0
cv2.imshow('dat', dat)
cv2.waitKey(0)