機器視覺學習總結

1機器視覺的成像

機器視覺應用到工業自動化檢測領域,可以代替人工從而提高工作效率並降低成本。目前,基於視覺的工業檢測主要用在定性分析和定量檢測中,但在大部分實際應用過程中,最終落腳仍爲定量檢測,定性分析任務只作爲定量檢測任務的前提。因此,需要關注圖像的生成過程。圖像的生成包括兩個關鍵問題,一是物理世界中點與圖像中點的對應,二是圖像中點的亮度。

1.1相機模型

相機成像的小孔模型:
在這裏插入圖片描述
在世界座標系中的點和相機座標系中的點的對應關係可以用數學公式描述爲:
在這裏插入圖片描述
在這裏插入圖片描述

1.2圖像亮度

圖像亮度與物體的輻照強度和傳感器的光譜靈敏的決定,輻照強度指照射到像平面的“輻射能”在單位面積上的功率,而輻照強度又由場景輻射強度(光照強度)決定,它們成正比例關係,比例係數有成像系統的參數決定。
在這裏插入圖片描述
要使光線能到達像平面,鏡頭的光圈必須有一定的直徑,因此前述小孔模型只是一個理想模型。當相機光圈直徑不爲0時,物體中一個點將在像平面上成一個圓斑,導致圖像不清晰,因此需要在成像系統中加入透鏡來對光線進行匯聚。

1.3 透鏡

一個理想的透鏡具有如下兩個特徵:1:它的投影方式和小孔模型相同;2,:將一定數量的光線匯聚到一起。完美的透鏡系統中,射向透鏡中心的光線不發生偏轉,射向透鏡邊緣的光線將會偏轉並和射向透鏡中心的光線匯聚。但這一理想透鏡只會對特定距離的物體纔會準確聚焦,物體前後移動生成的光斑小於傳感器分辨率的範圍被稱爲成像域深度,也稱景深。透鏡直徑越大,成像域深度就越小,因此在調節視覺系統時越有可能造成的聚焦誤差。
任何簡單透鏡都會產生缺陷和像差,但根據理想簡單透鏡的成像原理和光路的可逆性,將一塊透鏡放到另一塊透鏡的焦距附近,可以提高成像質量,因此將多個透鏡沿光軸仔細排列成爲組合透鏡。
不管是組合透鏡還是簡單透鏡,其投影方式不可能和理想小孔模型一樣,對所有光線的準確聚焦也是無法實現的,總會產生像差。但是對於一個設計精良的透鏡系統,這些缺陷會儘可能的做到最小。

2.灰度圖像基本操作

任何顏色都有紅、綠、藍三原色組成,在opencv中使用cvtColor函數使用COLOR_RGB2GRAY參數把彩色圖轉爲灰度圖。灰度是指黑白圖像中的顏色深度,每個像素一般使用一個字節存儲,範圍爲0-255,共256個灰度等級。白色爲255,黑色爲0。
灰度圖的預處理包含逐像素處理和卷積處理等。逐像素處理針對每一個像素獨立處理,處理前後同樣位置的像素具有相同的映射關係,亮度變化,直方圖均衡化屬於逐像素處理操作。卷積處理後圖中一個像素值與原圖中多個像素值相關,濾波,特徵點提取等都屬於卷積操作。

2.1逐像素處理操作

