目錄
- 一:邊緣提取
- 1.對影像進行閾值分割并反色
- 2.邊緣提取
- 二:影像濾波
- 1.讀取原圖
- 2.均值濾波
- 3.中值濾波
- 4.高斯濾波
- 5.高斯邊緣檢測
- 三:邊緣檢測算子
- 1.顯示原圖
- 2.對影像進行反色
- 3.對影像用sobel方法進行邊緣檢測
- 4.對影像用robert方法進行邊緣檢測
- 四:投影
- 1.顯示原圖
- 2.垂直方向投影
- 3.水平方向投影
- 五:車牌字符分割
- 1.讀取原圖
- 2.灰度轉換
- 3.反色
- 4.閾值分割
- 5.投影
- 6.字符識別匹配分割
??機器視覺是人工智能正在快速發展的一個分支,簡單說來,機器視覺就是用機器代替人眼來做測量和判斷,它是一項綜合技術,包括影像處理、機械工程技術、控制、電光源照明、光學成像、傳感器、模擬與數字視頻技術、計算機軟硬體技術(影像增強和分析演算法、影像卡、 I/O卡等),
??下面介紹一些機器視覺的基礎方法,用到的技術是python+opencv,python是一種很方便的高級編程語言,代碼量少,而OpenCV是一個基于BSD許可發行的跨平臺計算機視覺庫,可以運行在Linux、Windows、Android和Mac OS作業系統上,它輕量級而且高效——由一系列 C 函式和少量 C++ 類構成,同時提供了Python、Ruby、MATLAB等語言的介面,實作了影像處理和計算機視覺方面的很多通用演算法,
一:邊緣提取
??在機器視覺中,一個非常基礎的操作就是影像處理,而在影像處理中有一個十分重要的知識就是邊緣提取,邊緣提取,指數字影像處理中,對于圖片輪廓的一個處理,對于邊界處,灰度值變化比較劇烈的地方,就定義為邊緣,也就是拐點,拐點是指函式發生凹凸性變化的點,和高數的導數有聯系,將某個指定的物體的邊緣進行提取出來,而用python+opencv可以很方便地進行邊緣提取操作,
??步驟如下:
1.對影像進行閾值分割并反色
??首先需要新建一個python檔案,匯入cv2的庫(OpenCV2的python庫),并顯示一張圖片,代碼為:
import cv2
# 讀取本相對路徑下的initial.bmp檔案
image = cv2.imread ("initial.bmp")
# 將image對應影像在影像視窗顯示出來
cv2.imshow('initial',image)
# waitKey使視窗保持靜態直到用戶按下一個鍵
cv2.waitKey(0)

??對影像進行閾值分割,閾值設定為80,得到二值化灰度圖,代碼為:
# 對影像進行閾值分割,閾值設定為80,得到二值化灰度圖
ret,image1 = cv2.threshold(image,80,255,cv2.THRESH_BINARY)
cv2.imshow('grayscale',image1)

??將影像進行反色,代碼如下:
image2 = image1.copy() # 復制圖片
for i in range(0,image1.shape[0]): #image.shape表示影像的尺寸和通道資訊(高,寬,通道)
for j in range(0,image1.shape[1]):
image2[i,j]= 255 - image1[i,j]
cv2.imshow('colorReverse',image2)

2.邊緣提取
??下面就是邊緣提取了,用findContours差影法或者Canny方法檢測邊緣,用原影像減去腐蝕后的收縮影像,提取邊緣,代碼如下:
# 邊緣提取
img = cv2.cvtColor(image2,cv2.COLOR_BGR2GRAY)
canny_img_one = cv2.Canny(img,300,150)
canny_img_two = canny_img_one.copy() # 復制圖片
for i in range(0,canny_img_one.shape[0]): #image.shape表示影像的尺寸和通道資訊(高,寬,通道)
for j in range(0,canny_img_one.shape[1]):
canny_img_two[i,j]= 255 - canny_img_one[i,j]
cv2.imshow('edge',canny_img_two)
??最終我們就可以得到一個邊緣提取后的圖形,如下:

