詳解OpenMV圖像處理的基本方法

一、圖像處理基礎知識

1.攝像頭:光學信號轉換成電信號。計算機視覺中,最簡單的模型是小孔成像模型。
小孔成像是一種理想模型,實際鏡頭會存在場曲和畸變等,但可以通過在標定過程中引入畸變參數解決,仍可廣泛使用。

2.像素和分辨率

3.幀率:每秒鐘處理的圖片數量,>20人眼分辨不出卡頓。

4.顏色:不同波長的電磁波
通過RGB. CMYK HSB LAB色域來描述
RGB:三原色原理不是物理原因而是人的生理原因造成(錐形感光細胞)
LAB:L(亮度)、A(+:紅色,-:綠色)、B(+:黃色,-:藍色)用來接近人類視覺
L用來調整亮度對,a和b用來輸出色階來做精確的顏色平衡(查找色塊算法)
HSB/HSV:H(Hue色相)、S(Saturation飽和度)、B(Brightness明度)
HSL:L(亮度)
CMYK:C(藍色)、M(紅色)、Y(黃色)、K(黑色)
CMYK和RGB的區別:
(1)CMYK是減色模式,而RGB是加色模式
(2)CMYK需要外界光源才能看到,印刷品顏色;RGB是屏幕顯示發光的色彩模式,在黑暗房間也能看到

5.光源的選擇(光源對整個畫面的顏色變化有很大影響)

6.鏡頭的焦距和鏡頭畸變
焦距決定瞭拍攝的成像大小,視場角大小,景深大小和畫面的透視強弱。焦距長成像大(視角越小),焦距短成像小
鏡頭畸變:用代碼矯正鏡頭或直接使用無畸變鏡頭(加入瞭額外的矯正透鏡部分)
在感光芯片上的不同位置,與鏡頭距離不同近大遠小,在邊緣出現魚眼效果(桶形畸變)
標配鏡頭——桶形畸變
廣角鏡頭——同樣的區域取景范圍大瞭
無畸變鏡頭
長焦鏡頭——鎖定原來圖像中的某一具體物體

7.鏡頭的濾片
濾掉紅外光(根據需要濾掉不同波長的光),紅外光在正常分析顏色圖片的時候會使圖像泛白影響分析。(隻能通過650nm以內的)

二、OpenMV圖像處理的基本方法

1. 感光元件

sensor模塊,用於設置感光元件的參數。

sensor常用函數:

import sensor # 引入感光元件部分
# 設置攝像頭
sensor.reset() # 初始化感光元件
sensor.set_pixformat(sensor.RGB565)# 設置像素模式 sensor.GRAYSCALE:灰度,每個像素8bit, sensor.RGB565:彩色。每個像素16bit
sensor.set_framesize(sensor.QVGA)# 設置圖像大小
sensor.skip_frames(n)# n是跳過的幀數,等待感光元件穩定
# 拍攝
while(True):
   img = sensor.snapshot();# 拍攝一張照片,img為一個image對象

# 自動增益/白平衡/曝光
sensor.set_auto_gain() # True開啟;False關閉,使用顏色追蹤時,需關閉
sensor.set_auto_whitebal() # True開啟;False關閉,使用顏色追蹤時,需關閉
sensor.set_auto_exposure(enable[\,exposure_us])
# enable True打開/False關閉
# 如果關閉可以自己設置一個曝光值us為單位

# 設置窗口ROI
sensor.set_windowing(roi) #roi的格式是(x, y, w, h)的tupple.
sensor.set_framesize(sensor.VGA)
sensor.set_windowing((640,80))#選擇出自己想要的元素

