導航:首頁 > 源碼編譯 > opencvml演算法

opencvml演算法

發布時間:2023-06-17 01:59:51

㈠ opencv實現人臉識別有多少種演算法

OpenCV在2.4.1以後的版本中開始自帶人臉識別,共有三種人臉識別演算法的實現,分別是PCA , LDA , LBPH. OpenCV2創建方法如下:
cv::Ptr<cv::FaceRecognizer>facerPCA,facerLDA;
cv::Ptr<cv::FaceRecognizer>facerLBPH=cv::createLBPHFaceRecognizer();
facerPCA=cv::Algorithm::create<cv::FaceRecognizer>("FaceRecognizer.Eigenfaces");
facerLDA=cv::Algorithm::create<cv::FaceRecognizer>("FaceRecognizer.Fisherfaces");
在OpenCV3中,人臉識別的實現被移動到第三方庫opencv_contrib中,而且OpenCV3版本的各個版本3.0.0,3.2.0,3.3.0的創建方法均不同,且都被移動到cv::face::名字空間下.

㈡ opencv 中自帶的模板匹配演算法出處

方法如下:
使用OPENCV下SIFT庫做圖像匹配的常式
// opencv_empty_proj.cpp : 定義控制台應用程序的入口點。
//
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <opencv2/features2d/features2d.hpp>
#include<opencv2/nonfree/nonfree.hpp>
#include<opencv2/legacy/legacy.hpp>
#include<vector>
using namespace std;
using namespace cv;

int _tmain(int argc, _TCHAR* argv[])
{
const char* imagename = "img.jpg";

//從文件中讀入圖像
Mat img = imread(imagename);
Mat img2=imread("img2.jpg");

//如果讀入圖像失敗
if(img.empty())
{
fprintf(stderr, "Can not load image %s\n", imagename);
return -1;
}
if(img2.empty())
{
fprintf(stderr, "Can not load image %s\n", imagename);
return -1;
}
//顯示圖像
imshow("image before", img);
imshow("image2 before",img2);
//sift特徵檢測
SiftFeatureDetector siftdtc;
vector<KeyPoint>kp1,kp2;
siftdtc.detect(img,kp1);
Mat outimg1;
drawKeypoints(img,kp1,outimg1);
imshow("image1 keypoints",outimg1);
KeyPoint kp;
vector<KeyPoint>::iterator itvc;
for(itvc=kp1.begin();itvc!=kp1.end();itvc++)
{
cout<<"angle:"<<itvc->angle<<"\t"<<itvc->class_id<<"\t"<<itvc->octave<<"\t"<<itvc->pt<<"\t"<<itvc->response<<endl;
}
siftdtc.detect(img2,kp2);
Mat outimg2;
drawKeypoints(img2,kp2,outimg2);
imshow("image2 keypoints",outimg2);
SiftDescriptorExtractor extractor;
Mat descriptor1,descriptor2;
BruteForceMatcher<L2<float>> matcher;
vector<DMatch> matches;
Mat img_matches;
extractor.compute(img,kp1,descriptor1);
extractor.compute(img2,kp2,descriptor2);
imshow("desc",descriptor1);
cout<<endl<<descriptor1<<endl;
matcher.match(descriptor1,descriptor2,matches);
drawMatches(img,kp1,img2,kp2,matches,img_matches);
imshow("matches",img_matches);
//此函數等待按鍵,按鍵盤任意鍵就返回
waitKey();
return 0;
}

㈢ opencv關於像素點的圖像匹配演算法

首先,建議你將圖像中感興趣區域(比如上圖中的字母)取出來進行歸一化,然後在進行匹配率計算。這是因為周圍環境會對匹配率產生影響。
其次,建議你將匹配率演算法改成Hausdorff距離https://en.wikipedia.org/wiki/Hausdorff,這樣對圖像有些平移什麼的都不怎麼敏感了。

㈣ OpenCV(二)掩碼操作與平滑(均值,高斯模糊)

OpenCV知識總結來到了下一個難度高一點的,掩碼操作和模糊效果,這是圖像處理裡面常見的操作。
如果遇到問題請在這里聯系我: https://www.jianshu.com/p/67324fb69074

