国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

這篇具有很好參考價值的文章主要介紹了OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

一、圖像平滑

1、2D卷積

我們可以對 2D 圖像實施低通濾波(LPF),高通濾波(HPF)等。
LPF 幫助我們?nèi)コ胍?,模糊圖像。HPF 幫助我們找到圖像的邊緣。

OpenCV 提供的函數(shù) cv.filter2D() 可以讓我們對一幅圖像進(jìn)行卷積操作。

'''
下面我們將對一幅圖像使用平均濾波器(kernel核中的參數(shù)和為1,所有參數(shù)值相同),

將核放在圖像的一個像素 A 上,求與核對應(yīng)的圖像上 25(5x5)個像素的和,在取平均數(shù),用這個平均數(shù)替代像素 A 的值。
重復(fù)以上操作直到將圖像的每一個像素值都更新一遍。
'''

img = cv.imread('open_cv_logo.png')
kernel = np.ones((5,5),np.float32) / 25
print(kernel)
[[0.04 0.04 0.04 0.04 0.04]
 [0.04 0.04 0.04 0.04 0.04]
 [0.04 0.04 0.04 0.04 0.04]
 [0.04 0.04 0.04 0.04 0.04]
 [0.04 0.04 0.04 0.04 0.04]]
dst = cv.filter2D(img,-1,kernel)


plt.subplot(121),plt.imshow(img),plt.title('Original'),plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(dst),plt.title('Averaging'),plt.xticks([]), plt.yticks([])
plt.show()

OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

?

img = cv.imread('./data/xiaoren.png')

plt.figure(figsize=(10,5))

kernel = np.array(
    [
        [1,2,1],
        [0,-8,0],
        [1,2,1]
    ]
)


dst = cv.filter2D(img,-1,kernel)


plt.subplot(121),plt.imshow(cv.cvtColor(img,cv.COLOR_BGR2RGB)),plt.title('Original'),plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(cv.cvtColor(dst,cv.COLOR_BGR2RGB)),plt.title('Define kernel'),plt.xticks([]), plt.yticks([])
plt.show()

OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

?

2、圖像模糊

使用低通濾波器可以達(dá)到圖像模糊的目的。這對與去除噪音很有幫助。

其實就是去除圖像中的高頻成分(比如:噪音,邊界)。所以邊界也會被模糊一點(diǎn)。(當(dāng)然,也有一些模糊技術(shù)不會模糊掉邊界)。
OpenCV 提供了四種模糊技術(shù)。

'''
1、平均

這是由一個歸一化卷積框完成的。用卷積框覆蓋區(qū)域所有像素的平均值來代替中心元素。
可以使用函數(shù) cv2.blur() 和 cv2.boxFilter() 來完這個任務(wù)。
我們需要設(shè)定卷積框的寬和高。

下面是一個 3x3 的歸一化卷積框:
K = [
        [1,1,1],
        [1,1,1],
        [1,1,1]
    ] / 9

如果你不想使用歸一化卷積框,你應(yīng)該使用 cv2.boxFilter(),這時要傳入?yún)?shù) normalize=False。
'''
img = cv.imread('./data/xiaoren.png')
blur = cv.blur(img,ksize=(11,11))

plt.subplot(121),plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB)),plt.title('Original'),plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(cv.cvtColor(blur, cv.COLOR_BGR2RGB)),plt.title('Blurred'),plt.xticks([]), plt.yticks([])
plt.show()

OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?
?

'''
2、高斯模糊


把卷積核換成高斯核(簡單來說,方框不變,將原來每個方框的值是相等的,現(xiàn)在里面的值是符合高斯分布的,方框中心的值最大,其余方框根據(jù)
距離中心元素的距離遞減,構(gòu)成一個高斯小山包。原來的求平均數(shù)現(xiàn)在變成求加權(quán)平均數(shù),全就是方框里的值)。

實現(xiàn)的函數(shù)是 cv2.GaussianBlur()。
我們需要指定高斯核的寬和高(必須是奇數(shù))。以及高斯函數(shù)沿 X,Y 方向的標(biāo)準(zhǔn)差。

如果我們只指定了 X 方向的的標(biāo)準(zhǔn)差,Y 方向也會取相同值。如果兩個標(biāo)準(zhǔn)差都是 0,那么函數(shù)會根據(jù)核函數(shù)的大小自己計算。
高斯濾波可以有效的從圖像中去除高斯噪音。
'''

plt.figure(figsize=(20,10))

img = cv.imread('./data/koala.png')
#0 是指根據(jù)窗口大?。?,5)來計算高斯函數(shù)標(biāo)準(zhǔn)差
blur = cv.GaussianBlur(img, ksize=(5,5), sigmaX=10.0, sigmaY=10.0)

plt.subplot(121),plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB)),plt.title('Original'),plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(cv.cvtColor(blur, cv.COLOR_BGR2RGB)),plt.title('Blurred'),plt.xticks([]), plt.yticks([])
plt.show()

OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

?

'''
3、中值模糊

顧名思義就是用與卷積框?qū)?yīng)像素的中值來替代中心像素的值。這個濾波器經(jīng)常用來去除椒鹽噪聲。
(即將卷積域內(nèi)的所有像素按照從小到大排序,然后獲取中間值作為卷積的輸出。)


前面的濾波器都是用計算得到的一個新值來取代中心像素的值,而中值濾波是用中心像素周圍(也可以使他本身)的值來取代他。
他能有效的去除噪聲。卷積核的大小也應(yīng)該是一個奇數(shù)。
'''
# 加載圖像
img = cv.imread('./data/xiaoren.png')

# 加噪聲數(shù)據(jù)
noisy_img = np.random.normal(10, 10, (img.shape[0], img.shape[1], img.shape[2]))
noisy_img = np.clip(noisy_img, 0, 255).astype(np.uint8)
img = img + noisy_img

# 轉(zhuǎn)換為灰度圖像
img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# 做一個中值過濾
dst = cv.medianBlur(img, ksize=5)

# 可視化
plt.subplot(121)
plt.imshow(img, 'gray')
plt.title('Original')

plt.subplot(122)
plt.imshow(dst, 'gray')
plt.title('medianBlur')
plt.show()

OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

