標籤:des style class blog code color
將一副映像轉變成另一種表現形式 ,比如,傅裡葉變換將映像轉換成頻譜分量
卷積 —— 變換的基礎
cvFilter2D 源映像 src 和靶心圖表像 dst 大小應該相同
注意:卷積核的係數應該是浮點類型的,必須用 CV_32F 來初始化矩陣
cvFilter2D 函數內部處理邊界 —— cvCopyMakeBorder (將特定的映像輕微變大,然後以一種方式填充映像邊界)
梯度和Sobel導數
sobel 運算元包含任意階的微分以及融合偏導 大核對導數有更好的逼近,小核對雜訊更加敏感
如果源映像src是8位的,為避免溢出,靶心圖表像的深度必須是 IPL_DEPTH_16S
Scharr 濾波器
拉普拉斯變換 —— 二次導數 cvLaplace() —— 沿X軸Y軸的二次導數的和(周圍是更高值的單點或者小塊會使函數值最大化)
靶心圖表像必須是16位(有符號)或者32位(浮點)映像
應用:檢測團塊,邊緣檢測 —— 原始映像的邊緣位於拉普拉斯的值等於0的地方
Canny 運算元 —— 首先在x和y方向求一階導數,然後組合為4個方向的導數,這些方嚮導數達到局部最大值的點就是組成邊緣的候選點;將獨立的候選像素拼裝成輪廓(應用滯後性閾值)
cvCanny —— 推薦的上下限閾值比例為2:1或3:1
霍夫變換 —— 二值映像中的任何點都可能是一些候選直線集合的一部分
OpenCV 支援兩種不同形式的霍夫變換:標準霍夫變換(SHT),累計機率霍夫變換(PPHT)—— 減少計算時間
霍夫圓變換
#include <cv.h>#include <highgui.h>#include <math.h>int main(int argc,char** argv){ IplImage* img=cvLoadImage("circle.jpg",CV_LOAD_IMAGE_GRAYSCALE); CvMemStorage* storage=cvCreateMemStorage(0); cvSmooth(img,img,CV_GAUSSIAN,5,5); CvSeq* results=cvHoughCircles(img,storage,CV_HOUGH_GRADIENT,2,img->width/10); for (int i=0;i<results->total;i++) { float* p=(float*)cvGetSeqElem(results,i); CvPoint pt=cvPoint(cvRound(p[0]),cvRound(p[1])); cvCircle(img,pt,cvRound(p[2]),CV_RGB(0xff,0xff,0x00)); } cvNamedWindow("w1"); cvShowImage("w1",img); cvWaitKey(); cvReleaseMemStorage(&storage); cvDestroyAllWindows(); return 0;}
重新對應
cvRemap() —— 用於矯正失真的標定或立體映像(涉及到插值問題)
仿射變換,透視變換
一個平面內的任意平行四邊形ABCD可以被仿射為另一個平行四邊形 ,仿射變換是透視變換的子集
稠密仿射變換 —— 映像扭曲必須進行一些插值運算以使輸出的映像平滑 cvWarpAffine cvGetQuadrangleSubPix
仿射映射矩陣的計算 —— cvGetAffineTransform (兩個包含三個點的數組,定義了兩個平行四邊形)
// 首先利用 cvGetAffineTransform 計算變換矩陣,接下來做一次仿射變換#include <cv.h>#include <highgui.h>int main(int argc,char** argv){ CvPoint2D32f srcTri[3],dstTri[3]; CvMat* rot_mat=cvCreateMat(2,3,CV_32FC1); CvMat* warp_mat=cvCreateMat(2,3,CV_32FC1); IplImage *src,*dst; src=cvLoadImage("wukong.jpg",CV_LOAD_IMAGE_UNCHANGED); dst=cvCloneImage(src); dst->origin=src->origin; cvZero(dst); srcTri[0].x=0; srcTri[0].y=0; srcTri[1].x=src->width-1; srcTri[1].y=0; srcTri[2].x=0; srcTri[3].y=src->height-1; dstTri[0].x=src->width*0.0; dstTri[0].y=src->height*0.33; dstTri[0].x=src->width*0.85; dstTri[0].y=src->height*0.25; dstTri[0].x=src->width*0.15; dstTri[0].y=src->height*0.7; cvGetAffineTransform(srcTri,dstTri,warp_mat); cvWarpAffine(src,dst,warp_mat); cvCopy(dst,src); CvPoint2D32f center=cvPoint2D32f(src->width/2,src->height/2); double angle=-50.0; double scale=0.6; cv2DRotationMatrix(center,angle,scale,rot_mat); cvWarpAffine(src,dst,rot_mat); cvNamedWindow("w1"); cvNamedWindow("w2"); cvShowImage("w1",dst); cvShowImage("w2",src); cvWaitKey(); cvReleaseImage(&dst); cvReleaseMat(&rot_mat); cvReleaseMat(&warp_mat); cvDestroyAllWindows(); return 0;}
稀疏仿射變換
cvTransform()
透視變換
密集透視變換 cvWarpPerspective()
計算透視映射矩陣 cvGetPerspectiveTransform
// 透視變換 /**/#include <cv.h>#include <highgui.h>int main(int argc,char** argv){ CvPoint2D32f srcQuad[4],dstQuad[4]; CvMat *warp_matrix=cvCreateMat(3,3,CV_32FC1); IplImage *src,*dst; src=cvLoadImage("wukong.jpg",CV_LOAD_IMAGE_GRAYSCALE); dst=cvCloneImage(src); dst->origin=src->origin; cvZero(dst); srcQuad[0].x=0; srcQuad[0].y=0; srcQuad[1].x=src->width-1; srcQuad[1].y=0; srcQuad[2].x=0; srcQuad[2].y=src->height-1; srcQuad[3].x=src->width-1; srcQuad[3].y=src->height-1; dstQuad[0].x=src->width*0.05; dstQuad[0].y=src->height*0.33; dstQuad[1].x=src->width*0.9; dstQuad[1].y=src->height*0.25; dstQuad[2].x=src->width*0.2; dstQuad[2].y=src->height*0.7; dstQuad[3].x=src->width*0.8; dstQuad[3].y=src->height*0.9; cvGetPerspectiveTransform(srcQuad,dstQuad,warp_matrix); cvWarpPerspective(src,dst,warp_matrix); cvNamedWindow("w1"); cvShowImage("w1",dst); cvWaitKey(); cvReleaseImage(&dst); cvReleaseMat(&warp_matrix); cvDestroyAllWindows(); return 0;}
稀疏透視變換 cvPerspectiveTransform
透視變換實際上是一個嵌入在三維空間的二維平面上的實際映射點映射回一個不同的二維子空間
cvCartToPolar cvPolarToCart
笛卡爾空間和極行或徑向空間之間進行映射
對數極座標變換 —— 人的視覺系統 —— 是對物體視場的一種不變表示 cvLogPolar
#include <cv.h>#include <highgui.h>int main(int argc,char** argv){ IplImage* src; double M=40; // 縮放比例 src=cvLoadImage("wukong.jpg",CV_LOAD_IMAGE_GRAYSCALE); IplImage* dst=cvCreateImage(cvGetSize(src),8,1); IplImage* src2=cvCreateImage(cvGetSize(src),8,1); cvLogPolar(src,dst,cvPoint2D32f(src->width/2,src->height/2),M,CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS); cvLogPolar(dst,src2,cvPoint2D32f(src->width/2,src->height/2),M,CV_INTER_LINEAR|CV_WARP_INVERSE_MAP); cvNamedWindow("w1",1); cvShowImage("w1",dst); cvNamedWindow("w2",1); cvShowImage("w2",src2); cvWaitKey(); cvReleaseImage(&dst); cvReleaseImage(&src2); cvDestroyAllWindows(); return 0;}
離散傅裡葉變換 DFT
OpenCV 中實現了快速傅裡葉變換,cvDFT 可以計算輸入是一維或二維數組時的FFT
輸入數組和輸出數組必須是浮點類型並且通常是單通道或是雙通道的
cvMulSpectrums 頻譜乘法
#include <cv.h>#include <highgui.h> void speedy_convolution(const CvMat* A,const CvMat* B,CvMat* C){ // 建立兩個對於DFT演算法維數最佳的新數組 int dft_M=cvGetOptimalDFTSize(A->rows+B->rows-1); int dft_N=cvGetOptimalDFTSize(A->cols+B->cols-1); CvMat* dft_A = cvCreateMat(dft_M,dft_N,A->type); CvMat* dft_B=cvCreateMat(dft_M,dft_N,B->type); CvMat temp; cvGetSubRect(dft_A,&temp,cvRect(0,0,A->cols,A->rows)); cvCopy(A,&temp); cvGetSubRect(dft_A,&temp,cvRect(A->cols,0,dft_A->cols-A->cols,A->rows)); cvZero(&temp); cvDFT(dft_A,dft_A,CV_DXT_FORWARD,A->rows); cvGetSubRect(dft_B,&temp,cvRect(0,0,B->cols,B->rows)); cvCopy(B,&temp); cvGetSubRect(dft_B,&temp,cvRect(B->cols,0,dft_B->cols-B->cols,B->rows)); cvZero(&temp); cvDFT(dft_B,dft_B,CV_DXT_FORWARD,B->rows); // 所有頻譜元素相乘 cvMulSpectrums(dft_A,dft_B,dft_A,0); cvDFT(dft_A,dft_A,CV_DXT_INV_SCALE,C->rows); // 反變換 cvGetSubRect(dft_A,&temp,cvRect(0,0,C->cols,C->rows)); cvCopy(&temp,C); cvReleaseMat(dft_A); cvReleaseMat(dft_B);}
離散餘弦變換 DCT
類似於DFT,但所有係數都是實數 cvDCT
積分映像 —— 積分映像中的任意一點(x,y)的值是指從映像的左上方到這個點的所構成的矩形地區內所有點的灰階值之和
cvIntegral() —— 可以實現子領域的快速求和 —— 快速模糊,梯度估計,計算均值和標準差
距離變換 —— 定義一幅新映像,該映像中的每個輸出像素被設成於輸入像素0像素最近的距離 cvDistTransform()
輸出映像必須是32位浮點類型映像
長條圖均衡化
將長條圖範圍展開 ———— 映射函數應該是一個累計分布函數
cvEualizeHist(),原始映像以及靶心圖表像必須是單通道,大小相同的8位元影像像。對於彩色映像,必須先將每個通道分開,再分別進行處理