掩碼操作實際上思想上很簡單:根據一個掩碼矩陣(卷積核)重新計算圖像中的每一個像素。掩碼矩陣中的值表示近鄰像素的值(包括自身像素的值)對新像素的值有多大的影響,從數學上觀點看來,就是對掩碼矩陣內每一個設置好權重,然後對對應的像素領域內做一個權加平均。

卷積是什麼?用一個簡單的公式來表示:

本質上,卷積就是這種思想。卷積把萬事萬物看成一個輸入,當萬事萬物的狀態出現了變化,則會通過某種系統產生變化,變成另一種輸出狀態。而這個系統往往就在數學眼裡就叫做卷積。

而在深度學習中,往往每一個卷積核是一個奇數的矩陣,做圖像識別的時候會通過這個卷積核做一次過濾,篩選出必要的特徵信息。

那麼掩碼操作在數學上是怎麼回事?我們平常運用掩碼做什麼?在OpenCV中掩碼最常見的操作就是增加圖片對比度。對比度的概念是什麼,在上一節聊過,通俗來講就是能夠增強像素之間的細節。我們可以對對每個像素做如下操作:

可能這幅圖,理解起來比較困難。實際上流程如此:

舉個例子,就以計算出掩碼矩陣之後的E的位置,能看到此時是原圖中所有的像素都會取出和掩碼矩陣一樣大小的矩陣。也就是取出原圖的紅色那一塊的領域,分別對E周邊包括自己做了一次加權處理,最後賦值回E中。

並且進行如下的權加公式:

這樣就能對原來的矩陣進行掩碼處理。但是這么做發現沒有,如果我們要對A做掩碼處理就會發現掩碼矩陣對應到原圖的位置不存在。現在處理有兩種,一種是不對邊緣的像素做掩碼處理,另一種是為周邊的圖像做一個padding處理,這種操作在深度學習的圖像處理中很常見,通常設置0像素,或者拷貝對邊的邊緣像素。

能看到這里處理和卷積處理不太一樣,只是為了方便,把這種掩碼濾波操作稱為一種核,是自相關,並不是去計算卷積。

能看到此時這兩張圖片的對比度有很明顯的區別。經過掩碼矩陣之後,會發現原圖會更加平滑一點,而掩碼操作之後會導致整個圖片最亮和最暗之間的差距拉大。

從數學公式上來看,當前像素權重為5,周邊的點的權重是-1和0.能夠發現會對當前的節點加深,同時把周圍的像素值減掉,就增加了每一個像素點和周邊像素差值,也就是對比度。

當然在OpenCV中,有這么一個函數filter2D,處理掩碼操作。

這里創建一個3*3的核。這個核實際上就是上圖的那個。這樣傳遞一個掩碼矩陣和圖像的深度就完成了掩碼操作。

平滑也稱為模糊,是一項高頻率使用的操作。
平滑的作用有很多,其中一項就是降噪音。平滑處理和掩碼操作有點相似,也是需要一個濾波器,我們最常用的濾波器就是線性濾波器。線性濾波處理的輸出像素值 是輸出像素值 的權加和:

其中,h(k,l)成為核,它僅僅只是一個權加系數。圖形上的操作和上面的圖相似。不妨把核當成一個滑動窗口,不斷的沿著原圖像素的行列掃動,掃動的過程中,不斷的把路過像素都平滑處理。

這里先介紹均值濾波器,它的核心如下:

這里的參數意思是,src:輸入的圖像,dst:經過均值模糊之後的輸出圖像,Size:是指這個濾波器的大小,Point是指整個圖像模糊繞著哪個原點為半徑的進行處理,傳入(-1,-1)就是指圖像中心,這樣就能模糊整個圖像。

其計算原理很簡單就是,把核裡面的所有權重設置為1,最後全部相加求平均值。最後賦值到原來的像素上。

最有用的濾波器 (盡管不是最快的)。 高斯濾波是將輸入數組的每一個像素點與 高斯內核 卷積將卷積和當作輸出像素值。

高斯模糊實際上是一個二維的高斯核。回顧一下一維的高斯函數:

那麼二維實際上就是,就是在原來的x,y軸的情況下,增加一個z軸的緯度,實際上看起來就像一座山一樣。