二:影像濾波
??影像濾波,即在盡量保留影像細節特征的條件下對目標影像的噪聲進行抑制,是影像預處理中不可缺少的操作,其處理效果的好壞將直接影響到后續影像處理和分析的有效性和可靠性,
??噪聲就是由于成像系統、傳輸介質和記錄設備等的不完善,數字影像在其形成、傳輸記錄程序中或者在影像處理的某些環節當輸入的像物件并不如預想時受到的污染,
??而影像濾波有很多種濾波方式,本次實驗采用的濾波方式是均值濾波,中值濾波和高斯濾波,以及高斯邊緣檢測,
??均值濾波是典型的線性濾波演算法,它是指在影像上對目標像素給一個模板,該模板包括了其周圍的臨近像素(以目標像素為中心的周圍8個像素,構成一個濾波模板,即去掉目標像素本身),再用模板中的全體像素的平均值來代替原來像素值,
??中值濾波是基于排序統計理論的一種能有效抑制噪聲的非線性信號處理技術,中值濾波的基本原理是把數字影像或數字序列中一點的值用該點的一個鄰域中各點值的中值代替,讓周圍的像素值接近的真實值,從而消除孤立的噪聲點,
??高斯濾波是一種線性平滑濾波,適用于消除高斯噪聲,廣泛應用于影像處理的減噪程序,高斯濾波就是對整幅影像進行加權平均的程序,每一個像素點的值,都由其本身和鄰域內的其他像素值經過加權平均后得到,
??邊緣檢測的目的是標識數字影像中亮度變化明顯的點,高斯邊緣檢測是用高斯濾波的方式進行邊緣檢測,
??步驟如下:
1.讀取原圖
??首先展示原圖,代碼如下:
import cv2
import cv2 as cv
# 讀取本相對路徑下的initial.bmp檔案
image = cv2.imread ("initial.png")
# 加入文本資訊
cv2.putText(image,'initial',(50,50),cv2.FONT_HERSHEY_SIMPLEX,1.5,(255,0, 0),4)
# 將image對應影像在影像視窗顯示出來
cv2.imshow('initial',image)
cv2.waitKey(0)

2.均值濾波
??然后進行均值濾波,代碼如下:
# 均值濾波
image2 = cv2.blur(image,(10,5))
cv2.putText(image2,'averageFiltering',(50,50),cv2.FONT_HERSHEY_SIMPLEX,1.5,(255,0, 0),4)
cv2.imshow('averageFiltering',image2)

3.中值濾波
??然后進行中值濾波,代碼如下:
image3 = cv2.medianBlur(image, 5)
cv2.putText(image3,'medianFiltering',(50,50),cv2.FONT_HERSHEY_SIMPLEX,1.5,(255,0, 0),4)
cv2.imshow('medianFiltering',image3)

4.高斯濾波
??之后進行高斯濾波,代碼如下:
# 高斯濾波
image4 = cv2.GaussianBlur(image,(5,5),0)
cv2.putText(image4,'gaussianFilter',(50,50),cv2.FONT_HERSHEY_SIMPLEX,1.5,(255,0, 0),4)
cv2.imshow('gaussianFilter',image4)

5.高斯邊緣檢測
??最終進行高斯邊緣檢測,代碼如下:
# 高斯邊緣檢測
gau_matrix = np.asarray([[-2/28,-5/28,-2/28],[-5/28,28/28,-5/28],[-2/28,-5/28,-2/28]])
img = np.zeros(image.shape)
hight,width = image.shape
for i in range(1,hight-1):
for j in range(1,width-1):
img[i-1,j-1] = np.sum(image[i-1:i+2,j-1:j+2]*gau_matrix)
image5 = img.astype(np.uint8)
cv2.putText(image5,'gaussianEdgeDetection',(50,50),cv2.FONT_HERSHEY_SIMPLEX,1.5,(255,0, 0),4)
cv2.imshow('gaussianEdgeDetection',image5)