'''
4、雙邊濾波


函數(shù) cv2.bilateralFilter() 能在保持邊界清晰的情況下有效的去除噪音。

但是這種操作與其他濾波器相比會比較慢。
我們已經(jīng)知道高斯濾波器是求中心點(diǎn)鄰近區(qū)域像素的高斯加權(quán)平均值。
這種高斯濾波器只考慮像素之間的空間關(guān)系,而不會考慮像素值之間的關(guān)系(像素的相似度)。
所以這種方法不會考慮一個像素是否位于邊界。因此邊界也不會模糊掉,而這正不是我們想要。


雙邊濾波在同時使用空間高斯權(quán)重和灰度值相似性高斯權(quán)重。

空間高斯函數(shù)確保只有鄰近區(qū)域的像素對中心點(diǎn)有影響,灰度值相似性高斯函數(shù)確保只有與中心像素灰度值相近的才會被用來做模糊運(yùn)算。
所以這種方法會確保邊界不會被模糊掉,因為邊界處的灰度值變化比較大。
'''
# 雙邊濾波: 中間的紋理刪除,保留邊緣信息
# 加載圖像
img = cv.imread('./data/xiaoren.png')

# 做一個雙邊濾波
dst = cv.bilateralFilter(img, d=9, sigmaColor=75, sigmaSpace=75)

# 可視化
plt.subplot(121)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.title('Original')

plt.subplot(122)
plt.imshow(cv.cvtColor(dst, cv.COLOR_BGR2RGB))
plt.title('bilateralFilter')
plt.show()

OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

二、形態(tài)學(xué)轉(zhuǎn)換

主要包括腐蝕、擴(kuò)張、打開、關(guān)閉等操作;主要操作是基于kernel核的操作
常見的核主要有:矩陣、十字架、橢圓結(jié)構(gòu)的kernel

kernel1 = cv.getStructuringElement(cv.MORPH_RECT, ksize=(5,5))
print("矩形kernel:\n{}".format(kernel1))

kernel2 = cv.getStructuringElement(cv.MORPH_CROSS, ksize=(5,5))
print("十字架kernel:\n{}".format(kernel2))

kernel3 = cv.getStructuringElement(cv.MORPH_ELLIPSE, ksize=(5,5))
print("橢圓kernel:\n{}".format(kernel3))
矩形kernel:
[[1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]]
十字架kernel:
[[0 0 1 0 0]
 [0 0 1 0 0]
 [1 1 1 1 1]
 [0 0 1 0 0]
 [0 0 1 0 0]]
橢圓kernel:
[[0 0 1 0 0]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [0 0 1 0 0]]

1、腐蝕

腐蝕的意思是將邊緣的像素點(diǎn)進(jìn)行一些去除的操作;
腐蝕的操作過程就是讓kernel核在圖像上進(jìn)行滑動,當(dāng)內(nèi)核中的所有像素被視為1時,原始圖像中對應(yīng)位置的像素設(shè)置為1,否則設(shè)置為0.

  • 其主要效果是:可以在圖像中減少前景圖像(白色區(qū)域)的厚度,有助于減少白色噪音,可以用于分離兩個連接的對象
  • 一般應(yīng)用與只有黑白像素的灰度情況
'''
    第一種方式
'''
kernel = cv.getStructuringElement(cv.MORPH_ERODE, (5,5))
dst = cv.morphologyEx(img, cv.MORPH_ERODE, kernel)

# 可視化
plt.subplot(121)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.title('Original')

plt.subplot(122)
plt.imshow(cv.cvtColor(dst, cv.COLOR_BGR2RGB))
plt.title('erode')
plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

'''
    第二種方式
'''
img = cv.imread('./data/j.png',0)


# a. 定義一個核(全部設(shè)置為1表示對核中5*5區(qū)域的所有像素均進(jìn)行考慮,設(shè)置為0表示不考慮)
kernel = np.ones((5,5),np.uint8)
# b. 腐蝕操作
dst = cv.erode(img,kernel,iterations=1,borderType=cv.BORDER_REFLECT)

# 可視化
plt.subplot(121)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.title('Original')

plt.subplot(122)
plt.imshow(cv.cvtColor(dst, cv.COLOR_BGR2RGB))
plt.title('erode')
plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

2、擴(kuò)張、膨脹

和腐蝕的操作相反,其功能是增加圖像的白色區(qū)域的值

只要在kernel中所有像素中有可以視為1的像素值,那么就將原始圖像中對應(yīng)位置的像素值設(shè)置為1,否則設(shè)置為0。

通常情況下,在去除噪音后,可以通過擴(kuò)張在恢復(fù)圖像的目標(biāo)區(qū)域信息。

'''
    第一種方式
'''
kernel = cv.getStructuringElement(cv.MORPH_DILATE, (5,5))
dst = cv.morphologyEx(img, cv.MORPH_DILATE, kernel)

# 可視化
plt.subplot(121)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.title('Original')

plt.subplot(122)
plt.imshow(cv.cvtColor(dst, cv.COLOR_BGR2RGB))
plt.title('dilate')
plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

'''
    第二種方式
'''
img = cv.imread('./data/j.png',0)


# a. 定義一個核(全部設(shè)置為1表示對核中5*5區(qū)域的所有像素均進(jìn)行考慮,設(shè)置為0表示不考慮)
kernel = np.ones((5,5),np.uint8)
# b. 膨脹操作
dst = cv.dilate(img,kernel,iterations=1,borderType=cv.BORDER_REFLECT)

# 可視化
plt.subplot(121)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.title('Original')

plt.subplot(122)
plt.imshow(cv.cvtColor(dst, cv.COLOR_BGR2RGB))
plt.title('dilate')
plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

3、Open

Open其實指的就是先做一次腐蝕,然后再做一次擴(kuò)張操作,一般用于去除噪音數(shù)據(jù)。

# 加載圖像
img = cv.imread('./data/j.png', 0)

# 加載噪音數(shù)據(jù)(白色噪音)
rows, cols = img.shape
for i in range(100):
    x = np.random.randint(cols)
    y = np.random.randint(rows)
    img[y,x] = 255

'''
    第一種方式
'''
# a. 定義一個核(全部設(shè)置為1表示對核中5*5區(qū)域的所有像素均進(jìn)行考慮,設(shè)置為0表示不考慮)
kernel = np.ones((5,5),np.uint8)
# b. 先進(jìn)行腐蝕操作
dst1 = cv.erode(img,kernel,iterations=1,borderType=cv.BORDER_REFLECT)
# c. 后進(jìn)行膨脹操作
dst2 = cv.dilate(dst1,kernel,iterations=1,borderType=cv.BORDER_REFLECT)


# 可視化
plt.subplot(121)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.title('Original')