二維的高斯函數可以表示為:

為了達到達到

其OpenCV的調用方式:

這里的參數意思是,src:輸入的圖像,dst:經過高斯模糊之後的輸出圖像,Size:是指這個濾波器的大小。sigmaX和sigmaY分別指代的是高斯模糊x軸上和y軸上的二維高斯函數的變化幅度。

換個形象的話說,用上圖舉個例子,就是確定這個高斯函數這個山的x方向的陡峭程度以及y軸方向的陡峭程度。

下面就高斯模糊,均值模糊和原圖的比對

能看到,高斯模糊比起均值模糊保留了圖像中相關的形狀信息。

為什麼會這樣呢?原因很簡單。因為在計算高斯模糊之前,會根據當前像素區域中所有的像素點進行一次,核的計算,越往中心的權重越高,權重如同小山一下,因此中心的像素權重像素一高了,雖然模糊但是還是保留了原來的形狀。

但是當高斯模糊的矩陣大小和sigmaX,sigmaY相似的時候,整個高斯函數就不像山,而是想平原一樣平坦。換句話說,整個高斯核中的權重就會,偏向一,就會導致和均值模糊類似效果。

高斯模糊計算流程:
圖像中某一段圖形的像素是如下分布,

這個時候高斯模糊需要一個核去對每一個位置做濾波。此時不同於均值模糊,沒有固定的核矩陣,而是通過上面這個矩陣,計算出高斯的核,最後再計算變化後的矩陣每一個對應的像素。

雖然原理是這樣,但是實際上OpenCV為了迅速,在原生實現的時候,內部判斷到核是小於7的大小,設置一套固定的高斯模糊矩陣。

這樣直接就結束,不是我文章的風格,作為一個程序員,還是有必要探索一下,為什麼OpenCV計算速度會比我們自己手寫的快。

為了讓源碼看的不那麼辛苦,先聊聊OpenCV底層的設計思想。首先在OpenCV中,內置了幾種計算方案,按照效率高低優先度依次的向後執行。

這種設計可以看成我們的平常開發的攔截器設計。當發現優先度高的計算模式發現可以使用的時候,OpenCV將會使用這種模式下的演算法進行運算。

一般來說,OpenCV內置如下四個層級計算方案,按照優先順序依次為:

能看到按照這個優先順序不斷的向下查找,找到當前OpenCV最快的計算環境。除了最後一個之外,其他三個都是並發計算。

記住這個流程,我們查看OpenCV的源碼就很輕鬆了。

先來看看filter2D的源碼。

果不其然,在filter2D實現的第一步,就開始調用CV_OCL_RUN宏去調用OpenCL的顯卡並發計算。

能看到,這裡面發送了一個condition和一個方法到OpenCL中運行。但是如果,OpenCV在編譯的時候,我們沒有打開這個OpenCL的選項,沒有OpenCL的環境的時候,它實際上就是一個沒什麼用處的宏:

當有了OpenCL的環境,這個宏就會替換成這個:

能清晰的看到,此時會判斷當前的OpenCL是否還在活躍,活躍的狀態,並且條件和方法符合規范,就會通過CV_IMPL_ADD,把方法添加到一個vector向量中,讓OpenCL讀取執行。

在這裡面,OpenCV想要使用OpenCL進行計算,就需要這個Mat的類型是UMat,並且是緯度小於等於2.當不符合這兩個條件將不會執行OpenCL。

UMat是專門給OpenCL規范計算而使用的矩陣。裡面有很多和Mat相似的方法。

此時可能是多線程處理,因此會添加一個智能鎖,去保證數據的正確性。

具體的思路,將不作為重點,這邊先看看OpenCV是傳入了ocl_filter2D的方法,看看這個方法在OpenCL中的執行流程。

OpenCL會把命令最後發送到顯卡處理。

實際上這一步和上面的方法有點相似。本質上都是獲取需要模糊的區域,如果是(-1,-1),則取中心點,接著判斷當前濾波對邊緣的處理(BORDER_ISOLATED 不去獲取Point為圓心設置的模糊之外的區域)。