三:邊緣檢測算子
??邊緣檢測是影像處理和計算機視覺中的基本問題,邊緣檢測的目的是標識數字影像中亮度變化明顯的點,包括深度上的不連續、表面方向不連續、物質屬性變化和場景照明變化等,是計算機視覺的特征提取的一個領域,
??在實際的影像分割中,往往只用到一階和二階導數,雖然原理上,可以用更高階的導數,但是因為噪聲的影響,在純粹二階的導數操作中就會出現對噪聲的敏感現象,三階以上的導數資訊往往失去了應用價值,二階導數還可以說明灰度突變的型別,在某些情況下,如灰度變化均勻的影像,只利用一階導數可能找不到邊界,此時二階導數就能提供很有用的資訊,二階導數對噪聲也比較敏感,解決的方法是先對影像進行平滑濾波,消除部分噪聲,再進行邊緣檢測,不過,利用二階導數資訊的演算法是基于過零檢測的,因此得到的邊緣點數比較少,有利于后繼的處理和識別作業,
??計算機視覺正是模仿人類視覺的這個程序,因此在檢測物體邊緣時,先對其輪廓點進行粗略檢測,然后通過鏈接規則把原來檢測到的輪廓點連接起來,同時也檢測和連接遺漏的邊界點及去除虛假的邊界點,影像的邊緣是影像的重要特征,是計算機視覺、模式識別等的基礎,因此邊緣檢測是圖象處理中一個重要的環節,
??而在opencv中也有幾個邊緣檢測方法,一階的有Roberts Cross算子,Prewitt算子,Sobel算子,Canny算子,Krisch算子,羅盤算子;而二階的還有Marr-Hildreth,在梯度方向的二階導數過零點,
??步驟如下:
1.顯示原圖
??首先用下面的代碼表現出原影像:
# 讀取本相對路徑下的dip_switch_02.bmp檔案
src_s = cv2.imread ("dip_switch_02.bmp",0)
cv2.imshow('src_s',src_s)

2.對影像進行反色
??對影像進行反色,反色是與原色疊加可以變為白色的顏色,可以用白色(RGB:255,255,255)減去原來圖片的顏色,因此對于黑白圖片,我們先加載一個8位灰度影像,每一個像素對應的灰度值從0-255,則只需要讀取每個像素的灰度值A,再將255-A寫入,這樣操作一遍后,影像就會反色了,代碼如下:
src = https://www.cnblogs.com/ITXiaoAng/p/cv.imread("dip_switch_02.bmp")
height, width, channels = src.shape
for row in range(height):
for list in range(width):
for c in range(channels):
pv = src[row, list, c]
src[row, list, c] = 255 - pv
cv.imshow("AfterDeal", src)

3.對影像用sobel方法進行邊緣檢測
??Sobel算子是一種用于邊緣檢測的離散微分算子,它結合了高斯平滑和微分求導,該算子用于計算影像明暗程度近似值,根據影像邊緣旁邊明暗程度把該區域內超過某個數的特定點記為邊緣,Sobel 算子在Prewitt算子的基礎上增加了權重的概念,認為相鄰點的距離遠近對當前像素點的影響是不同的,距離越近的像素點對應當前像素的影響越大,從而實作影像銳化并突出邊緣輪廓,
??Sobel算子的邊緣定位更準確,常用于噪聲較多,灰度漸變的影像
Sobel算子包含兩組3x3的矩陣,分別為橫向及縱向模板,將之與影像作平面卷積,即可分別得出橫向及縱向的亮度差分近似值,
??代碼如下:
# 用sobel方法進行邊緣檢測
x = cv2.Sobel(src,cv2.CV_16S,1,0)
y = cv2.Sobel(src,cv2.CV_16S,0,1)
absX = cv2.convertScaleAbs(x) # 轉回uint8
# cv2.imshow("absX", absX)
# 截圖后反轉
def inverse_color(image):
height, width, channels = image.shape
for row in range(height):
for list in range(width):
for c in range(channels):
pv = image[row, list, c]
image[row, list, c] = 255 - pv
cv.imshow("result", image)
one = cv.imread("2.jpg")
inverse_color(one)