對每個像素點獨立進行函數運算,返回的仍然是圖像,通常用於把機器視覺關注的特徵凸顯出來。
2.1.1圖像二值化
圖像二值化就是將圖像上的像素點的灰度值設置爲0或255,也就是將整個圖像呈現出明顯的黑白效果的過程。圖像的二值化使圖像中數據量大爲減少,從而能凸顯出目標的輪廓。
圖像二值化公式:
在這裏插入圖片描述
圖像的二值化需要確定閾值,閾值可以人爲根據先驗指定,也可以根據圖像全局特徵進行計算。
圖像自動二值化閾值計算算法有大津法(OTSU)和三角形法(TRIANGLE)。
在這裏插入圖片描述
三角法使用直方圖數據,基於純幾何方法來尋找最佳閾值,它的成立條件是假設直方圖最大波峯在靠近最亮的一側,然後通過三角形求得最大直線距離,根據最大直線距離對應的直方圖灰度等級即爲分割閾值。當最大波峯在暗的一側時,可通過對直方圖進行翻轉進行處理。
在這裏插入圖片描述
OpenCV提供了圖像二值化的函數cvThreshold和inRange,cvThreshold函數可以手動指定閾值,也可以指定參數THRESH_OTSU使用OTSU算法,指定參數THRESH_TRIANGLE使用三角法。inRange可以指定閾值分割的上下界,並可同時對多個通道操作。
如下圖是電子jj鏡頭獲取到的一幅圖像,任務是要識別視野中的紅色氣球中心。
在這裏插入圖片描述
首先將彩色圖轉換爲灰度圖,發現無法使用二值化方法直接分割。
在這裏插入圖片描述
因此使用彩色圖像單通道數據進行分割,經過測試,單使用任一通道都無法有效分割,因此將彩色圖像轉到LAB顏色空間,對三個通道分別二值化,然後求交得到,中心的十字可以使用膨脹和腐蝕形態學操作消除。
在這裏插入圖片描述
算法主要代碼如下:

Mat ThresholdLAB(Mat src, Vec3d low, Vec3d high)
{
    Mat bgr, lab, dst;
    src.convertTo(bgr, CV_32FC3, 1.0 / 255, 0);
    cvtColor(bgr, lab, CV_BGR2Lab);
    Mat mask;
    inRange(lab, Scalar(low[0], low[1], low[2]), Scalar(high[0], high[1], high[2]), mask);
    Mat gray_all;
    GaussianBlur(mask, gray_all, Size(3, 3), 0);
    threshold(gray_all, gray_all, 100, 255, THRESH_BINARY);
    Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
    //去除瞄準十字
erode(gray_all, gray_all, element);
    dilate(gray_all, gray_all, element);
    return gray_all;
}

2.1.2亮度變換
亮度變換有兩個功能,一是提高對比度,二是消除或者減輕因環境光照強度、物體表面反射、相機增益等引起的亮度變化。爲了補償這些因素,對圖像進行轉換,以使所得像素值的均值爲0,方差爲1。
在實際的圖像處理中,如果認爲圖像的絕對亮度不包含視覺任務需求的關鍵信息,則可以使用這種方式對圖像進行處理。
在這裏插入圖片描述
原始圖片是兩張亮度不同的人臉圖片,它們的像素均值和標準差都不同,可以進過亮度變化,使第二張圖的像素亮度和方差變爲與第一張圖相等。處理結果如下:
在這裏插入圖片描述
使用公式如下:
在這裏插入圖片描述
均值和標準差可以使用OPENCV中的函數meanStdDev實現。
算法主要代碼:

for (int i = 0; i < img.rows; i++)
{
	for (int j = 0; j < img.cols; j++)
	{
		int tmp = img.at<uchar>(i, j);
		double yy = (tmp - mean2) / stddev2*stddev1 + mean1;
		yy = yy > 255 ? 255 : yy < 0 ? 0 : yy;
		img.at<uchar>(i, j) = yy;
	}
}

2.1.3直方圖均衡化
圖像的直方圖可以反映圖像的一些全局特徵,比如偏暗,偏亮,亮度集中等。
在這裏插入圖片描述
直方圖均衡化處理的“中心思想”是把原始圖像的灰度直方圖從比較集中的某個灰度區間變成在全部灰度範圍內的均勻分佈。直方圖均衡化就是對圖像進行非線性拉伸,重新分配圖像像素值,使一定灰度範圍內的像素數量大致相同。直方圖均衡化就是把給定圖像的直方圖分佈改變成“均勻”分佈直方圖分佈。直方圖均衡化的映射函數爲:
在這裏插入圖片描述
Opencv中equalizeHist函數可以完成上述操作,輸入的圖像必須是8位的單通道圖像。
在這裏插入圖片描述

2.2卷積操作

數字圖像處理中的預處理步驟很多屬於卷積操作,各種濾波,特徵提取等都是利用了卷積操作完成。進行卷積操作時,定義一個卷積核,使用這個卷積核和圖像進行卷積,對於圖像上的一個點,讓卷積核的原點和該點重合,然後卷積核上的點和圖像上對應的點相乘,然後各點的積相加,就得到了該點的卷積值。對圖像上的每個點都進行相同處理。
2.2.1基於卷積運算的圖像濾波
圖像濾波,即在儘量保留圖像細節特徵的條件下對目標圖像的噪聲進行抑制,是圖像預處理中不可缺少的操作,其處理效果的好壞將直接影響到後續圖像處理和分析的有效性和可靠性。
Opencv中提供的濾波器有方框濾波boxFilter,高斯濾波GaussianBlur,中值濾波medianBlur以及雙邊濾波bilateralFilter,前兩者爲線性濾波,後兩者爲非線性濾波。雙邊濾波嚴格上不屬於卷積操作,因爲卷積核在圖像上滑動時會根據特徵調整卷積核(權重)。
方框濾波器的卷積核爲
在這裏插入圖片描述
中值濾波器的卷積核爲
在這裏插入圖片描述
高斯濾波的卷積核通過二維高斯分佈進行計算
在這裏插入圖片描述
高斯濾波算子通常也作爲其它圖像處理算子的一部分,比如LoG(Laplace of Gaussian)算子和DoG(Difference of Gaussian)算子。
雙邊濾波的基本思路是同時考慮將要被濾波的像素點的空域信息和值域信息。首先,對於圖像濾波來說,通常認爲圖像在空間中變化緩慢,因此相鄰的像素點會更相近。但是這個假設在圖像的邊緣處變得不成立。如果在邊緣處也用這種思路來進行濾波的話,邊緣會模糊掉。因此考慮再利用像素點的值的大小進行補充,因爲邊緣兩側的點的像素值差別很大,因此會使得其加權的時候權重具有很大的差別,從而使得只考慮自己所屬的一邊的鄰域。可以理解成先根據像素值對要用來進行濾波的鄰域做一個分割或分類,再給該點所屬的類別相對較高的權重,然後進行鄰域加權求和,得到最終結果。

2.2.2基於卷積運算的特徵提取
特徵提取是圖象處理中的一個初級運算,它檢查每個像素來確定該像素是否代表一個特徵,因此一般作爲更大的算法的一部分。圖像中的特徵指邊,角,交叉,區域等。有些特徵可以使用卷積的方式提取。
Robert 算子:Robert算子是一種種利用局部差分算子尋找邊緣的算子,對具有陡峭的低噪聲的圖像效過較好。Robert算子的卷積核爲:
在這裏插入圖片描述
Sobel算子:Sobel算子主要用作邊緣檢測,它屬於一階離散性差分算子,用來運算圖像亮度函數的灰度之近似值。在圖像的任何一點使用此算子,將會產生對應的灰度矢量或是其法矢量。Sobel算子的卷積核有兩個,對應兩個方向。
在這裏插入圖片描述
Opencv中Sobel的使用:

Mat task4 = imread("pic/task4-2.jpg");
Mat gray,sobel1,sobel2,sobel;
cvtColor(task4, gray, COLOR_RGB2GRAY);
Sobel(gray, sobel1, CV_8U, 1, 0, 3);
Sobel(gray, sobel2, CV_8U, 0, 1, 3);
addWeighted(sobel1, 0.5, sobel2, 0.5, 0, sobel);
imshow("task4", task4);
imshow("sobel", sobel);
waitKey();

Soble算子處理效果:
在這裏插入圖片描述
Laplacian算子:Laplacian算子屬於二階微分算子,由於拉普拉斯算子是一種微分算子,因此強調的是圖像中灰度的突變,並不強調灰度緩慢變化的區域。這將產生把淺灰色邊線和突變點疊加到暗色背景中的圖像。將原圖像和拉普拉斯圖像疊加在一起,可以復原背景特性並保持拉普拉斯銳化處理的效果。Laplacian算子是一種特別容易受到噪聲干擾的邊緣發現算子,所以經常對要處理的圖像首先進行一個高斯模糊,然後再進行拉普拉斯算子的邊緣提取。先進行高斯濾波,再使用拉普拉斯算子的過程統稱爲LoG(Laplace of Gaussian function)算子。
Laplacian算子的卷積核有兩種,分爲4鄰域和8鄰域:
在這裏插入圖片描述
Opencv中Laplacian的使用:

Mat task5 = imread("pic/task4-3.jpg");
cvtColor(task5, task5, COLOR_BGR2GRAY);
Mat gray_all, laplacian;
GaussianBlur(task5, gray_all, Size(3, 3), 0);
Laplacian(task5, laplacian, CV_8U, 3);
imshow("task5", task5);
imshow("laplacian", laplacian);
waitKey();

Laplacian算子處理效果:
在這裏插入圖片描述
Canny 邊緣檢測算法:Canny邊緣檢測算法使用了上述介紹的部分算子,比如高斯濾波算子,Sobel算子,其關注具體的邊緣檢測應用。該算法由Canny在1986年提出,雖然年代久遠,但它是邊緣檢測的一種標準算法,在研究中有廣泛使用。Canny邊緣檢測算子的目標是找到一個最優的邊緣檢測算法,即算法要儘可能的檢測邊緣,檢測到的邊緣要和實際邊緣儘量接近,對圖像的中邊緣只標識一次。Canny算法檢測邊緣點的具體步驟爲:灰度化,高斯濾波,用一階偏導有限差分算子計算梯度幅值和方向,對梯度幅值進行非極大值抑制,用雙閾值算法檢測和連接邊緣,邊界跟蹤。在opencv中,差分算子使用sobel算子,可以手動指定尺寸,雙閾值由手動指定,邊界跟蹤使用滯後濾波。

3.灰度圖像特徵提取

除了上面提到的使用逐像素操作和卷積操作提取圖像邊緣特徵的操作外,數字圖像處理中有更加高級的特徵提取方法。

3.1邊界特徵法

邊界特徵法該方法通過對邊界特徵的描述來獲取圖像的形狀參數,其中Hough變換檢測平行直線方法和邊界方向直方圖方法是經典方法。
Hough 變換是利用圖像全局特性而將邊緣像素連接起來組成區域封閉邊界的一種方法,其基本思想是點—線的對偶性;
邊界方向直方圖法首先微分圖像求得圖像邊緣,然後,做出關於邊緣大小和方向的直方圖,通常的方法是構造圖像灰度梯度方向矩陣。
Hough直線檢測代碼:

Mat srcImage = imread("pic/task9-2.jpg"),gray,show;
show = srcImage.clone();
cvtColor(srcImage, gray, COLOR_RGB2GRAY);
Canny(gray, gray, 100, 200, 3, false);
vector<Vec2f> lines;

HoughLines(gray, lines, 1.0, CV_PI / 60, 100, 0, 0);
RNG rng(time(0));

for (size_t i = 0; i < lines.size(); i++)
{
	int rand1 = rng.uniform(0, 150);
	int rand2 = rng.uniform(0, 150);
	int rand3 = rng.uniform(0, 150);
	float rho = lines[i][0], theta = lines[i][1];
	Point pt1, pt2;
	double a = cos(theta), b = sin(theta);
	double x0 = a*rho, y0 = b*rho;
	pt1.x = cvRound(x0 + 2000 * (-b));  //把浮點數轉化成整數
	pt1.y = cvRound(y0 + 2000 * (a));
	pt2.x = cvRound(x0 - 2000 * (-b));
	pt2.y = cvRound(y0 - 2000 * (a));
	line(show, pt1, pt2, Scalar(rand1, rand2, rand3), 4, LINE_AA);
}
imshow("output", show);
waitKey();

Hough直線檢測實驗效果:
在這裏插入圖片描述

3.2幾何參數法

