在科學(xué)技術(shù)快速發(fā)展的今日晶姊,圖像處理技術(shù)在科研度苔、軍事、工業(yè)生產(chǎn)揖赴、衛(wèi)生雪位、教育等與人類生活息息相關(guān)的領(lǐng)域得到廣泛的應(yīng)用竭钝。人臉識別、自動駕駛、各種無人服務(wù)香罐,這些新興技術(shù)都體現(xiàn)了機(jī)器視覺系統(tǒng)正確認(rèn)知客觀世界的重要性卧波。邊緣檢測是圖像處理中最基本卻又最困難的一個問題,邊緣檢測更是實現(xiàn)圖像分割庇茫、目標(biāo)識別等圖像技術(shù)的重要前提港粱。
圖像邊緣指的是圖形周圍像素灰度急劇變化的那些像素的集合,是圖像最基本的特征旦签。所謂圖像邊緣檢測就是利用灰度值不連續(xù)的性質(zhì)查坪,以灰度突變?yōu)榛A(chǔ)分割出目標(biāo)區(qū)域,檢測出符合邊緣特性的邊緣像素顷霹,完成圖像處理咪惠。
1. 經(jīng)典邊緣檢測方法
在經(jīng)典邊緣檢測算法中,我們常利用各種微分算子對邊緣特征進(jìn)行提取淋淀,以達(dá)到圖像處理的目的遥昧。這些算子包含一階微分算子,如 Sobel 算子朵纷、Prewitt 算子炭臭、Roberts 算子、Canny 算子等等袍辞;還有二階微分算子鞋仍,如 Laplacian 算子、LoG 算子等等搅吁。以上這些微分算子最終都能完成邊緣檢測的任務(wù)威创,各有優(yōu)勢。
1.1 算子在邊緣檢測中的實際運(yùn)用
目前谎懦,所有具有計算機(jī)視覺設(shè)計需求的公司都會使用這些算子來進(jìn)行邊緣檢測處理肚豺,其中我們耳熟能詳?shù)木桶v訊、谷歌界拦、英特爾吸申、英偉達(dá)、特斯拉等等享甸。在騰訊的各游戲部門中截碴,通常需要獲取場景對應(yīng)的深度、法線和顏色信息蛉威,然后利用邊緣檢測算子來判斷游戲場景的實際情況日丹,之后進(jìn)行場景渲染;特斯拉發(fā)展的自動駕駛技術(shù)是通過利用車上配置的傳感器將實際場景轉(zhuǎn)換成圖像蚯嫌,再利用各個算子進(jìn)行邊緣檢測算法處理聚凹,實現(xiàn)感知周圍環(huán)境的效果割坠,達(dá)到規(guī)避障礙物或變換車道的目的,具體實現(xiàn)方法如下:
1.1.1 利用車載傳感器獲得車道圖像(下圖)
1.1.2 使用 Canny 算子得到邊緣檢測處理結(jié)果:
import cv2import numpy as npdef canyEdgeDetector(image): edged = cv2.Canny(image, 50, 150) return edged
1.1.3 在處理后的圖像上妒牙,根據(jù)實際需求,定義需要關(guān)注的區(qū)域对妄。
def getROI(image): height = image.shape[0] width = image.shape[1] # Defining Triangular ROI: The values will change as per your camera mounts # triangle = np.array([[(100, height), (width, height), (width-500, int(height/1.9))]]) triangle = np.array([[(120, height), (width, height), (400, 228)]]) # creating black image same as that of input image black_image = np.zeros_like(image) # Put the Triangular shape on top of our Black image to create a mask mask = cv2.fillPoly(black_image, triangle, 255) # applying mask on original image masked_image = cv2.bitwise_and(image, mask) return masked_image
1.1.4 為了分析路況及車道情況湘今,我們要獲得圖像中的所有直線,通過以下代碼完成:
def getLines(image): # lines=cv2.HoughLinesP(image,bin_size,precision,threshold,dummy 2d array--no use,minLineLength,maxLineGap) # lets take bin size to be 2 pixels # lets take precision to be 1 degree= pi/180 radians # threshold is the votes that a bin should have to be accepted to draw a line # minLineLength --the minimum length in pixels a line should have to be accepted. # maxLineGap --the max gap between 2 broken line which we allow for 2 lines to be connected together. lines = cv2.HoughLinesP(image, 0.3, np.pi/180, 100, np.array([]),minLineLength=70, maxLineGap=20) return lines
再通過以下程序獲取圖像和線條列表剪菱,并在圖像上繪制出線條:
#display lines over a imagedef displayLines(image, lines): if lines is not None: for line in lines: # print(line) --output like [[704 418 927 641]] this is 2d array representing [[x1,y1,x2,y2]] for each line x1, y1, x2, y2 = line.reshape(4) # converting to 1d array [] # draw line over black image --(255,0,0) tells we want to draw blue line (b,g,r) values 10 is line thickness cv2.line(image, (x1, y1), (x2, y2), (255, 0, 0), 10) return image
定義另一個效用函數(shù)從斜率和截距中獲取線坐標(biāo)
def getLineCoordinatesFromParameters(image, line_parameters): slope = line_parameters[0] intercept = line_parameters[1] y1 = image.shape[0] # since line will always start from bottom of image y2 = int(y1 * (3.4 / 5)) # some random point at 3/5 x1 = int((y1 - intercept) / slope) x2 = int((y2 - intercept) / slope) return np.array([x1, y1, x2, y2])
1.1.5 將上述得到的直線進(jìn)行分組摩瞎,分組后找到各組的平均斜率和截距,并通過算法為每個組創(chuàng)建一條線孝常。
#Avergaes all the left and right lines found for a lane and retuns single left and right line for the the lanedef getSmoothLines(image, lines): left_fit = [] # will hold m,c parameters for left side lines right_fit = [] # will hold m,c parameters for right side lines for line in lines: x1, y1, x2, y2 = line.reshape(4) # polyfit gives slope(m) and intercept(c) values from input points # last parameter 1 is for linear..so it will give linear parameters m,c parameters = np.polyfit((x1, x2), (y1, y2), 1) slope = parameters[0] intercept = parameters[1] if slope < 0: left_fit.append((slope, intercept)) else: right_fit.append((slope, intercept))# take averages of all intercepts and slopes separately and get 1 single value for slope,intercept# axis=0 means vertically...see its always (row,column)...so row is always 0 position.# so axis 0 means over row(vertically)left_fit_average = np.average(left_fit, axis=0)right_fit_average = np.average(right_fit, axis=0)# now we have got m,c parameters for left and right line, we need to know x1,y1 x2,y2 parametersleft_line = getLineCoordinatesFromParameters(image, left_fit_average)right_line = getLineCoordinatesFromParameters(image, right_fit_average)return np.array([left_line, right_line])
1.1.6 經(jīng)過上述所有步驟的處理之后旗们,我們就通過 Canny 算子進(jìn)行的邊緣檢測處理獲得了單獨(dú)的函數(shù),我們只需要在主代碼中調(diào)用它們构灸,就能夠通過車載圖傳獲得車道信息進(jìn)行下一步的處理上渴。
image = cv2.imread("3d21d93f722e1e3a5dd8fd8bbcd1c5d0.png") #Load Imageedged_image = canyEdgeDetector(image) # Step 1roi_image = getROI(edged_image) # Step 2lines = getLines(roi_image) # Step 3image_with_lines = displayLines(image, lines)cv2.imshow("Output", roi_image)# cv2.waitKey(0)# smooth_lines = getSmoothLines(image, lines) # Step 5# image_with_smooth_lines = displayLines(image, smooth_lines) # Step 4## cv2.imshow("Output", image_with_smooth_lines)cv2.waitKey(0)
1.2 各個算子邊緣檢測能力的區(qū)別
通過上述邊緣檢測算法完成車道分析之后,自動駕駛系統(tǒng)會很具實際情況判斷是否需要變道或者規(guī)避障礙物喜颁,這就是現(xiàn)在邊緣檢測在實際應(yīng)用中所發(fā)揮的作用稠氮。各個算子在實際操作中,對于圖像邊緣檢測的完成情況也略有不同半开,具體有什么樣的區(qū)別隔披,我們可以看看以下實例:
1.2.1 Roberts 算子
Roberts 算子又稱為交叉微分算法,它是基于交叉差分的梯度算法寂拆,通過局部差分計算檢測邊緣線條奢米。常用來處理具有陡峭的低噪聲圖像,當(dāng)圖像邊緣接近于正 45 度或負(fù) 45 度時纠永,該算法處理效果更理想鬓长。其缺點(diǎn)是對邊緣的定位不太準(zhǔn)確,提取的邊緣線條較粗渺蒿。
1.2.2 Prewitt 算子
Prewitt 算子是一種圖像邊緣檢測的微分算子痢士,其原理是利用特定區(qū)域內(nèi)像素灰度值產(chǎn)生的差分實現(xiàn)邊緣檢測。由于 Prewitt 算子采用 33 模板對區(qū)域內(nèi)的像素值進(jìn)行計算茂装,而 Robert 算子的模板為 22怠蹂,故 Prewitt 算子的邊緣檢測結(jié)果在水平方向和垂直方向均比 Robert 算子更加明顯。Prewitt 算子適合用來識別噪聲較多少态、灰度漸變的圖像城侧。
1.2.3 Sobel 算子
Sobel 算子是一種用于邊緣檢測的離散微分算子,它結(jié)合了高斯平滑和微分求導(dǎo)彼妻。該算子用于計算圖像明暗程度近似值嫌佑,根據(jù)圖像邊緣旁邊明暗程度把該區(qū)域內(nèi)超過某個數(shù)的特定點(diǎn)記為邊緣豆茫。Sobel 算子在 Prewitt 算子的基礎(chǔ)上增加了權(quán)重的概念,認(rèn)為相鄰點(diǎn)的距離遠(yuǎn)近對當(dāng)前像素點(diǎn)的影響是不同的屋摇,距離越近的像素點(diǎn)對應(yīng)當(dāng)前像素的影響越大揩魂,從而實現(xiàn)圖像銳化并突出邊緣輪廓。Sobel 算子的邊緣定位更準(zhǔn)確炮温,常用于噪聲較多火脉、灰度漸變的圖像。
1.2.4 Laplacian 算子
Laplacian 算子是維歐幾里德空間中的一個二階微分算子柒啤,通過灰度差分計算鄰域內(nèi)的像素倦挂。Laplacian 算子其實主要是利用 Sobel 算子的運(yùn)算,通過加上 Sobel 算子運(yùn)算出的圖像 X 方向和 Y 方向上的導(dǎo)數(shù)担巩,得到輸入圖像的圖像銳化結(jié)果方援。同時,在進(jìn)行 Laplacian 算子處理之后涛癌,還需要調(diào)用 convertScaleAbs()函數(shù)計算絕對值犯戏,并將圖像轉(zhuǎn)換為 8 位圖進(jìn)行顯示。Laplacian 算子容易丟失一部分邊緣的方向信息祖很,造成一些不連續(xù)的檢測邊緣笛丙,同時抗噪聲能力比較差,由于其算法可能會出現(xiàn)雙像素邊界假颇,常用來判斷邊緣像素位于圖像的明區(qū)或暗區(qū)胚鸯,很少用于邊緣檢測。
2. 經(jīng)典邊緣檢測技術(shù)新發(fā)展
隨著數(shù)學(xué)理論和人工智能技術(shù)的發(fā)展笨鸡,經(jīng)典邊緣檢測還結(jié)合了很多相關(guān)領(lǐng)域內(nèi)的理論知識形成了一些新的檢測方法姜钳,以下是這些新方法中較為常見的幾個例子:
2.1 基于數(shù)學(xué)形態(tài)學(xué)的邊緣檢測:
數(shù)學(xué)形態(tài)學(xué)是基于積分幾何和幾何概論建立的關(guān)于圖像形狀和尺寸的研究方法,實質(zhì)上是一種非線性濾波方法形耗。數(shù)學(xué)形態(tài)學(xué)的方法應(yīng)用于視覺圖像的處理就是用具有一定形狀哥桥、大小的結(jié)構(gòu)元素去探測、度量和提取圖像中對應(yīng)形狀激涤,以達(dá)到對圖像進(jìn)行處理拟糕、分析識別的目的。在圖像處理的過程中倦踢,主要使用的是二值形態(tài)學(xué)和灰度形態(tài)學(xué)送滞。我們可以來看看這個方法對于圖像輪廓的提取能力如何:
2.2 基于小波和小波包變換的邊緣檢測算法:
小波變換具有非常豐富的數(shù)學(xué)理論做支撐,有著非常大的發(fā)展前景辱挥;小波變換很好的利用了時域頻域的局部化特征犁嗅,通過對信號進(jìn)行細(xì)化分析,能達(dá)到高頻處時間細(xì)分晤碘、低頻處頻率細(xì)分褂微,所以小波變換適合復(fù)雜圖像的邊緣檢測功蜓,它的邊緣處理能力如下:
2.3 基于模糊理論的邊緣檢測算法:
實際應(yīng)用中的圖像邊緣是不確定的,具有模糊性宠蚂,用經(jīng)典數(shù)學(xué)描述不準(zhǔn)確式撼,所以利用模糊理論進(jìn)行邊緣檢測時,首先將圖像看作是一個模糊集肥矢,將圖像中每一個具有特定灰度級的元素進(jìn)行標(biāo)記端衰,從而將待處理的圖像映射為具有模糊特征的矩陣,在此基礎(chǔ)上進(jìn)行模糊增強(qiáng)處理甘改,由于圖像邊緣梯度的模糊性,這個方法能夠得到比較好的邊緣檢測效果灭抑。下圖就是模糊方法處理后得到的圖像邊緣:
2.4 基于神經(jīng)網(wǎng)絡(luò)的邊緣檢測算法:
神經(jīng)網(wǎng)絡(luò)是一種基于現(xiàn)有數(shù)據(jù)創(chuàng)建預(yù)測的計算系統(tǒng)十艾,隨著神經(jīng)網(wǎng)絡(luò)技術(shù)的發(fā)展,人們又將其加入到圖像邊緣檢測中腾节,希望能夠獲得更好的檢測結(jié)果忘嫉。神經(jīng)網(wǎng)絡(luò)的邊緣檢測一般利用 BP 網(wǎng)絡(luò),采用滾動訓(xùn)練和權(quán)值隨機(jī)擾動方法案腺,提高了神經(jīng)網(wǎng)絡(luò)的學(xué)習(xí)效果庆冕,獲得的邊緣圖像封閉性好,更加精確劈榨。我們來看看它實際的處理能力:
除了上述的微分算子邊緣檢測及發(fā)展出的幾個新方法外访递,還有很多領(lǐng)域的研究人員結(jié)合自己的理論知識提出了不少新算法,比如基于分形幾何的邊緣檢測算法同辣、基于遺傳算法的邊緣檢測算法拷姿、漫射邊緣檢測方法、多尺度邊緣檢測技術(shù)旱函、亞像素邊緣定位技術(shù)响巢、FCM 聚類的邊緣檢測算法等等,都能夠取得較好的圖像邊緣檢測效果棒妨。
3. 經(jīng)典邊緣檢測的實際應(yīng)用及局限
隨著圖像邊緣檢測技術(shù)的完善和發(fā)展踪古,它的成果早已經(jīng)融入到我們生活的方方面面。我們平時使用的手機(jī)面容解鎖券腔,數(shù)碼相機(jī)的眼部追蹤和自動對焦功能伏穆,翻譯軟件的拍照識別翻譯,停車場車牌號檢測颅眶,文字識別等等蜈出,都運(yùn)用到了圖像的邊緣檢測技術(shù)。在很多專業(yè)領(lǐng)域內(nèi)涛酗,都依賴于圖像邊緣檢測技術(shù)帶來的成果铡原,比如在醫(yī)療領(lǐng)域偷厦,B 超、CT 的分析也是依靠圖像邊緣檢測完成的燕刻,像無人駕駛等等領(lǐng)域也都有它的身影只泼。可以說卵洗,我們已經(jīng)享受到很多邊緣檢測技術(shù)帶來的便利请唱。
目前所有在使用的傳統(tǒng)圖像邊緣檢測算法在大部分時間內(nèi)可以滿足我們工作生產(chǎn)的需求,但它們都不具備絕對優(yōu)勢过蹂,一個好的邊緣檢測方法一方面要求能夠檢測出有效邊緣十绑,另一方面要求其抗噪能力強(qiáng),目前的經(jīng)典邊緣檢測算法或多或少都會遇到噪聲的影響酷勺,如椒鹽噪聲本橙、高斯噪聲等等;同時在實際生活中脆诉,當(dāng)我們碰到尺寸甚亭、分辨率更大的圖像時,經(jīng)典邊緣檢測算法必須要對像素逐個進(jìn)行計算击胜,這就帶來了很大的工作量和巨大的時間成本亏狰。
4. 量子算法的登場
在更高效率的需求下,很多人將目光轉(zhuǎn)向了量子算法領(lǐng)域偶摔。隨著量子力學(xué)和信息科學(xué)的發(fā)展暇唾,基于量子信號處理的圖像處理研究是目前圖像處理的前沿。如果我們采用量子算法進(jìn)行圖像邊緣檢測啰挪,依托于量子態(tài)疊加和量子糾纏帶來的巨大并行計算的能力信不,量子圖像處理與經(jīng)典圖像處理相比具有天然的優(yōu)勢,能為圖像邊緣檢測帶來指數(shù)級的加速亡呵。
4.1 量子算法的實現(xiàn)原理:
在使用量子算法進(jìn)行圖像邊緣檢測時抽活,首先我們需要將圖像各個像素歸一化,讓每個像素的概率加權(quán)等于 1锰什,然后讓這些像素矢量轉(zhuǎn)化成為比特字串下硕,經(jīng)過一個置換酉陣,我們就可以檢測像素矢量的梯度了汁胆,之后的工作就是找到像素從明變化到暗的位置梭姓,這就是我們需要的圖像邊緣所在的點(diǎn)。(下圖所示為量子電位圖)
4.2 量子算法進(jìn)行邊緣檢測的步驟:
具體操作步驟如下圖所示:算法的輸入量嫩码,是一張?zhí)幚砗玫?256×256 的灰度圖誉尖,像素點(diǎn)的值在 0 到 1 之間。之后圖片會被分割成 1024 張 16×16 的子圖铸题,對每一張子圖铡恕,我們創(chuàng)建格式相同的兩個量子電路琢感,分別用于處理子圖的橫向邊緣掃描和縱向邊緣掃描,掃描的結(jié)果探熔,是一張 16×16 的橫向掃描圖和一張 16×16 的縱向掃描圖的和驹针,即為這張子圖對應(yīng)的圖像邊緣。當(dāng)我們對這 1024 張子圖全部進(jìn)行上述的步驟后诀艰,將得到的 1024 張掃描結(jié)果進(jìn)行重構(gòu)柬甥,得到一張 256×256 的完整灰度圖,這張圖即為輸出結(jié)果其垄。處理時的具體步驟如下圖所示:
4.3 量子算法完成邊緣檢測的步驟代碼
完成量子算法檢測邊緣步驟所需要的算法代碼如下:
from edge_detection import QED,crop_image,plot_imageimport cv2from PIL import Imageimport numpy as npimport matplotlib.pyplot as plt
第一步:圖像預(yù)處理
將需要進(jìn)?圖形邊緣檢測的圖?苛蒲,通過 Image.open ?式打開,并轉(zhuǎn)換成灰度圖(Lmodeimage)存儲
讀出存儲的灰度圖绿满,并剪切?算法可以處理的??:256×256
將像素值不? 0.5 的設(shè)置為 0撤防,?于 0.5 的設(shè)置為 1
將 256×256 ??的圖?,分割成 16×16 的圖?堆
img = Image.open('./test.jpeg').convert('L')img.save('grey.png')image256 = plt.imread("grey.png")res = cv2.resize(image256, dsize=(256, 256),interpolation=cv2.INTER_CUBIC)res[res\<.5] = 0res[res\>.5] = 1crop = crop_image(res)cropped = crop.image_stackplot_image(res,"original image")
第二步:量子 QED 實例化
對每?個圖?堆中的 16×16 的分割?圖棒口,我們使? QED 算法,得到分割后的圖像
對圖?堆中的每?個?圖完成循環(huán)辜膝,我們得到?個邊緣檢測之后的圖?堆 image_out
?成?張和原圖像?樣??的 error_correction 圖?无牵,?于像素值校正
最后邊緣檢測的結(jié)果,即為 image_edge+error_correction
image_out = np.zeros(cropped.shape) for i in range(len(cropped)): if (np.sum(cropped[i])>0) * (np.sum(cropped[i])<256): method = QED(image_in = cropped[i]) out = method.get_scan_images() image_out[i] = out[2] image_edge = crop.reshape(image_out) error_correction = np.ones((256,256)) for i in range(1,16): error_correction[i*16-1] = 0 for j in range(1,16): error_correction[:,j*16-1] = 0 plot_image(image_edge*error_correction,"edge detected image")
可以看到厂抖,經(jīng)過處理后的圖像邊緣處理是非常清晰的茎毁,說明量子算法在圖像處理上會比傳統(tǒng)的邊緣檢測效果更好。同時我們還將量子算法與傳統(tǒng)邊緣檢測數(shù)據(jù)進(jìn)行了對比(下圖)忱辅,我們發(fā)現(xiàn)在所花費(fèi)的時間上七蜘,量子算法確實快了很多,同時隨著邊緣檢測圖片像素數(shù)量的增加墙懂,量子算法所具有的優(yōu)勢會越來越明顯橡卤。
5. 量子算法未來的發(fā)展
現(xiàn)階段,量子算法在圖像邊緣檢測上的優(yōu)勢已經(jīng)初見成效损搬,啟科量子作為量子領(lǐng)域的先行者碧库,會在量子算法領(lǐng)域深耕,大大加快量子算法在應(yīng)用方面的實驗工作巧勤,發(fā)揮量子算法在計算機(jī)視覺方向等領(lǐng)域上的全部潛能嵌灰,為行業(yè)發(fā)展做出應(yīng)有的貢獻(xiàn)。同時颅悉,啟科量子也會借著量子領(lǐng)域的東風(fēng)沽瞭,積極探索,勇敢嘗試剩瓶,努力實現(xiàn)企業(yè)價值驹溃,不遺余力地為量子算法以及量子計算領(lǐng)域的發(fā)展添磚加瓦城丧。
注:部分圖片及內(nèi)容來源于網(wǎng)絡(luò),如有侵權(quán)吠架,請聯(lián)系刪除芙贫。
參考鏈接:
https://blog.csdn.net/zaishuiyifangxym/article/details/89840396
https://www.dounaite.com/article/6261531a1ca8a644a40db371.html
Xi-Wei Yao. Quantum Image Processing and Its Application to Edge Detection: Theory and Experiment. Physical Review X 7,031041(2017)
王敏杰.圖像邊緣檢測技術(shù)綜述[J].中南大學(xué)學(xué)報(自然科學(xué)版).2011.9
王軍敏.基于多尺度小波變換的圖像邊緣檢測[J].平頂山學(xué)院學(xué)報.2013