4.對影像用robert方法進行邊緣檢測
??Roberts 算子又稱為交叉微分算子,它是基于交叉差分的梯度演算法,通過區域差分計算檢測邊緣線條,常用來處理具有陡峭的低噪聲影像,當影像邊緣接近于正 45 度或負 45 度時,該演算法處理效果更理想,其缺點是對邊緣的定位不太準確,提取的邊緣線條較粗,
# 用robert方法進行邊緣檢測
dst = cv2.addWeighted(absX,0.5,absY,0.5,0)
# cv2.imshow("dst", dst)
# 截圖后反轉
def inverse_color(image):
height, width, channels = image.shape
for row in range(height):
for list in range(width):
for c in range(channels):
pv = image[row, list, c]
image[row, list, c] = 255 - pv
cv.imshow("result", image)
three = cv.imread ("3.jpg")
inverse_color(three)

四:投影
??投影就是就是把一個場景投影到攝像機的像平面上,型別有透視投影,仿射投影,弱透視投影與類透視投影等,
??在opencv中,投影主要分為水平投影和垂直投影,水平投影是二維影像在y軸上的投影;垂直投影是二維影像在x軸上的投影,
??在水平和垂直的方向上進行投影,先將投影的影像轉化為灰度圖,然后進行二值化閾值分割,之后在水平和垂直的方向上進行投影,所用庫為cv2以及matplotlib資料分析庫進行操作,
??步驟如下:
1.顯示原圖
import cv2
import numpy as np
from matplotlib import pyplot as plt
img=cv2.imread('123.jpg')

2.垂直方向投影
img=cv2.imread('123.jpg') #讀取圖片,裝換為可運算的陣列
GrayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #將BGR圖轉為灰度圖
ret,thresh1=cv2.threshold(GrayImage,130,255,cv2.THRESH_BINARY)#將圖片進行二值化(130,255)之間的點均變為255(背景)
(h,w)=thresh1.shape #回傳高和寬
a = [0 for z in range(0, w)]
#記錄每一列的波峰
for j in range(0,w): #遍歷一列
for i in range(0,h): #遍歷一行
if thresh1[i,j]==0: #如果改點為黑點
a[j]+=1 #該列的計數器加一計數
thresh1[i,j]=255 #記錄完后將其變為白色
for j in range(0,w): #遍歷每一列
for i in range((h-a[j]),h): #從該列應該變黑的最頂部的點開始向最底部涂黑
thresh1[i,j]=0 #涂黑
plt.imshow(thresh1,cmap=plt.gray())
plt.show()
cv2.imshow('one',thresh1)
cv2.waitKey(0)

3.水平方向投影
for j in range(0,h):
for i in range(0,w):
if thresh1[j,i]==0:
a[j]+=1
thresh1[j,i]=255
for j in range(0,h):
for i in range(0,a[j]):
thresh1[j,i]=0
plt.imshow(thresh1,cmap=plt.gray())
plt.show()