# 設置翻轉
sensor.set_hmirror(True)# 水平方向翻轉
sensor.set_vflip((True)# 垂直方向翻轉

sensor圖像大小常用數據

sensor.QQCIF: 88x72
sensor.QCIF: 176x144
sensor.CIF: 352x288
sensor.QQSIF: 88x60
sensor.QSIF: 176x120
sensor.SIF: 352x240
sensor.QQQQVGA: 40x30
sensor.QQQVGA: 80x60
sensor.QQVGA: 160x120
sensor.QVGA: 320x240
sensor.VGA: 640x480
sensor.HQQQVGA: 80x40
sensor.HQQVGA: 160x80
sensor.HQVGA: 240x160
sensor.B64X32: 64x32 #(用於幀差異 image.find_displacement())
sensor.B64X64: 64x64 #用於幀差異 image.find_displacement())
sensor.B128X64: 128x64 #(用於幀差異 image.find_displacement())
sensor.B128X128: 128x128 #(用於幀差異 image.find_displacement())
sensor.LCD: 128x160 #(用於LCD擴展板)
sensor.QQVGA2: 128x160 #(用於LCD擴展板)
sensor.WVGA: 720x480 #(用於 MT9V034)
sensor.WVGA2:752x480 #(用於 MT9V034)
sensor.SVGA: 800x600 #(僅用於 OV5640 感光元件)
sensor.XGA: 1024x768 #(僅用於 OV5640 感光元件)
sensor.SXGA: 1280x1024 #(僅用於 OV5640 感光元件)
sensor.UXGA: 1600x1200 #(僅用於 OV5640 感光元件)
sensor.HD: 1280x720 #(僅用於 OV5640 感光元件)
sensor.FHD: 1920x1080 #(僅用於 OV5640 感光元件)
sensor.QHD: 2560x1440 #(僅用於 OV5640 感光元件)
sensor.QXGA: 2048x1536 #(僅用於 OV5640 感光元件)
sensor.WQXGA: 2560x1600 #(僅用於 OV5640 感光元件)
sensor.WQXGA2: 2592x1944 #(僅用於 OV5640 感光元件)

相關名詞解釋

1. 自動增益
為瞭能在不同的景物照度條件下都能輸出的標準視頻信號,必須使放大器的增益能夠在較大的范圍內進行調節。這種增益調節通常都是通過檢測視頻信號的平均電平而自動完成的,實現此功能的電路稱為自動增益控制電路,簡稱AGC電路 。具有AGC功能的攝像機,在低照度時的靈敏度會有所提高,但此時的噪點也會比較明顯。這是由於信號和噪聲被同時放大的緣故
2.白平衡
就是讓白色看起來是白色。在日光燈的房間裡拍攝的影像會顯得發綠,在室內鎢絲燈光下拍攝出來的景物就會偏黃,而在日光陰影處拍攝到的照片則莫名其妙地偏藍,其原因就在於白平衡的設置上。
3.色溫
光線的溫度——暖光或冷光(K:開爾文)冷光色溫高偏藍;暖光色溫低偏紅
光的色調是通過色溫來實現的,色溫會告訴相機這些光是暖色調還是冷色調

在這裡插入圖片描述

4.曝光
光圈越大,單位時間內通過的光越多;快門,允許光通過的時間。
光圈表示方法:F+數值,數值越小光圈越大,相鄰差2倍
快門表示方法:1/30s,直接使用時間單位,相鄰差2倍
光圈和快門的組合形成瞭曝光量(不同的組合雖然能夠達到相同的曝光量,但是所拍攝出來的圖片效果是不同的)
根據物體運動的規律選擇快門,在拍攝運動物體時發現,往往拍攝出來的主體是模糊的,這多半就是因為快門的速度不夠快。快門快瞭,進光量可能減少,色彩偏淡,這就需要增加曝光來加強圖片亮度。
曝光模式是計算機采用自然光源的模式——快門優先、光圈優先、手動曝光、AE鎖等模式。
(1)快門和光圈優先:機器自動測光系統計算出曝光量的值,然後自己選擇快門和光圈,系統根據你選的快門或光圈去確定另一個的參數(在手動定義快門(光圈)的情況下通過相機測光而獲取光圈(快門)值)
(2)手動曝光模式
每次拍攝時都需手動完成光圈和快門速度的調節
(3)AE模式(Auto Exposure自動曝光)
光圈優先AE式,快門速度優先AE式,程式AE式,閃光AE式和深度優先AE式

5.ROI
要處理的圖像中提取出的要處理的區域

在這裡插入圖片描述

roi的格式是(x, y, w, h)的tupple.
x:ROI區域中左上角的x坐標
y:ROI區域中左上角的y坐標
w:ROI的寬度
h:ROI的高度

2. 圖像的基本運算

相關函數:

# 1. 獲取/設置像素點
image.get_pixel(x,y)
# 獲取一個像素點的值
# 灰度:得到灰度值
# RGB:得到(r,g,b)的tuple

image.set_pixel(x,y,pixel)
# 設置一個像素點的值
# 灰度:設置灰度值
# RGB:設置(r,g,b)的tuple

# 2. 獲取圖像的寬度和高度
image.width()
image.height()
image.format()# 返回灰度還是彩色
image.size() # 返回圖像大小byte

# 3. 圖像的運算
# 圖像可以是從文件讀入的iamge對象,但是二者必須是相同的尺寸和類型(灰色/彩色)
image.invert() # 取反,二值圖像0變1,1變0
image.nand(image) #與非
image.nor(image) #或非
image.xor(image) #異或
image.xnor(image) # 異或非
image.difference(image) # 從一張圖片減去另一張圖片,絕對值相減,經常用於移動檢測

3. 使用圖像的統計信息

使用ROI選擇需要處理的圖像區域,然後根據相應函數返回對所要研究區域的對應值。

image.get_statistics(roi=Auto)# roi bins之類的參數一定要顯式聲明 

image.get_statistics(roi=(0,0,10,20))
#statistics.mean() 返回灰度的平均數(0-255) (int)。你也可以通過statistics[0]獲得。
#statistics.median() 返回灰度的中位數(0-255) (int)。你也可以通過statistics[1]獲得。
#statistics.mode() 返回灰度的眾數(0-255) (int)。你也可以通過statistics[2]獲得。
#statistics.stdev() 返回灰度的標準差(0-255) (int)。你也可以通過statistics[3]獲得。
#staistics.min() 返回灰度的最小值(0-255) (int)。你也可以通過statistics[4]獲得。
#statistics.max() 返回灰度的最大值(0-255) (int)。你也可以通過statistics[5]獲得。
#statistics.lq() 返回灰度的第一四分數(0-255) (int)。你也可以通過statistics[6]獲得。
#statistics.uq() 返回灰度的第三四分數(0-255) (int)。你也可以通過statistics[7]獲得。

# lab三個通道的相關信息
#l_mean,l_median,l_mode,l_stdev,l_min,l_max,l_lq,l_uq,
#a_mean,a_median,a_mode,a_stdev,a_min,a_max,a_lq,a_uq,
#b_mean,b_median,b_mode,b_stdev,b_min,b_max,b_lq,b_uq,

4. 畫圖

將所研究區域標註出來

# 顏色可以是灰度值0-255,也可以是彩色值(r,g,b)的tuple,但是color必須顯式註明,默認是白色
image.draw_line((10,10,20,30),color=(255,0,0))
image.draw_rectangle(rect_tuple,color=(255,0,0))

# 畫直線
image.draw_line(line_tuple,color=White) 
# line_tuple=(x1,y1,x2,y2) 從(x1,y1)到(x2,y2)的直線
# 顏色可以是灰度值(0-255),也可以是彩色值(r,g.b)的tuple

# 在圖像中畫一個矩形框
image.draw_rectangle(rect_tuple, color=White) 
# 在圖像中畫一個矩形框
# rect_tuple 的格式是 (x, y, w, h)

# 畫圓
image.draw_circle(x, y, radius, color=White) 
# 在圖像中畫一個圓
# 圓心+半徑

# 畫十字
image.draw_cross(x, y, size=5, color=White) 
# 在圖像中畫一個十字
# size是兩側的尺寸

# 寫字
image.draw_string(x, y, text, color=White)
# 在圖像中寫字 8x10的像素
# xy是坐標,使用\n\r或\r\n會使光標移動到下一行
# text是要寫的字符串

5. 尋找色塊

find_blobs函數的參數介紹:

image.find_blobs(thresholds, roi=Auto, x_stride=2, y_stride=1, invert=False, 
area_threshold=10, pixels_threshold=10, merge=False, margin=0, threshold_cb=None, 
merge_cb=None)
# thresholds 顏色的閾值
# roi感興趣區
# x_stride 查找的色塊的x方向上最小寬度的像素,比如想要找x方向上寬度大於10的像素,=10即可(默認是2)
# y_stride 查找的色塊的y方向上最小寬度的像素(默認是1)
# invert 反轉閾值,將閾值以外的顏色作為閾值進行查找
# area_threshold 面積閾值,如果色塊被包圍起來的面積小於這個值會被舍棄
# pixels_threshold 像素個數閾值,如果色塊的像素數量小於這個值,會被過濾掉
# merge True,合並所有重疊的blob為1個,這個是合並所有的blob,無論什麼顏色,如果想要分別混合的話,分別調用不同顏色閾值的find_blobs
# margin 邊界,如果設置為1,那麼兩個blobs如果間距1一個像素點,也會被合並
# 合並所有
all_blobs = img.find_blobs([red,blue,yellow],merge=True)
# 單個合並
red_blobs = img.find_blobs([red],merge=True)
blue_blobs = img.find_blobs([blue],merge=True)
yellow_blobs = img.find_blobs([yellow],merge=True)

find_blobs的返回值介紹:
find_blobs對象返回的是多個blob的列表,一個blobs列表裡面包含很多的blob對象,blobs對象就是色塊,每個blobs對象包含一個色塊的信息。
可以使用for循環遍歷色塊:

blobs = img.find_blobs([red])
for blob in blobs:
	print(blob.cx())

色塊blob對象

常見blob的方法:

blob.rect() #返回這個色塊的外框——矩形元組(x, y, w, h),可以直接在image.draw_rectangle中使用。
blob.x() #返回色塊的外框的x坐標(int),也可以通過blob[0]來獲取。
blob.y() #返回色塊的外框的y坐標(int),也可以通過blob[1]來獲取。
blob.w() #返回色塊的外框的寬度w(int),也可以通過blob[2]來獲取。
blob.h() #返回色塊的外框的高度h(int),也可以通過blob[3]來獲取。
blob.pixels() #返回色塊的像素數量(int),也可以通過blob[4]來獲取。
blob.cx() #返回色塊的外框的中心x坐標(int),也可以通過blob[5]來獲取。
blob.cy() #返回色塊的外框的中心y坐標(int),也可以通過blob[6]來獲取。
blob.rotation() #返回色塊的旋轉角度(單位為弧度)(float)。如果色塊類似一個鉛筆,那麼這個值為0~180°。如果色塊是一個圓,那麼這個值是無用的。如果色塊完全沒有對稱性,那麼你會得到0~360°,也可以通過blob[7]來獲取。
blob.code() #返回一個16bit數字,每一個bit會對應每一個閾值。
# 一個色塊red-0001,blue-0010,如果是red和blue的merge得到的blob-0011
blob.count() #如果merge=True,那麼就會有多個blob被合並到一個blob,這個函數返回的就是這個的數量。如果merge=False,那麼返回值總是1。也可以通過blob[9]來獲取
blob.area() #返回色塊的外框的面積。應該等於(w * h)
blob.density() #返回色塊的密度。這等於色塊的像素數除以外框的區域。
#如果密度較低,那麼說明目標鎖定的不是很好。
#比如,識別一個紅色的圓,返回的blob.pixels()是目標圓的像素點數,blob.area()是圓的外接正方形的面積。

顏色閾值

# 分別是LAB的最小值和最大值
red = (minL, maxL, minA, maxA, minB, maxB)
# 如果是灰度圖的話,隻有min和max
grey = (min,max)


顏色閾值的獲得:

在這裡插入圖片描述
在這裡插入圖片描述

幀緩沖區是IDE實時獲取的圖像;圖像文件是SD卡中存儲的。

在這裡插入圖片描述

拖動滑塊可以直接看到閾值的效果,想要的結果就是將目標顏色都變成白色,其他顏色全為黑色。

6. AprilTag實現標記跟蹤

AprilTag是一個視覺基準系統,可用於各種任務,包括AR,機器人和相機校準。這個tag可以直接用打印機打印出來,而AprilTag檢測程序可以計算相對於相機的精確3D位置,方向和id。

在這裡插入圖片描述

可以得到空間位置量和旋轉角度進行3D定位

在這裡插入圖片描述

???

6. 模版匹配NCC

歸一化互相關匹配
???
註意:

  • 模版圖片的大小如果超過openmv內置的flash,需要SD卡
  • 創建或導入的模版必須是pgm格式的,而且大小不能超過openmv的像素大小
  • 可以直接使用openmv截取模版圖像,但是一定要註意轉換成pgm格式

7. 多模版匹配

提前存取多個模版即可

8. 特征點檢測

特征點檢測要比模版匹配更加靈活,模版匹配隻要大小和角度有一點不同,就可能匹配失敗。但是特征點檢測,在剛開始運行程序的時候,例程提取最開始的圖像作為目標物體特征,kpts1保存目標物體的特征。默認會匹配目標特征的多種比例大小和角度,而不僅僅是保存目標特征時的大小角度。也可以提前保存目標特征,之前不這麼做是因為每次運行程序光線不同特征不同,匹配度會降低,但是增加瞭對曝光度、白平衡、自動增益值的調節之後,相對來說會減弱光線的幹擾,也可以提前保存特征(車裡光線的幹擾情況也得考慮。。)

例程有參考價值(待。。)
例程隻支持灰度圖,註意一下使用的特征提取算法是FAST/AGAST算法

9. 測距

  • 第一種方法是Apriltag進行3D定位測距
  • 第二種方法按照參照物距離的比例進行測距

得第一次通過一個實際距離已知的測距來得到參數k的值,然後再進行後面的計算。

OpenMV使用的是單目攝像頭。
關於單目攝像頭和雙目攝像頭:
無人駕駛的智能攝像頭要求:看得遠,質量高。
看得遠長焦距,但視角會變窄,主要是反應時間充足;質量高采用黑白相機成像。
測距原理上,兩種攝像頭便完全不同。單目攝像頭需要對目標進行識別,也就是說在測距前先識別障礙物是車、人還是別的什麼。在此基礎上再進行測距。而雙目攝像頭則更加像人類的雙眼,主要通過兩幅圖像的視差計算來確定距離。​雙目攝像頭當然也不是十全十美,因為需要靠計算來進行測距。其最大的難點就在於計算量巨大。這帶來的直接問題就是小型化難度很大。

例程有參考價值(待。。)

10. 掃碼識別

暫時沒用

11. 顏色形狀同時識別

例程是首先在圖像中進行圓形識別,然後統計圓形中的圖像顏色

12. 顏色模版匹配同時識別

首先進行顏色識別,然後再去識別到的顏色區域裡去找到所要的模版
和11一樣,例程具有參考價值而且如何進行算法的組合使用需要考慮(待。。)

13.分辨不同人臉

例程可用(待。。)
使用LBP特征分辨不同的人臉。這裡是首先選擇瞭20張同一個人不同表情的人臉保存(通過不同的燈光顯示告知被采集數據者數據采集完成與否)
然後識別的是當前攝像頭視野內的人臉並輸出與當前對象最匹配的人。

14. 高級特征

HAAR
HOG
LBP
看一下其他實際應用效果比較好的特征可以應用的選擇一下

到此這篇關於OpenMV圖像處理的基本方法的文章就介紹到這瞭,更多相關OpenMV圖像處理內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: