當前位置:首頁 » 操作系統 » opencv演算法原理

opencv演算法原理

發布時間: 2023-07-18 12:46:05

1. 如何利用opencv計算圖像畸變系數,並進行校正與攝像機標定

如果知道圖像,不知道相機還怎麼通過相機來標定畸變?
1、只給定一張圖片可以根據圖像中相關特徵進行標定,比如:圖像中的某個物體具有直線性特點。一般是找出本來應當是直線的物體邊緣,在其上取若干點,根據這些點將圖像中的物體邊緣重新校正為直線。簡單講就是利用: line is straight 這個原理。
2、目前最常用的張正友在1998年提出的一種標定方法,是通過二維標定板(平面標定板),根據小孔成像的原理,通過對 reprojection error 最小化進行非線性優化,來實現對相機的標定。並非根據看似高大上的訓練集來標定。
當然他寫這篇文章的目的不單單是為了校正畸變。畸變參數只是張正友相機標定法所求參數的一部分,即:兩個徑向畸變系數和兩個切向畸變系數。

消除畸變的目的是讓相機盡量地逼近針孔相機模型,這樣相機成像時直線才會保持其直線性。一般常見的畸變校正演算法都是根據這一原理來實現的。
當然,還有二般的情況。比如:圖像中壓根就沒有直線性物體存在。我們該怎麼辦?還能進行標定嗎?
答案是肯定的。可以利用對極約束,對圖像畸變進行標定。不過,這需要至少兩幅圖像,而且這兩幅圖像必須是同一相機在短時間內拍攝得到。

2. opencv進階1

在Opencv中人臉識別是基於Haar特徵+Adaboost級聯分類器來實現人臉識別的!

要理解這節內容,我們首先要明白什麼是特徵?

特徵其實就是某個區域的像素點經過運算之後得到的結果! 例如haar特徵其實就是用下圖列出的模板在圖像中滑動,計算白色區域覆蓋的像素之和減去黑色區域覆蓋的像素之和,運算出來的結果就是haar特徵值!

Haar特徵一般和Adaboost分類器結合在一起進行目標識別!

這里需要運動機器學習的知識! 不過值得慶幸的是Opencv已經為我們訓練好了數據,並且已經提取出了人臉的特徵,在opencv的源碼中有相應的xml特徵文件. 並且我們只需要調用opencv提供好的API即可快速完成人臉識別的功能!

核心api為:

實現步驟:

HSV(Hue, Saturation, Value)是根據顏色的直觀特性由A. R. Smith在1978年創建的一種顏色空間, 也稱六角錐體模型(Hexcone Model)。

這個模型中顏色的參數分別是:色調(H),飽和度(S),明度(V)

用角度度量,取值范圍為0°~360°,從紅色開始按逆時針方向計算,紅色為0°,綠色為120°,藍色為240°。它們的補色是:黃色為60°,青色為180°,品紅為300°;

飽和度S表示顏色接近光譜色的程度。一種顏色,可以看成是某種光譜色與白色混合的結果。其中光譜色所佔的比例愈大,顏色接近光譜色的程度就愈高,顏色的飽和度也就愈高。飽和度高,顏色則深而艷。光譜色的白光成分為0,飽和度達到最高。通常取值范圍為0%~100%,值越大,顏色越飽和。

明度表示顏色明亮的程度,對於光源色,明度值與發光體的光亮度有關;對於物體色,此值和物體的透射比或反射比有關。通常取值范圍為0%(黑)到100%(白)。

結論:

注意: 在opencv中,H、S、V值范圍分別是[0,180],[0,255],[0,255],而非[0,360],[0,1],[0,1];

這里我們列出部分hsv空間的顏色值, 表中將部分紫色歸為紅色

[圖片上傳失敗...(image-4f70f7-1563843266225)]
.jpg)

注意,這僅僅只能做一個比較粗糙的判定,按照我們人的正常思維,在傍晚臨界點我們也無法判定當前是屬於晚上還是白天!

在一張圖片中,如果某個物體的顏色為純色,那麼我們就可以使用顏色過濾inRange的方式很方便的來提取這個物體.

下面我們有一張網球的圖片,並且網球的顏色為一定范圍內的綠色,在這張圖片中我們找不到其它顏色也為綠色的圖片,所以我們可以考慮使用綠色來提取它!

圖片的顏色空間默認為BGR顏色空間,如果我們想找到提取純綠色的話,我們可能需要寫(0,255,0)這樣的內容,假設我們想表示一定范圍的綠色就會很麻煩!

所以我們考慮將它轉成HSV顏色空間,綠色的色調H的范圍我們很容易知道,剩下的就是框定顏色的飽和度H和亮度V就可以啦!

實現步驟:

圖像二值化( Image Binarization)就是將圖像上的像素點的灰度值設置為0 255,也就是將整個圖像呈現出明顯的黑白效果的過程。

在數字圖像處理中,二值圖像佔有非常重要的地位,圖像的二值化使圖像中數據量大為減少,從而能凸顯出目標的輪廓。

[圖片上傳失敗...(image-a31052-1563843266226)]

我們使用一個全局值作為閾值。但是在所有情況下這可能都不太好,例如,如果圖像在不同區域具有不同的照明條件。在這種情況下,自適應閾值閾值可以幫助。這里,演算法基於其周圍的小區域確定像素的閾值。因此,我們為同一圖像的不同區域獲得不同的閾值,這為具有不同照明的圖像提供了更好的結果。

除上述參數外,方法cv.adaptiveThreshold還有三個輸入參數:

adaptiveMethod 決定閾值是如何計算的:

BLOCKSIZE 確定附近區域的大小和 Ç 是從平均值或附近的像素的加權和中減去一個常數。

採用日本人大津提出的演算法,又稱作最大類間方差法,被認為是圖像分割中閾值選取的最佳演算法,採用這種演算法的好處是執行效率高!

<img src="./img2/otsu.jpg" width="500" />

如果我們把圖像看作信號,那麼雜訊就是干擾信號。我們在採集圖像時可能因為各種各樣的干擾而引入圖像雜訊。在計算機中,圖像就是一個矩陣, 給原始圖像增加雜訊, 我們只需要讓像素點加上一定灰度即可.
f(x, y) = I(x, y) + noise

常見的雜訊有椒鹽雜訊(salt and pepper noise),為什麼叫椒鹽雜訊?因為圖像的像素點由於雜訊影響隨機變成了黑點(dark spot)或白點(white spot)。這里的「椒」不是我們常見的紅辣椒或青辣椒,而是外國的「胡椒」(香料的一種)。我們知道,胡椒是黑色的,鹽是白色的,所以才取了這么個形象的名字.

接下來我們來生成10%的椒雜訊和鹽雜訊:

我們還要注意,opencv的圖像矩陣類型是uint8,低於0和高於255的值並不截斷,而是使用了模操作。即200+60=260 % 256 = 4。所以我們需要先將原始圖像矩陣和雜訊圖像矩陣都轉成浮點數類型進行相加操作,然後再轉回來。

3. 如何利用opencv實現彩色圖像邊緣檢測演算法

在opencv中顯示邊緣檢測很簡單,只需調用一個cvCanny函數,其使用的是Canny演算法來實現對圖像的邊緣檢測.
函數原型為:
void cvCanny( const CvArr* image,CvArr* edges,double threshold1,double threshold2, int aperture_size=3 );
第一個參數為待檢測的圖像,注意一點,其必須是灰度圖.
第二個參數為輸出的邊緣圖,其也是一個灰度圖.
後三個參數與Canny演算法直接相關,threshold1和threshold2 當中的小閾值用來控制邊緣連接,大的閾值用來控制強邊緣的初始分割,aperture_size運算元內核大小,可以去看看Canny演算法.
從彩色圖到灰度圖需要使用到cvCvtColor函數,其接受三個參數,第一為輸入,第二為輸出,第三個為轉換的標識,我們這邊是RGB到GRAY,使用的是CV_RGB2GRAY.
參考demo代碼如下:

#include <iostream>

#include <string>
#include <sstream>
#include <opencv/cv.h>
#include <opencv/highgui.h>

using namespace std;

int String2int(const string& str_)
{
int _nre = 0;
stringstream _ss;
_ss << str_;
_ss >> _nre;
return _nre;
}

void DoCanny(const string& strFileName_)
{
//原彩色圖片
IplImage* _pIplImageIn = cvLoadImage(strFileName_.data());

if (_pIplImageIn == NULL)
{
return;
}
//彩色圖片轉換成灰度圖放置的圖片
IplImage* _pIplImageCanny = cvCreateImage(cvGetSize(_pIplImageIn), _pIplImageIn->depth, 1);
cvCvtColor(_pIplImageIn, _pIplImageCanny, CV_RGB2GRAY);//CV_RGB2GRAY將rgb圖轉成灰度圖
//只有邊緣路徑的圖片
IplImage* _pIplImageOut = cvCreateImage(cvGetSize(_pIplImageIn), IPL_DEPTH_8U, 1);

//邊緣檢測只能作用於灰度圖
if (_pIplImageCanny->nChannels != 1)
{
return;
}

//邊緣檢測操作
cvCanny(_pIplImageCanny, _pIplImageOut, 1, 110, 3);

cvNamedWindow("Src");
cvShowImage("Src", _pIplImageIn);
cvNamedWindow("Canny");
cvShowImage("Canny", _pIplImageOut);

cvWaitKey(0);

cvReleaseImage(&_pIplImageIn);
cvReleaseImage(&_pIplImageCanny);
cvReleaseImage(&_pIplImageOut);

cvDestroyWindow("Src");
cvDestroyWindow("Canny");

}

int main(int argc, char* argv[])
{
if (argc < 2)
{
cout << "You should give the filename of picture!" << endl;
return -1;
}
DoCanny(argv[1]);
return 0;
}

熱點內容
伺服器電腦機房是幹嘛的 發布:2025-03-16 02:30:47 瀏覽:488
龍貝格演算法c語言 發布:2025-03-16 02:26:28 瀏覽:101
c語言字元串讀入 發布:2025-03-16 02:21:23 瀏覽:476
python爬蟲開發環境 發布:2025-03-16 02:19:55 瀏覽:626
androidondestory 發布:2025-03-16 02:12:49 瀏覽:862
軟體源碼侵權 發布:2025-03-16 02:06:54 瀏覽:287
給表添加欄位的sql 發布:2025-03-16 02:04:29 瀏覽:473
1除5演算法 發布:2025-03-16 02:02:57 瀏覽:757
oppo雲密碼本在哪裡 發布:2025-03-16 01:57:13 瀏覽:534
c語言定義pi的 發布:2025-03-16 01:51:08 瀏覽:603