五:車牌字符分割
??車牌識別系統(Vehicle License Plate Recognition,VLPR) 是計算機視頻影像識別技術在車輛牌照識別中的一種應用,
??車牌識別技術要求能夠將運動中的汽車牌照從復雜背景中提取并識別出來,通過車牌提取、影像預處理、特征提取、車牌字符識別等技術,識別車輛牌號、顏色等資訊,目前最新的技術水平為字母和數字的識別率可達到99.7%,漢字的識別率可達到99%,
??要將車牌進行字符分割,先進行字符識別操作,這里進行的是直接用方框識別并括起來,需要的步驟是首先要讓彩色的車牌影像轉化為灰度圖,再反色,閾值分割,再利用水平和垂直方向的投影依次截取需要的小方框的長和寬,進行識別,用到的技術是python+opencv其中的cv2庫以及資料分析numpy庫,
??步驟如下:
1.讀取原圖
import cv2
import cv2 as cv
import numpy as np
image1 = cv.imread('123456.jpg',1)
cv.imshow('image1', image1)

2.灰度轉換
??然后把圖片轉化為灰度圖,這里設定讀取圖片用灰度圖片讀取即可,
image2 = cv.imread('123456.jpg',0)
cv.imshow('image2', image2)

3.反色
??接著將影像進行反色,記錄寬高和深度,并用255減去灰度圖顏色的寬高,
height, width, deep = image1.shape
dst = np.zeros((height,width,1), np.uint8)
for i in range(0, height):
for j in range(0, width):
grayPixel = image2[i, j]
dst[i, j] = 255-grayPixel
cv2.imshow('image3', dst)

4.閾值分割
??然后將反色后的影像進行閾值分割,閾值設為100,
ret, thresh = cv2.threshold(dst, 100, 255, cv2.THRESH_TOZERO)
cv2.imshow('image4', thresh)

5.投影
??之后在水平和垂直方向上進行投影,畫出投影圖,并記錄投影小黑點的單位起始長度陣列,設定兩個函式,回傳之后要用到的每個小分割矩形的特征點坐標值,
# 水平方向投影
def hProject(binary):
h, w = binary.shape
# 水平投影
hprojection = np.zeros(binary.shape, dtype=np.uint8)
# 創建h長度都為0的陣列
h_h = [0]*h
for j in range(h):
for i in range(w):
if binary[j,i] == 0:
h_h[j] += 1
# 畫出投影圖
for j in range(h):
for i in range(h_h[j]):
hprojection[j,i] = 255
return h_h
# 垂直反向投影
def vProject(binary):
h, w = binary.shape
# 垂直投影
vprojection = np.zeros(binary.shape, dtype=np.uint8)
# 創建 w 長度都為0的陣列
w_w = [0]*w
for i in range(w):
for j in range(h):
if binary[j, i ] == 0:
w_w[i] += 1
for i in range(w):
for j in range(w_w[i]):
vprojection[j,i] = 255
return w_w


6.字符識別匹配分割
??根據回傳的陣列,確定分割位置,進行字符識別匹配分割,
th = thresh
h,w = th.shape
h_h = hProject(th)
start = 0
h_start, h_end = [], []
position = []
# 根據水平投影獲取垂直分割
for i in range(len(h_h)):
if h_h[i] > 0 and start == 0:
h_start.append(i)
start = 1
if h_h[i] ==0 and start == 1:
h_end.append(i)
start = 0
for i in range(len(h_start)):
cropImg = th[h_start[i]:h_end[i], 0:w]
if i ==0:
pass
w_w = vProject(cropImg)
wstart , wend, w_start, w_end = 0, 0, 0, 0
for j in range(len(w_w)):
if w_w[j] > 0 and wstart == 0:
w_start = j
wstart = 1
wend = 0
if w_w[j] ==0 and wstart == 1:
w_end = j
wstart = 0
wend = 1
# 當確認了起點和終點之后保存坐標
if wend == 1:
position.append([w_start, h_start[i], w_end, h_end[i]])
wend = 0
# 確定分割位置
for p in position:
cv2.rectangle(thresh, (p[0], p[1]), (p[2], p[3]), (0, 0, 255), 2)
cv2.imshow('image7', thresh)
cv.waitKey(0)


轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/162478.html
標籤:Python
上一篇:python自學之路
下一篇:python漢諾塔問題