形狀的表達和匹配採用更爲簡單的區域特徵描述方法,例如採用形狀定量測度比如面積、周長,一階矩,二階矩,不變矩等形狀參數。形狀最小包圍矩形的面積,周長,長邊方向等,對於橢圓等形狀,可以利用圓度、偏心率、主軸方向等幾何參數,進行基於形狀特徵的圖像檢索。形狀參數的提取,必須以圖像處理及圖像分割爲前提,幾何參數的準確性必然受到圖像分割效果的影響,對分割效果很差的圖像,幾何參數甚至無法提取。
3.2.1輪廓面積和周長
在Opencv中使用contourArea計算輪廓的面積,單位是像素個數;使用arcLength來計算輪廓和曲線的長度。
輪廓的面積和周長可以用來篩選目標,輪廓面積和周長的比例和目標的細長程度有關,也可作爲篩選條件。
3.2.2圖像的矩
矩函數在模式識別、目標分類、目標識別與方位估計、圖像的編碼與重構等都有廣泛應用。從一幅圖像計算出來的矩,不僅可以描述圖像形狀的全局特徵,而且可以提供大量關於該圖像不同的幾何特徵信息,如大小,位置、方向和形狀等。圖像矩這種描述能力廣泛應用於各種圖像處理、計算機視覺和機器人技術領域的目標識別與方位估計中。
一階矩與形狀有關係,可以用來計算重心,二階矩表示目標相對原點擴展程度,不具有選擇不變性,三階矩不單獨使用,和二階矩組合可以得到Hu不變矩,具有旋轉,平移,縮放不變性,用來做匹配。Opencv中函數moments用來計算矩,使用Humoments計算Hu不變矩。Opencv模板匹配函數matchShape使用Hu不變矩進行模板匹配並給出匹配參數。
在這裏插入圖片描述
在這裏插入圖片描述
其中前6個具有平移,縮放,旋轉和翻轉不變性,第7個矩表示圖像或特徵的翻轉。
Hu對於圖像中的大物體和紋理特徵簡單的圖識別效果較好,可以用來對車牌字符進行識別等應用。下圖是對字母K進行縮放和旋轉處理後計算出的Hu矩,7個值距離很近。

在這裏插入圖片描述
opencv代碼:

string path = "pic/task6-" + to_string(i+4) + ".png";
Mat task6 = imread(path, IMREAD_GRAYSCALE);
threshold(task6, task6,100,255, THRESH_BINARY);
Moments mu = moments(task6, true);
double humoments[7];
HuMoments(mu, humoments);
for (int j = 0; j < 7; j++)
{
	humoments[j] = -1 * copysign(1.0, humoments[j]) * log10(abs(humoments[j]));
	cout << "Hu[" << j << "]:" << humoments[j] << endl;
}
cout << endl;

OpenCV中除了對整幅圖像計算Hu矩外,還可以對輪廓計算Hu矩,因此可以對輪廓進行旋轉平移縮放不變的輪廓匹配,OpenCV中實現函數是matchShape。其衡量兩個輪廓匹配好壞的指標函數可以通過參數指定,共有三種,分別是:
在這裏插入圖片描述
3.2.3輪廓包圍形狀
OpenCV提供三種常見輪廓包圍形狀,分別是包圍矩形,最小包圍矩形和最下包圍圓。函數分別是BoundingRect,MinAreaRect和MinEnclosingCircle。
在這裏插入圖片描述
使用輪廓包圍形狀的特徵可提取目標位姿信息,尺寸信息,缺陷信息等。
3.2.4圓度,主軸方向,偏心率
對於圓形目標,在經過相機後畸變近似爲橢圓。在識別到橢圓目標後,得到橢圓的長軸方向,偏心率等,除了可以完成目標的定位,還可以根據偏心參數還原圓形目標。
下圖所示爲工業攝影測量中使用的Schneider編碼靶標,靶標的定位使用中心的圓,靶標的信息由外環的顏色順序進行編碼。
在這裏插入圖片描述
Schneider編碼靶標識別算法流程圖
在這裏插入圖片描述
算法效果:
在這裏插入圖片描述

3.3 特徵點及特徵向量法

3.3.1 Harris角點檢測
Harris角點檢測的基本思想:算法基本思想是使用一個固定窗口在圖像上進行任意方向上的滑動,比較滑動前與滑動後兩種情況,窗口中的像素灰度變化程度,如果存在任意方向上的滑動,都有着較大灰度變化,那麼可以認爲該窗口中存在角點。
Harris角點檢測可以分爲5個步驟:
在這裏插入圖片描述Harris角點檢測算子對圖像的亮度和對比度變化不敏感,該算子具有旋轉不變性,不具有縮放不變性。
OpenCV計算Harris角點檢測代碼:

Mat show = imread("pic/task9-1.jpg");
Mat srcImage, dst, norm_dst;
cvtColor(show, srcImage, COLOR_RGB2GRAY);
	
cornerHarris(srcImage, dst, 2, 3, 0.04);
normalize(dst, norm_dst, 0, 255, NORM_MINMAX, CV_8UC1, Mat()); //CV_32FC1

for (int i = 0; i < srcImage.rows; i++)
	for (int j = 0; j < srcImage.cols; j++)
		if (norm_dst.at<uchar>(i, j) > 128)
			circle(show, Point(j, i), 1, Scalar(0, 255, 0), 2);
imshow("show", show);
	waitKey();
**加粗樣式**

在這裏插入圖片描述
3.3.2 SIFT 檢測
SIFT算法的實質是在不同的尺度空間上查找關鍵點(特徵點),並計算出關鍵點的方向。SIFT所查找到的關鍵點是一些十分突出,不會因光照,仿射變換和噪音等因素而變化的點,如角點、邊緣點、暗區的亮點及亮區的暗點等。
SIFT算法分解爲如下四步:

  1. 尺度空間極值檢測:搜索所有尺度上的圖像位置。通過高斯微分函數來識別潛在的對於尺度和旋轉不變的興趣點。
  2. 關鍵點定位:在每個候選的位置上,通過一個擬合精細的模型來確定位置和尺度。關鍵點的選擇依據於它們的穩定程度。
  3. 方向確定:基於圖像局部的梯度方向,分配給每個關鍵點位置一個或多個方向。所有後面的對圖像數據的操作都相對於關鍵點的方向、尺度和位置進行變換,從而提供對於這些變換的不變性。
  4. 關鍵點描述:在每個關鍵點周圍的鄰域內,在選定的尺度上測量圖像局部的梯度。這些梯度被變換成一種表示,這種表示允許比較大的局部形狀的變形和光照變化。
    SIFT算法在OpenCV中的contrib的SIFT_Impl中實現。
    3.3.3 SURF 特徵檢測
    SURF是speeded up roubst feature的簡稱,在不同尺度空間定位關鍵點,並給出每個點的特徵向量。SURF特徵檢測的步驟:
    1.尺度空間的極值檢測:搜索所有尺度空間上的圖像,通過Hessian來識別潛在的對尺度和選擇不變的興趣點。
    2.特徵點過濾並進行精確定位。
    3.特徵方向賦值:統計特徵點圓形鄰域內的Harr小波特徵。即在60度扇形內,每次將60度扇形區域旋轉0.2弧度進行統計,將值最大的那個扇形的方向作爲該特徵點的主方向。
    4.特徵點描述:沿着特徵點主方向周圍的鄰域內,取4×4×4個矩形小區域,統計每個小區域的Haar特徵,然後每個區域得到一個4維的特徵向量。一個特徵點共有64維的特徵向量作爲SURF特徵的描述子。
    SURF算法OpenCV中的contrib的SURF_Impl中實現。
    3.3.4 FAST角點檢測
    Fast算法的思想是:角點所在像素和周圍領域像素差別較大,因此,檢測一個像素鄰域有多少與處在不同區域,即像素值相差較大的像素個數。相差較大的像素個數越多,該點越有可能是角點。
    FAST算法步驟:
    在這裏插入圖片描述
    在OpenCV中,FAST算法在feature2D模塊的FastFeatureDetector中實現。
    opencv實現代碼:
Mat srcImage = imread("pic/task9-1.jpg", IMREAD_GRAYSCALE);
vector<KeyPoint>detectKeyPoint;
Mat keyPointImage;
Ptr<FastFeatureDetector> fast = FastFeatureDetector::create();
fast->detect(srcImage, detectKeyPoint);
drawKeypoints(srcImage, detectKeyPoint, keyPointImage, Scalar(0, 0, 255));
imshow("src image", srcImage);
imshow("keyPoint image", keyPointImage);
imwrite("pic/pic/task9-1.jpg", keyPointImage);
waitKey();

在這裏插入圖片描述
3.4.5 總結
角點檢測可以提取圖像的低級特徵,可以用來做特徵的定位,比如相機參數標定算法中的棋盤格角點定位,也可作爲後續高級特徵生成的輸入。帶有特徵向量的特徵點用於對圖像拼接,三維重構等應用中。
下圖是在實驗室環境下獲取到的傳送帶運動時的連續兩幀圖像,通過對角點的檢測,實現前後兩張圖像的拼接。
在這裏插入圖片描述
獲取到傳送帶運動時的視頻,實時運行以上算法,將面陣相機獲取到的視頻拼接爲一幅長圖。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章