能看到這個枚舉已經解釋很清楚了,默認的邊緣處理是復制二個和倒數第二個填充邊緣。
最後進入到hal的filter2D進一步操作。

能看到這里有四種方式:

在情況1中,一般的情況replacementFilter2D返回的是一個沒有實現的錯誤碼,第二種情況是Intel的並行計算庫,沒有任何研究,跳過。我們來看看第三種情況和第四種情況

當然這裡面判斷能夠使用dft的判斷首先要當前必須要整張圖做濾波處理,其次是不能是(0,0)的點為圓心做濾波。最後要判斷當前當前的cpu指令是否支持,支持則允許核的寬 高最高為130以內使用原生實現,否則只支持核的寬 高為50以內使用原生實現。

能看到這裡面的核心就是調用crossCorr,處理核以及原圖的矩陣(使用了快速傅立葉處理相關性計算)。最後從同add添加到目標Mat中,由於add的delta函數為0,因此就和替代的效果一致。

能看到此時,先初始化一個FilterEngine(線性濾波引擎),接著使用apply調用濾波引擎的執行方法。

我們來看看線性引擎的創建:

實際上在這個過程中通過makePtr創建一個sharedptr的指針指向FilterEngine,其原理和Android的智能指針相似。

這個引擎不是關鍵關鍵的是getLinearFilter,這個方法創建了一個線性濾波器的實際操作對象。

我們來看看這個結構體:
能看到這裡面會根據次數傳進來的目標矩陣和原始矩陣的位深創建不同的濾波操作者。

假設,我們現在原圖和目標圖都是8位位深的矩陣,我們只需要關注下面這個構造函數。

Fliter2D結構體持有著模糊中心點,核,原/目標矩陣, 可以猜測到實際上正在做操作的就是這個結構體。

在preprocess2DKernel方法中,Fliter2D把核的相關信息存儲到coords,coeffs中

可以看到此時會判斷當前的核矩陣中type是什麼,接著再把矩陣中每一個不為0的位置設置進coords,像素數值設置到_coeffs。此時相當於把核矩陣展開成一個向量。

能看到此時濾波引擎會先調用FilterEngine__start,再調用FilterEngine__proceed執行計算。
實際上在FilterEngine__start中計算的是本次循環,需要計算的邊界。

FilterEngine__proceed中才是正式計算,做dst循環,最後把具體操作丟給線性引擎生成的Fliter2D的方法中。

了解這兩個東西我們直接抽出核心看看fliter是如何運作:

㈤ 如何利用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;
}

㈥ opencv檢測缺陷用哪些演算法

根據不同的需求來進行不同的處理
1 空洞 這個肯定是像素顏色和周邊的不同 建議用閾值分割 然後輪廓檢測
2 褶皺 這個褶皺肯定會有梯度的變化 建議檢測邊緣 再計算褶皺的梯度信息
3 劃痕 這個和上一個問題相似 但是也有不同 應該是梯度的方向和強度不同(一個是凹一個是凸)
4 斑點 如果只是點點星星的 opencv里也有很多角點檢測演算法 比如 surf fast ORB等

閱讀全文

與opencvml演算法相關的資料

熱點內容
dvd光碟存儲漢子演算法 瀏覽:757
蘋果郵件無法連接伺服器地址 瀏覽:963
phpffmpeg轉碼 瀏覽:672
長沙好玩的解壓項目 瀏覽:145
專屬學情分析報告是什麼app 瀏覽:564
php工程部署 瀏覽:833
android全屏透明 瀏覽:737
阿里雲伺服器已開通怎麼辦 瀏覽:803
光遇為什麼登錄時伺服器已滿 瀏覽:302
PDF分析 瀏覽:486
h3c光纖全工半全工設置命令 瀏覽:143
公司法pdf下載 瀏覽:382
linuxmarkdown 瀏覽:350
華為手機怎麼多選文件夾 瀏覽:683
如何取消命令方塊指令 瀏覽:350
風翼app為什麼進不去了 瀏覽:779
im4java壓縮圖片 瀏覽:362
數據查詢網站源碼 瀏覽:151
伊克塞爾文檔怎麼進行加密 瀏覽:893
app轉賬是什麼 瀏覽:163