plt.subplot(122)
plt.imshow(cv.cvtColor(dst2, cv.COLOR_BGR2RGB))
plt.title('open')
plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

'''
    第二種方式
'''
# a. 定義一個核(全部設(shè)置為1表示對核中5*5區(qū)域的所有像素均進(jìn)行考慮,設(shè)置為0表示不考慮)
kernel = np.ones((5,5), np.uint8)
# b. Open操作
dst = cv.morphologyEx(img, op=cv.MORPH_OPEN, kernel=kernel, iterations=1)


# 可視化
plt.subplot(121)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.title('Original')

plt.subplot(122)
plt.imshow(cv.cvtColor(dst, cv.COLOR_BGR2RGB))
plt.title('open')
plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

4、Closing

Closing其實指的就是先做一次擴(kuò)張,再做一次腐蝕
對前景圖像中的如果包含黑色點(diǎn),有去除的效果。

# 加載圖像
img = cv.imread('./data/j.png', 0)

# 加載噪音數(shù)據(jù)
rows, cols = img.shape
# 加白色點(diǎn)
for i in range(100):
    x = np.random.randint(cols)
    y = np.random.randint(rows)
    img[y,x] = 255

# 加黑色點(diǎn)
for i in range(1000):
    x = np.random.randint(cols)
    y = np.random.randint(rows)
    img[y,x] = 0
'''
    第一種方式
'''

# a. 定義一個核(全部設(shè)置為1表示對核中5*5區(qū)域的所有像素均進(jìn)行考慮,設(shè)置為0表示不考慮)
kernel = np.ones((5,5), np.uint8)
# b. 再膨脹
dst = cv.dilate(img, kernel, iterations=1)

# c. 先腐蝕
dst = cv.erode(dst, kernel, iterations=1)



# 可視化
plt.subplot(121)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.title('Original')

plt.subplot(122)
plt.imshow(cv.cvtColor(dst, cv.COLOR_BGR2RGB))
plt.title('open')
plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

'''
    第二種方式
'''

# a. 定義一個核(全部設(shè)置為1表示對核中5*5區(qū)域的所有像素均進(jìn)行考慮,設(shè)置為0表示不考慮)
kernel = np.ones((5,5), np.uint8)
# b. Closing操作
dst = cv.morphologyEx(img, op=cv.MORPH_CLOSE, kernel=kernel, iterations=1)

# c. 可視化
# 可視化
plt.subplot(121)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.title('Original')

plt.subplot(122)
plt.imshow(cv.cvtColor(dst, cv.COLOR_BGR2RGB))
plt.title('open')
plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

5、Morphological Gradient(形態(tài)梯度)

在膨脹和腐蝕圖像之間獲取一個差集,也就是Gradient=Dilate - Erode;

該操作的作用能夠提取邊緣特征信息。

img = cv.imread('./data/j.png', 0)

# a. 定義一個核(全部設(shè)置為1表示對核中5*5區(qū)域的所有像素均進(jìn)行考慮,設(shè)置為0表示不考慮)
kernel = np.ones((5,5), np.uint8)

# b. 形態(tài)梯度(dilate - erode)
dst = cv.morphologyEx(img, op=cv.MORPH_GRADIENT, kernel=kernel, iterations=1)

# 可視化
plt.subplot(121)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.title('Original')

plt.subplot(122)
plt.imshow(cv.cvtColor(dst, cv.COLOR_BGR2RGB))
plt.title('Gradient')
plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

6、Top Hat

在原始圖像和Open操作的圖像上做一個差集,也就是Top Hat=image - Open;

該操作的主要作用是可以提取一些非交叉點(diǎn)的信息。一般不用。

img = cv.imread('./data/j.png', 0)

# a. 定義一個核(全部設(shè)置為1表示對核中9*9區(qū)域的所有像素均進(jìn)行考慮,設(shè)置為0表示不考慮)
kernel = np.ones((9,9), np.uint8)

# b1. Open(先腐蝕,再擴(kuò)展)
dst1 = cv.morphologyEx(img, op=cv.MORPH_OPEN, kernel=kernel, iterations=1)
# b2. Top Hat(src - open)
dst2 = cv.morphologyEx(img, op=cv.MORPH_TOPHAT, kernel=kernel, iterations=1)



# 可視化
plt.subplot(131)
plt.imshow(img, 'gray')
plt.title('img')

plt.subplot(132)
plt.imshow(dst1, 'gray')
plt.title('Open')

plt.subplot(133)
plt.imshow(dst2, 'gray')
plt.title('TopHat')
plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度
?

7、Black Hat

在Close操作的圖像和原始圖像上做一個差集,也就是Black Hat = Close -image;

該操作的主要作用是可以提取一些交叉點(diǎn)附件的位置特征信息。一般不用。

# a. 定義一個核(全部設(shè)置為1表示對核中9*9區(qū)域的所有像素均進(jìn)行考慮,設(shè)置為0表示不考慮)
kernel = np.ones((9,9), np.uint8)

# b1. Close(先膨脹,再腐蝕)
dst1 = cv.morphologyEx(img, op=cv.MORPH_CLOSE, kernel=kernel, iterations=1)
# b2. Black Hat(close - src)
dst2 = cv.morphologyEx(img, op=cv.MORPH_BLACKHAT, kernel=kernel, iterations=1)
# dst2 = dst1 - img

# c. 可視化
plt.subplot(131)
plt.imshow(img, 'gray')
plt.title('img')

plt.subplot(132)
plt.imshow(dst1, 'gray')
plt.title('Close')

plt.subplot(133)
plt.imshow(dst2, 'gray')
plt.title('BlackHat')
plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

三、圖像梯度

除了前面介紹的普通濾波/卷積操作外,在圖像空域上而言,還存在一些比較重要的特征信息,

比如:邊緣(Edge)特征信息;
邊緣信息指的就是像素值明顯變化的區(qū)域,具有非常豐富的語義信息,常用于物體識別等領(lǐng)域

通過對圖像梯度的操作,可以發(fā)現(xiàn)圖像的邊緣信息
在OpenCV中提供了三種類型的高通濾波器,常見處理方式:Sobel、Scharr以及Laplacian導(dǎo)數(shù)

1、Sobel

主要就是梯度和高斯平滑的結(jié)合,在求解梯度之前,首先進(jìn)行一個高斯平滑的操作。

# 加載圖像
img = cv.imread('./data/xiaoren.png', 0)

# 畫幾條線條
rows, cols = img.shape
cv.line(img, pt1=(0,rows//3), pt2=(cols,rows//3), color=0, thickness=5)
cv.line(img, pt1=(0,2*rows//3), pt2=(cols,2*rows//3), color=0, thickness=5)
cv.line(img, pt1=(cols//3,0), pt2=(cols//3,rows), color=0, thickness=5)
cv.line(img, pt1=(2*cols//3,0), pt2=(2*cols//3,rows), color=0, thickness=5)
cv.line(img, pt1=(0,0), pt2=(cols,rows), color=0, thickness=1)
print("")

?

# x方向的的Sobel過濾,ksize:一般取值為3,5,7;
# 第二個參數(shù):ddepth,給定輸出的數(shù)據(jù)類型的取值范圍,默認(rèn)為unit8的,取值為[0,255],如果給定-1,表示輸出的數(shù)據(jù)類型和輸入一致。
sobelx = cv.Sobel(img, 6, dx=1, dy=0, ksize=5)
sobely = cv.Sobel(img, cv.CV_64F, dx=0, dy=1, ksize=5)

sobelx2 = cv.Sobel(img, cv.CV_64F, dx=2, dy=0, ksize=5)
sobely2 = cv.Sobel(img, cv.CV_64F, dx=0, dy=2, ksize=5)

sobel = cv.Sobel(img, cv.CV_64F, dx=1, dy=1, ksize=5)

sobelx_y = cv.Sobel(sobelx, cv.CV_64F, dx=0, dy=1, ksize=5)
sobely_x = cv.Sobel(sobely, cv.CV_64F, dx=1, dy=0, ksize=5)


# c. 可視化
plt.figure(figsize=(20,10))

plt.subplot(241)
plt.imshow(img, 'gray')
plt.title('img')

plt.subplot(242)
plt.imshow(sobelx, 'gray')
plt.title('sobelx')

plt.subplot(243)
plt.imshow(sobely, 'gray')
plt.title('sobely')

plt.subplot(244)
plt.imshow(sobelx2, 'gray')
plt.title('sobelx2')

plt.subplot(245)
plt.imshow(sobely2, 'gray')
plt.title('sobely2')

plt.subplot(246)
plt.imshow(sobel, 'gray')
plt.title('sobel')

plt.subplot(247)
plt.imshow(sobelx_y, 'gray')
plt.title('sobelx_y')

plt.subplot(248)
plt.imshow(sobely_x, 'gray')
plt.title('sobely_x')

plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

'''
自定義kernel,實現(xiàn)sobel
'''
kernel = np.asarray([
    [-1, -2, -1],
    [0, 0, 0],
    [1, 2, 1]
])
# 做一個卷積操作
# 第二個參數(shù)為:ddepth,一般為-1,表示不限制,默認(rèn)值即可。
sobely = cv.filter2D(img, 6, kernel)
sobelx = cv.filter2D(img, 6, kernel.T)

plt.figure(figsize=(10,5))
# 可視化
plt.subplot(131)
plt.imshow(img, 'gray')
plt.title('Original')

plt.subplot(132)
plt.imshow(sobelx, 'gray')
plt.title('sobelx')

plt.subplot(133)
plt.imshow(sobely, 'gray')
plt.title('sobely')
plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

'''
sobelx
=
    [
        [-1, 0, 1],
        [-2, 0, 2],
        [-1, 0, 1]
    ]
=   [-1 0 1](水平梯度) X [1 2 1].T(高斯平滑)


sobely
=
    [
        [-1, -2, -1],
        [0, 0, 0],
        [1, 2, 1]
    ]
=   [1 2 1](高斯平滑) X [-1 0 1].T(垂直梯度)


'''
# kernel = np.asarray([
#     [-1, -2, -1],
#     [0, 0, 0],
#     [1, 2, 1]
# ])
kernel1 = np.asarray([[1,2,1]])
kernel2 = np.asarray([[-1],[0],[1]])

# 做一個卷積操作
# 第二個參數(shù)為:ddepth,一般為-1,表示不限制,默認(rèn)值即可。
# sobelx = cv.filter2D(img, 6, kernel.T)
# 先高斯平滑
a = cv.filter2D(img, 6, kernel1.T)
# 再水平梯度
sobelx = cv.filter2D(a, 6, kernel2.T)

# sobely = cv.filter2D(img, 6, kernel)
# 先高斯平滑
a = cv.filter2D(img, 6, kernel1)
# 再垂直梯度
sobely = cv.filter2D(a, 6, kernel2)

plt.figure(figsize=(10,5))
# 可視化
plt.subplot(131)
plt.imshow(img, 'gray')
plt.title('Original')

plt.subplot(132)
plt.imshow(sobelx, 'gray')
plt.title('sobelx')

plt.subplot(133)
plt.imshow(sobely, 'gray')
plt.title('sobely')
plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

2、Scharr

Scharr可以認(rèn)為是一種特殊的Sobel方式, 實際上就是一種特殊的kernel

# 加載圖像
img = cv.imread('./data/xiaoren.png', 0)


# 畫幾條線條
rows, cols = img.shape
cv.line(img, pt1=(0,rows//3), pt2=(cols,rows//3), color=0, thickness=5)
cv.line(img, pt1=(0,2*rows//3), pt2=(cols,2*rows//3), color=0, thickness=5)
cv.line(img, pt1=(cols//3,0), pt2=(cols//3,rows), color=0, thickness=5)
cv.line(img, pt1=(2*cols//3,0), pt2=(2*cols//3,rows), color=0, thickness=5)
print("")


# Scharr中,dx和dy必須有一個為0,一個為1
scharr_x = cv.Scharr(img, cv.CV_64F, dx = 1, dy = 0)
scharr_y = cv.Scharr(img, cv.CV_64F, dx = 0, dy = 1)


scharr_x_y = cv.Scharr(scharr_x, cv.CV_64F, dx = 0, dy = 1)
scharr_y_x = cv.Scharr(scharr_y, cv.CV_64F, dx = 1, dy = 0)


# c. 可視化
plt.figure(figsize=(20,10))

plt.subplot(231)
plt.imshow(img, 'gray')
plt.title('img')

plt.subplot(232)
plt.imshow(scharr_x, 'gray')
plt.title('scharr_x')

plt.subplot(233)
plt.imshow(scharr_y, 'gray')
plt.title('scharr_y')

plt.subplot(234)
plt.imshow(scharr_x_y, 'gray')
plt.title('scharr_x_y')

plt.subplot(235)
plt.imshow(scharr_y_x, 'gray')
plt.title('scharr_y_x')

plt.show()

?

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

3、Laplacian

使用拉普拉斯算子進(jìn)行邊緣提取

# 加載圖像
img = cv.imread('./data/xiaoren.png', 0)

# 畫幾條線條
rows, cols = img.shape
cv.line(img, pt1=(0,rows//3), pt2=(cols,rows//3), color=0, thickness=5)
cv.line(img, pt1=(0,2*rows//3), pt2=(cols,2*rows//3), color=0, thickness=5)
cv.line(img, pt1=(cols//3,0), pt2=(cols//3,rows), color=0, thickness=5)
cv.line(img, pt1=(2*cols//3,0), pt2=(2*cols//3,rows), color=0, thickness=5)
print("")

# ksize設(shè)置為3
ksize = 3

sobel_x = cv.Sobel(img, cv.CV_64F, dx=1, dy=0, ksize=ksize)
sobel_y = cv.Sobel(img, cv.CV_64F, dx=0, dy=1, ksize=ksize)

laplacian = cv.Laplacian(img, cv.CV_64F, ksize=ksize)
# 對laplacian取絕對值,并且準(zhǔn)換為uint8格式
laplacian_v2 = np.uint8(np.absolute(laplacian))

scharr_x = cv.Scharr(img, cv.CV_64F, dx=1, dy=0)
scharr_y = cv.Scharr(img, cv.CV_64F, dx=0, dy=1)


# c. 可視化
plt.figure(figsize=(20,10))

plt.subplot(241)
plt.imshow(img, 'gray')
plt.title('img')

plt.subplot(242)
plt.imshow(sobel_x, 'gray')
plt.title('sobel_x')

plt.subplot(243)
plt.imshow(sobel_y, 'gray')
plt.title('sobel_y')

plt.subplot(244)
plt.imshow(laplacian, 'gray')
plt.title('laplacian')

plt.subplot(245)
plt.imshow(laplacian_v2, 'gray')
plt.title('laplacian_v2')

plt.subplot(246)
plt.imshow(scharr_x, 'gray')
plt.title('scharr_x')

plt.subplot(247)
plt.imshow(scharr_y, 'gray')
plt.title('scharr_y')
plt.show()

?

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

'''

在Sobel檢測中,depth對于結(jié)果的影響,當(dāng)輸出的depth設(shè)置為比較低的數(shù)據(jù)格式,那么當(dāng)梯度值計算為負(fù)值的時候,就會將其重置為0,從而導(dǎo)致失真。
在Laplacian檢測中,該問題不大。

'''
# 構(gòu)建一個圖像
# 構(gòu)建黑底白框的圖像
img = np.zeros((300,300), np.uint8)
img[100:200,100:200] = 255
# 構(gòu)建白底黑框的圖像
# img = np.ones((300,300), np.uint8) * 255
# img[100:200,100:200] = 0

ksize = 5

# 做Sobel的操作
dst1 = cv.Sobel(img, cv.CV_8U, 1, 0, ksize=ksize)
dst2 = cv.Sobel(img, cv.CV_64F, 1, 0, ksize=ksize)
dst3 = np.uint8(np.absolute(dst2))



# 做Laplacian的操作
# dst1 = cv.Laplacian(img, cv.CV_8U, ksize=ksize)
# dst2 = cv.Laplacian(img, cv.CV_64F, ksize=ksize)
# dst3 = np.uint8(np.absolute(dst2))

# c. 可視化
plt.figure(figsize=(10,5))

plt.subplot(221)
plt.imshow(img, 'gray')
plt.title('img')

plt.subplot(222)
plt.imshow(dst1, 'gray')
plt.title('dst1')

plt.subplot(223)
plt.imshow(dst2, 'gray')
plt.title('dst2')

plt.subplot(224)
plt.imshow(dst3, 'gray')
plt.title('dst3')

plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

4、Canday算法

Canny算法是一種比Sobel和Laplacian效果更好的一種邊緣檢測算法;在Canny算法中,主要包括以下幾個階段:

  • Noise Reduction:降噪,使用5*5的kernel做Gaussian filter降噪;
  • Finding Intensity Gradient of the Image:求圖像像素的梯度值;
  • Non-maximum Suppression:刪除可能不構(gòu)成邊緣的像素,即在漸變方向上相鄰區(qū)域的像素梯度值是否是最大值,如果不是,則進(jìn)行刪除。
  • Hysteresis Thresholding:基于閾值來判斷是否屬于邊;大于maxval的一定屬于邊,小于minval的一定不屬于邊,在這個中間的可能屬于邊的邊緣。
# 加載圖像
img = cv.imread('./data/xiaoren.png', 0)

# 畫幾條線條
rows, cols = img.shape
cv.line(img, pt1=(0,rows//3), pt2=(cols,rows//3), color=0, thickness=5)
cv.line(img, pt1=(0,2*rows//3), pt2=(cols,2*rows//3), color=0, thickness=5)
cv.line(img, pt1=(cols//3,0), pt2=(cols//3,rows), color=0, thickness=5)
cv.line(img, pt1=(2*cols//3,0), pt2=(2*cols//3,rows), color=0, thickness=5)
cv.line(img, pt1=(0,0), pt2=(cols,rows), color=0, thickness=1)
print("")


# 做一個Canny邊緣檢測(OpenCV中是不包含高斯去燥的)
# a. 高斯去燥
blur = cv.GaussianBlur(img, (5,5),0)
# b. Canny邊緣檢測
edges = cv.Canny(blur,threshold1=10, threshold2=250)

# 可視化
plt.figure(figsize=(20,10))
plt.subplot(131)
plt.imshow(img,cmap = 'gray')
plt.title('Original Image')

plt.subplot(132)
plt.imshow(blur,cmap = 'gray')
plt.title('Gaussian Blur Image')

plt.subplot(133)
plt.imshow(edges,cmap = 'gray')
plt.title('Canny Edge Image')
plt.show()

?

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

5、輪廓信息

  • 輪廓信息可以簡單的理解為圖像曲線的連接點(diǎn)信息,在目標(biāo)檢測以及識別中有一定的作用。
  • 輪廓信息的查找最好是基于灰度圖像或者邊緣特征圖像,因為基于這樣的圖像比較容易找連接點(diǎn)信息;

NOTE:在OpenCV中,查找輪廓是在黑色背景中查找白色圖像的輪廓信息。

# 加載圖像
img = cv.imread('./data/xiaoren.png')

# 將圖像轉(zhuǎn)換為灰度圖像
img1 = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# 做一個圖像反轉(zhuǎn)(0 -> 255, 255 -> 0)
img1 = cv.bitwise_not(img1)

# 做一個二值化
ret, thresh = cv.threshold(img1, 127, 255, cv.THRESH_BINARY)

# 發(fā)現(xiàn)輪廓信息
# 第一個參數(shù)是原始圖像,第二個參數(shù)是輪廓的檢索模型,第三個參數(shù)是輪廓的近似方法
# 第一個返回值是輪廓,第二個參數(shù)值為層次信息
# CHAIN_APPROX_SIMPLE指的是對于一條直線上的點(diǎn)而言,僅僅保留端點(diǎn)信息,而CHAIN_APPROX_NONE保留所有點(diǎn)
# contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
contours, hierarchy = cv.findContours(thresh, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
print("總的輪廓數(shù)目:{}".format(len(contours)))
print('hierarchy.shape = ', hierarchy.shape)

# 在圖像中繪制圖像
# 當(dāng)contourIdx為-1的時候,表示繪制所有輪廓,當(dāng)為大于等于0的時候,表示僅僅繪制某一個輪廓
# 這里的返回值img3和img是同一個對象,在當(dāng)前版本中
# img3 = cv.drawContours(img, contours, contourIdx=-1, color=(0, 0, 255), thickness=2)
max_idx = np.argmax([len(t) for t in contours])
# print(max_idx)
img3 = cv.drawContours(img, contours, contourIdx=max_idx, color=(0, 0, 255), thickness=2)

# 可視化
plt.figure(figsize=(10,5))
plt.subplot(121)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.title('Original Image')

plt.subplot(122)
plt.imshow(thresh,cmap = 'gray')
plt.title('thresh')

plt.show()
總的輪廓數(shù)目:283
hierarchy.shape =  (1, 283, 4)

OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

6、輪廓信息說明

# 構(gòu)建黑底白框的圖像
img = np.zeros((300,300), np.uint8)
img[10:290,10:290] = 255
img[50:200, 50:200] = 0
img[55:100, 55:100] = 255
img[120:190, 120:150] = 255
img[130:160, 130:145] = 0
img[210:250, 210:250] = 0
img[250:270, 150:180] = 0
img[205:220, 205:220] = 0

# 可視化
plt.imshow(img, 'gray')
plt.title('img')

plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

?

ret, thresh = cv.threshold(img, 127, 255, cv.THRESH_BINARY)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
img3 = cv.drawContours(img, contours, contourIdx=-1, color=128, thickness=2)

print("總的輪廓數(shù)目:{}".format(len(contours)))
print('hierarchy.shape = ', hierarchy.shape)
hierarchy
# 是一個[1, n, 4]格式,n為輪廓的數(shù)目,這個中間保存的是輪廓包含信息

# 每個輪廓的層次信息是一個4維的向量值,
# 第一個值表示當(dāng)前輪廓的上一個同層級的輪廓下標(biāo),
# 第二值表示當(dāng)前輪廓的下一個同層級的輪廓下標(biāo),
# 第三個表示當(dāng)前輪廓的第一個子輪廓的下標(biāo),
# 第四個就表示當(dāng)前輪廓的父輪廓的下標(biāo)
總的輪廓數(shù)目:7
hierarchy.shape =  (1, 7, 4)





array([[[-1, -1,  1, -1],
        [ 2, -1, -1,  0],
        [ 3,  1, -1,  0],
        [-1,  2,  4,  0],
        [ 6, -1,  5,  3],
        [-1, -1, -1,  4],
        [-1,  4, -1,  3]]], dtype=int32)

7、輪廓屬性

獲取得到輪廓坐標(biāo)后,就可以基于輪廓來計算面積、周長等屬性。

# 加載圖像
img = cv.imread('./data/xiaoren.png')

# 將圖像轉(zhuǎn)換為灰度圖像
img1 = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# 做一個圖像反轉(zhuǎn)(0 -> 255, 255 -> 0)
img1 = cv.bitwise_not(img1)

# 做一個二值化
ret, thresh = cv.threshold(img1, 127, 255, cv.THRESH_BINARY)

# 發(fā)現(xiàn)輪廓信息
# 第一個參數(shù)是原始圖像,第二個參數(shù)是輪廓的檢索模型,第三個參數(shù)是輪廓的近似方法
# 第一個返回值是輪廓,第二個參數(shù)值為層次信息
# CHAIN_APPROX_SIMPLE指的是對于一條直線上的點(diǎn)而言,僅僅保留端點(diǎn)信息,而CHAIN_APPROX_NONE保留所有點(diǎn)
# contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
contours, hierarchy = cv.findContours(thresh, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)

idx = np.argmax([len(t) for t in contours])
cnt = contours[idx]
print(cnt.shape)
print(cnt[:2,:,:])
# 繪制輪廓
cv.drawContours(img, contours, contourIdx=idx, color=(0, 0, 255), thickness=2)

# 計算面積
area = cv.contourArea(cnt)
# 計算周長
perimeter = cv.arcLength(cnt, closed=True)
print("面積為:{}, 周長為:{}".format(area, perimeter))


'''
1、獲取最大的矩形邊緣框, 返回值為矩形框的左上角的坐標(biāo)以及寬度和高度
'''
x,y,w,h = cv.boundingRect(cnt)
# 繪圖
cv.rectangle(img, pt1=(x,y), pt2=(x+w,y+h), color=(255,0,0), thickness=2)


'''
2、繪制最小矩形(所有邊緣在矩形內(nèi))、得到矩形的點(diǎn)(左下角、左上角、右上角、右下角<順序不一定>)、繪圖
'''
# minAreaRect:求得一個包含點(diǎn)集cnt的最小面積的矩形,這個矩形可以有一點(diǎn)的旋轉(zhuǎn)偏轉(zhuǎn)的,輸出為矩形的四個坐標(biāo)點(diǎn)
# rect為三元組,
#       第一個元素為旋轉(zhuǎn)中心點(diǎn)的坐標(biāo)
#       第二個元素為矩形的高度和寬度
#       第三個元素為旋轉(zhuǎn)大小,正數(shù)表示順時針選擇,負(fù)數(shù)表示逆時針旋轉(zhuǎn)
rect = cv.minAreaRect(cnt)
box = cv.boxPoints(rect)
box = np.int64(box)
cv.drawContours(img, [box], 0, (0, 255, 0), 2)

'''
3、繪制最小的圓(所有邊緣在圓內(nèi))
'''
(x,y), radius = cv.minEnclosingCircle(cnt)
center = (int(x), int(y))
radius = int(radius)
cv.circle(img, center, radius, (0, 0, 255), 5)


'''
4、繪制最小的橢圓(所有邊緣不一定均在圓內(nèi))
'''
ellipse = cv.fitEllipse(cnt)
cv.ellipse(img, ellipse, (0, 255, 0), 5)


# 可視化
plt.subplot(121)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.title('Original Image')

plt.subplot(122)
plt.imshow(thresh,cmap = 'gray')
plt.title('thresh')

plt.show()
(1050, 1, 2)
[[[306 220]]

 [[306 229]]]
面積為:65960.5, 周長為:2487.3636897802353

OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

'''
5、旋轉(zhuǎn)后繪制最小橢圓
'''
# 加載圖像
img = cv.imread('./data/xiaoren.png')

# 旋轉(zhuǎn)

rect = [(302, 420), (317.06085205078125, 372.9076232910156), 18]
M = cv.getRotationMatrix2D(center=rect[0], angle=rect[-1], scale=1)
img = cv.warpAffine(img, M, (cols, rows), borderValue=[255,255,255])

# 將圖像轉(zhuǎn)換為灰度圖像
img1 = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# 做一個圖像反轉(zhuǎn)(0 -> 255, 255 -> 0)
img1 = cv.bitwise_not(img1)

# 做一個二值化
ret, thresh = cv.threshold(img1, 127, 255, cv.THRESH_BINARY)
# 發(fā)現(xiàn)輪廓信息
contours, hierarchy = cv.findContours(thresh, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)

idx = np.argmax([len(t) for t in contours])
cnt = contours[idx]

# 繪制輪廓
cv.drawContours(img, contours, contourIdx=idx, color=(0, 0, 255), thickness=2)

# 繪制最小矩形(所有邊緣在矩形內(nèi))、得到矩形的點(diǎn)(左下角、左上角、右上角、右下角<順序不一定>)、繪圖
# minAreaRect:求得一個包含點(diǎn)集cnt的最小面積的矩形,這個矩形可以有一點(diǎn)的旋轉(zhuǎn)偏轉(zhuǎn)的,輸出為矩形的四個坐標(biāo)點(diǎn)
# rect為三元組,第一個元素為旋轉(zhuǎn)中心點(diǎn)的坐標(biāo)
# rect為三元組,第二個元素為矩形的高度和寬度
# rect為三元組,第三個元素為旋轉(zhuǎn)大小,正數(shù)表示順時針選擇,負(fù)數(shù)表示逆時針旋轉(zhuǎn)
rect = cv.minAreaRect(cnt)
box = cv.boxPoints(rect)
box = np.int64(box)
cv.drawContours(img, [box], 0, (0, 255, 0), 2)
print(rect)


# 可視化
plt.figure(figsize=(10,5))
plt.subplot(121)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.title('Original Image')

plt.subplot(122)
plt.imshow(thresh,cmap = 'gray')
plt.title('thresh')

plt.show()
((300.05328369140625, 390.378662109375), (290.5243225097656, 397.2838134765625), 88.93909454345703)

OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度

8、直方圖

'''
OpenCV中的直方圖的主要功能是可以查看圖像的像素信息以及提取直方圖中各個區(qū)間的像素值的數(shù)目作為當(dāng)前圖像的特征屬性進(jìn)行機(jī)器學(xué)習(xí)模型
'''

# 加載圖像
img = cv.imread('./data/koala.png', 0)

# 兩種方式基本結(jié)果基本類似
# 1、基于OpenCV的API計算直方圖
hist1 = cv.calcHist([img], channels=[0], mask=None, histSize=[256], ranges=[0,256])


# 2、基于NumPy計算直方圖
hist2, bins = np.histogram(img.ravel(), 256, [0, 256])


# 和np.histogram一樣的計算方式,但是效率快
hist3 = np.bincount(img.ravel(), minlength=256)

# 可視化
plt.figure(figsize=(20,10))
plt.subplot(231)
plt.imshow(img, 'gray')
plt.title('Original Image')


plt.subplot(232)
# 可以直接使用matpliab中的hist API直接畫直方圖
plt.plot(hist1)
plt.title('hist1')

plt.subplot(233)
plt.plot(hist2)
plt.title('hist2')


plt.subplot(234)
plt.plot(hist3)
plt.title('hist3')

# 可以直接使用matpliab中的hist API直接畫直方圖
plt.subplot(235)
plt.hist(img.ravel(), 256, [0, 256])
plt.title('plt.hist')

plt.show()

?
OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度
?文章來源地址http://www.zghlxwxcb.cn/news/detail-471300.html

到了這里,關(guān)于OpenCV基礎(chǔ)操作(5)圖像平滑、形態(tài)學(xué)轉(zhuǎn)換、圖像梯度的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Python-OpenCV中的圖像處理-形態(tài)學(xué)轉(zhuǎn)換

    Python-OpenCV中的圖像處理-形態(tài)學(xué)轉(zhuǎn)換

    形態(tài)學(xué)操作:腐蝕,膨脹,開運(yùn)算,閉運(yùn)算,形態(tài)學(xué)梯度,禮帽,黑帽等 主要涉及函數(shù):cv2.erode(), cv2.dilate(), cv2.morphologyEx() 原理:形態(tài)學(xué)操作是根據(jù)圖像形狀進(jìn)行的簡單操作。一般情況下對二值化圖像進(jìn)行的操作。需要輸入兩個參數(shù),一個是原始圖像,第二個被稱為結(jié)構(gòu)化

    2024年02月13日
    瀏覽(24)
  • Opencv | 圖像卷積與形態(tài)學(xué)變換操作

    Opencv | 圖像卷積與形態(tài)學(xué)變換操作

    在每個圖像位置(x,y)上進(jìn)行基于鄰域的函數(shù)計算,其中函數(shù)參數(shù)被稱為卷積核 (kernel) kernel核的尺寸通常為奇數(shù),一般為: 3 ? 3 、 5 ? 5 、 7 ? 7 3*3、5*5、7*7 3 ? 3 、 5 ? 5 、 7 ? 7 不同功能需要定義不同的函數(shù),其中功能可以有: 圖像增強(qiáng): ??????????平滑 / 去

    2024年04月23日
    瀏覽(23)
  • OpenCV基本圖像處理操作(一)——圖像基本操作與形態(tài)學(xué)操作

    OpenCV基本圖像處理操作(一)——圖像基本操作與形態(tài)學(xué)操作

    圖像顯示 轉(zhuǎn)hsv圖像 顏色表示為三個組成部分:色調(diào)(Hue)、飽和度(Saturation)和亮度(Value)。常用于圖像處理中,因為它允許調(diào)整顏色的感知特性,如色彩和亮度,這些在RGB顏色模型中不那么直觀。 HSV模型特別適用于任務(wù)如圖像分割和對象追蹤,因為它可以更好地處理光

    2024年04月22日
    瀏覽(167)
  • OpenCV圖像處理學(xué)習(xí)十,圖像的形態(tài)學(xué)操作——膨脹腐蝕

    OpenCV圖像處理學(xué)習(xí)十,圖像的形態(tài)學(xué)操作——膨脹腐蝕

    一.形態(tài)學(xué)操作概念 圖像形態(tài)學(xué)操作是指基于形狀的一系列圖像處理操作的合集,主要是基于集合論基礎(chǔ)上的形態(tài)學(xué)數(shù)學(xué)對圖像進(jìn)行處理。 形態(tài)學(xué)有四個基本操作:腐蝕、膨脹、開操作、閉操作,膨脹與腐蝕是圖像處理中最常用的形態(tài)學(xué)操作手段。 二.形態(tài)學(xué)操作-膨脹 跟卷積

    2024年02月05日
    瀏覽(24)
  • 圖像形態(tài)學(xué)-閾值的概念、功能及操作(threshold()函數(shù)))【C++的OpenCV 第九課-OpenCV圖像常用操作(六)】

    圖像形態(tài)學(xué)-閾值的概念、功能及操作(threshold()函數(shù)))【C++的OpenCV 第九課-OpenCV圖像常用操作(六)】

    首先,顧名思義,“ 閾 ”就是范圍或者 限制 ,所以,“閾值”就是 某個限制的值 (該值具有一定的數(shù)學(xué)含義,即“ 臨界值 ”,例如車輛限高桿的高度就是一種閾值,不可超越;亦或者1.1米以下兒童不收費(fèi),超過1.1就要收費(fèi)。) 其次,圖形學(xué)中的閾值,往往指某個你想要

    2024年02月03日
    瀏覽(22)
  • 使用opencv c++完成圖像中水果分割(分水嶺、形態(tài)學(xué)操作、通道處理)單獨(dú)標(biāo)記每個水果

    使用opencv c++完成圖像中水果分割(分水嶺、形態(tài)學(xué)操作、通道處理)單獨(dú)標(biāo)記每個水果

    2023.4.16日更新 1. 利用一階矩增加了草莓等水果的質(zhì)心繪制。 2. 繪制出了生長方向。 原為本人機(jī)器人視覺作業(yè)。參考文章http://t.csdn.cn/eQ0qp(目測是上一屆的學(xué)長) 要求:在網(wǎng)絡(luò)上尋找水果重疊在一起的圖片、經(jīng)過一系列圖像處理,完成每個水果的分割,并單獨(dú)標(biāo)記出來。 導(dǎo)

    2024年02月04日
    瀏覽(56)
  • 圖像的形態(tài)學(xué)開操作(開運(yùn)算)和閉操作(閉運(yùn)算)的概念和作用,并用OpenCV的函數(shù)morphologyEx()實現(xiàn)對圖像的開閉操作

    圖像的形態(tài)學(xué)開操作(開運(yùn)算)和閉操作(閉運(yùn)算)的概念和作用,并用OpenCV的函數(shù)morphologyEx()實現(xiàn)對圖像的開閉操作

    大家看這篇博文前可以先看一看下面這篇博文,下面這篇博文是這篇博文的基礎(chǔ): 詳解圖像形態(tài)學(xué)操作之圖形的腐蝕和膨脹的概念和運(yùn)算過程,并利用OpenCV的函數(shù)erode()和函數(shù)dilate()對圖像進(jìn)行腐蝕和膨脹操作 圖像形態(tài)學(xué)腐蝕可以將細(xì)小的噪聲區(qū)域去除,但是會將圖像主要區(qū)域

    2024年02月06日
    瀏覽(17)
  • OpenCv之圖像形態(tài)學(xué)

    OpenCv之圖像形態(tài)學(xué)

    目錄 一、形態(tài)學(xué) ?二、圖像全局二值化 ?三、自適應(yīng)閾值二值化 四、腐蝕操作 五、獲取形態(tài)學(xué)卷積核 六、膨脹操作 七、開運(yùn)算 八、閉運(yùn)算 定義: 指一系列處理圖像形狀特征的圖像處理技術(shù) 形態(tài)學(xué)的基本思想是利用一種特殊的結(jié)構(gòu)元(本質(zhì)上就是卷積核)來測量或提取輸入圖

    2024年02月16日
    瀏覽(13)
  • OpenCv之圖像形態(tài)學(xué)(二)

    OpenCv之圖像形態(tài)學(xué)(二)

    目錄 一、形態(tài)學(xué)梯度 二、頂帽操作 三、黑帽操作 梯度=原圖 - 腐蝕 腐蝕之后原圖邊緣變小,原圖 - 腐蝕 就可以得到腐蝕掉的部分,即邊緣 案例代碼如下: 運(yùn)行結(jié)果如下: 頂帽 = 原圖 - 開運(yùn)算 開運(yùn)算的效果是去除圖形外的噪點(diǎn),原圖 - 開運(yùn)算就得到了去掉的噪點(diǎn) 案例代碼如

    2024年02月16日
    瀏覽(32)
  • 我在Vscode學(xué)OpenCV 圖像處理一(閾值處理、形態(tài)學(xué)操作【連通性,腐蝕和膨脹,開閉運(yùn)算,禮帽和黑帽,內(nèi)核】)

    我在Vscode學(xué)OpenCV 圖像處理一(閾值處理、形態(tài)學(xué)操作【連通性,腐蝕和膨脹,開閉運(yùn)算,禮帽和黑帽,內(nèi)核】)

    例如,設(shè)定閾值為127,然后: ? 將圖像內(nèi)所有像素值大于 127 的像素點(diǎn)的值設(shè)為 255。 ? 將圖像內(nèi)所有像素值小于或等于 127 的像素點(diǎn)的值設(shè)為 0。 cv2.threshold() 和 cv2.adaptiveThreshold() 是 OpenCV 中用于實現(xiàn)閾值處理的兩個函數(shù),它們之間有以下區(qū)別: 1.1.1. cv2.threshold(): 這個函數(shù)

    2024年02月05日
    瀏覽(32)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包