从这篇起,更多的介绍如何使用,原理会少一点,原理部分会放上其他参考的博客。 1 原理简介 对于笛卡尔坐标系中圆的方程为 实际上,为了减少计算量,OpenCV基于图像梯度: 1 什么是像素重映射 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位或者浮点型图像。 1 什么是直方图 图像直方图,是指对整个图像在灰度范围内的像素值(0~255)统计出现频率次数,据此生成的直方图,成为图像直方图。直方图反映了图像灰度的分布情况。是图像的统计学特征。 直方图均衡化是一种提高图像对比度的方法,拉伸图像灰度值范围 1 概念 将一张0~255的图片像素划分为 把多通道图像分为多个单通道图像: 直方图计算: 1 直方图比较方法 对输入的两张图像计算得到直方图H1与H2,归一化到相同的尺度空间然后可以通过计算H1与H2的之间的距离得到两个直方图的相似程度进而比较图像本身的相似程度。OpenCV提供的比较方法有四种(下面出现的 1 反向投影 实现步骤: mixChannels函数:用于将输入数组的指定通道复制到输出数组的指定通道。 1 模板匹配介绍 OpenCV提供的几种方法:
文章目录
20 霍夫圆检测
2 相关API①原理简介
(x−a)2+(y−b)2=r2也就是
x=a+rcosθ
y=b+rsinθ
即
a=x−rcosθ
b=y−rsinθ对于圆而言,只要圆心a,b相等,半径r相等,那么就在同一个圆上。经过xy坐标系映射到abr的坐标系上,会形成很多三维的曲线,多个曲线相交于三维坐标系abr的同一个点,通过判断abr坐标系中每一点的相交数量,大于一定阈值的点就是xy坐标系上的圆。
②相关API cv::HoughCircles
vector<Vec3f> circles; HoughCircles( InputArray image, //输入图像,必须是8位的单通道灰度图像 OutputArray circles, //输出结果,发现的圆信息 Int method, //方法-HOUGH_GRADIENT Double dp, //dp=1尺度,1就是原图,2是图片减一半 Double mindist, //10 最短距离,可以分辨两个圆,否则认为是同心圆 Double param1, //Canny边缘检测的第一阈值 Double param2, //中心点累加器阈值-候选圆心 Int minradius, //最小半径 Int maxradius //最大半径 ); for(size_t i=0; i<circles.size();i++) { Vec3f cc = circles[i]; circle(dst, Point(cc[0], cc[1]), cc[2], Scalar(0, 0, 255), 2, LINE_AA); circle(dst, Point(cc[0], cc[1]), 2, Scalar(0, 0, 255), 2, LINE_AA); }
21 像素重映射
2 API介绍①什么是像素重映射
②相关API
Remap( InputArray src, //输入图像 OutputArray dst, //输出图像 InputArray map1, //x映射表 CV_32FC1/CV_32FC2 InputArray map2, //y映射表 int interpolation, //选择的差值方法,常见线性插值,可选择立方等 int borderMode, //BORDER_CONSTANT const Scalar borderValue //color )
第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放函数调用后的输出结果,需和源图片有一样的尺寸和类型
第三个参数,InputArray类型的map1,它有两种可能的表示对象。表示点(x,y)的第一个映射。表示CV_16SC2 , CV_32FC1 或CV_32FC2类型的X值。
第四个参数,InputArray类型的map2,同样,它也有两种可能的表示对象,而且他是根据map1来确定表示那种对象。若map1表示点(x,y)时。这个参数不代表任何值。表示CV_16UC1 , CV_32FC1类型的Y值(第二个值)。
第五个参数,int类型的interpolation,插值方式,之前的resize( )函数中有讲到,需要注意,resize( )函数中提到的INTER_AREA插值方式在这里是不支持的,所以可选的插值方式如下:INTER_NEAREST – 最近邻插值INTER_LINEAR – 双线性插值(默认值)INTER_CUBIC – 双三次样条插值(逾4×4像素邻域内的双三次插值)INTER_LANCZOS4 -Lanczos插值(逾8×8像素邻域的Lanczos插值)。
第六个参数,int类型的borderMode,边界模式,有默认值BORDER_CONSTANT.
第七个参数,const Scalar&类型的borderValue,当有常数边界时使用的值,其默认值为0。void updata_map() { for (int row = 0; row < img.rows; row++) { for (int col = 0; col < img.cols; col++) { switch (index) { //index = 0 ,图像的行跟列为为原来的1/2。 //index = 1,为左右翻转(列变换,行不变) //index = 2,为上下翻转(行变换,列不变) //index = 3,为中心旋转 case 0: if (col > (img.cols*0.25) && col<(img.cols*0.75) && row>(img.rows*0.25) && row < (img.rows*0.75)) { map_x.at<float>(row, col) = 2 * (col - (img.cols*0.25)); map_y.at<float>(row, col) = 2 * (row - (img.rows*0.25) - 0.25); } else { map_x.at<float>(row, col) = 0; map_y.at<float>(row, col) = 0; } break; case 1: map_x.at<float>(row, col) = (img.cols - col - 1); map_y.at<float>(row, col) = row; break; case 2: map_x.at<float>(row, col) = col; map_y.at<float>(row, col) = (img.rows - row - 1); break; case 3: map_x.at<float>(row, col) = (img.cols - col - 1); map_y.at<float>(row, col) = (img.rows - row - 1); break; default: break; } } }
22 直方图均衡化
2 直方图均衡化
3 API说明①什么是直方图(Histogram)
②直方图均衡化
通过remap我们可以将图像灰度分布从一个分布映射到另外一个分布,如何再得到映射后的像素值即可。③相关API
equalizeHist( InputArray src, //输入图像,必须是8位单通道图像 OutputArray dst, //输出结果 )
23 直方图计算
2 相关API①直方图概念续
[0,255]=[0,15]⋃[16,31]⋃...⋃[240,255]
bins1⋃bins2⋃...⋃binsn=16
②相关API
split( const Mat &src, //输入图像 Mat* mvbegin //输出的单通道图像数组 )
//分通道显示 vector<Mat> bgr_graphs; split(src, bgr_graphs);
calcHist( const Mat* images, //输入图像指针 int images, //图像数目 const int* channels, //通道数 InputArray mask, //输入mask,可选 OutputArray hist, //输出的直方图数据 int dims, //维数 const int* histsize, //直方图级数 const float* ranges, //值域范围 bool uniform, //默认为True bool accumulate //默认为False )
③示例
#include <opencv2/opencv.hpp> #include <iostream> #include <math.h> using namespace std; using namespace cv; int main(int argc, char** argv) { Mat src = imread("D:/vcprojects/images/test.png"); if (!src.data) { printf("could not load image...n"); return -1; } char INPUT_T[] = "input image"; char OUTPUT_T[] = "histogram demo"; namedWindow(INPUT_T, CV_WINDOW_AUTOSIZE); namedWindow(OUTPUT_T, CV_WINDOW_AUTOSIZE); imshow(INPUT_T, src); vector<Mat> bgr_planes; split(src, bgr_planes); //imshow("single channel demo", bgr_planes[0]); int histSize = 256; float range[] = { 0, 256 }; const float *histRanges = { range }; Mat b_hist, g_hist, r_hist; calcHist(&bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRanges, true, false); calcHist(&bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRanges, true, false); calcHist(&bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRanges, true, false); int hist_h = 400; int hist_w = 512; int bin_w = hist_w / histSize; Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0)); normalize(b_hist, b_hist, 0, hist_h, NORM_MINMAX, -1, Mat()); normalize(g_hist, g_hist, 0, hist_h, NORM_MINMAX, -1, Mat()); normalize(r_hist, r_hist, 0, hist_h, NORM_MINMAX, -1, Mat()); // render histogram chart for (int i = 1; i < histSize; i++) { line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(b_hist.at<float>(i - 1))), Point((i)*bin_w, hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, LINE_AA); line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(g_hist.at<float>(i - 1))), Point((i)*bin_w, hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, LINE_AA); line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(r_hist.at<float>(i - 1))), Point((i)*bin_w, hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, LINE_AA); } imshow(OUTPUT_T, histImage); waitKey(0); return 0; }
24 直方图比较
2 相关API①直方图比较方法概述
H^都表示均值):
d(H1,H2)=∑I(H1(I)−H1^)2∑I(H2(I)−H2^)2∑I(H1(I)−H1)^(H2(I)−H2^)
Hk^=N1J∑Hk(J)即均值为,一张直方图下,各个区间对应的像素点个数的均值
(H(I)−H^)2,分母为
(H(I)−H^)4,结果为1。如果不相同,结果小于1。
d(H1,H2)=I∑H1(I)(H1(I)−H2(I))2
d(H1,H2)=I∑min(H1(I),H2(I))
d(H1,H2)=1−H1^H2^N21I∑H1(I)⋅H2(I)
N∑IH1(I)⋅H2(I)的结果为这张相同图片的均值,
H1^H2^1也是均值,那么结果为0。②相关API
comparHist( InputArray H1, InputArray H2, int method //比较方法 );
25 直方图反向投影(Back Projection)
2 实现步骤与相关API①反向投影
设有原灰度图像矩阵:
⎣⎢⎢⎡1595268637074716⎦⎥⎥⎤
把图像划分为[0-2]、[3-5]、[5-7]、[7-9]四个区间,那么直方图Hist=4 4 6 2,下面计算反向投影矩阵(用Hist直方图的值替代掉原灰度图像矩阵的值,如第一个点在[0-2]区间内,替换成4):
⎣⎢⎢⎡4424462646464646⎦⎥⎥⎤
实际上是将图像的256个灰度值置为很少的几个值了,具体有几个值,要看把0~255划分为多少个区间!反向投影中某点的值就是它对应的原图像中的点所在区间的灰度直方图值。所以,一个区间点越多,在反向投影矩阵中就越亮。反向投影中的“反向”指的是从直方图值到反向投影矩阵映射的过程。
通过反向投影,原始的图像被简化了,而这个简化的过程实际上就是提取出图像的某个特征。所以我们就可以用这个特征来对比两幅图,如果两幅图的反向投影矩阵相似或相同,那么我们就可以判定这两幅图这个特征是相同的。②相关API
③示例
#include <opencv2/opencv.hpp> #include <iostream> #include <math.h> using namespace std; using namespace cv; Mat src; Mat hsv; Mat hue; int bins = 12; void Hist_And_Backprojection(int, void*); int main(int argc, char** argv) { src = imread("D:/vcprojects/images/t1.jpg"); if (src.empty()) { printf("could not load image...n"); return -1; } const char* window_image = "input image"; namedWindow(window_image, CV_WINDOW_NORMAL); namedWindow("BackProj", CV_WINDOW_NORMAL); namedWindow("Histogram", CV_WINDOW_NORMAL); cvtColor(src, hsv, CV_BGR2HSV); hue.create(hsv.size(), hsv.depth()); int nchannels[] = { 0, 0 }; mixChannels(&hsv, 1, &hue, 1, nchannels, 1); createTrackbar("Histogram Bins:", window_image, &bins, 180, Hist_And_Backprojection); Hist_And_Backprojection(0, 0); imshow(window_image, src); waitKey(0); return 0; } void Hist_And_Backprojection(int, void*) { float range[] = { 0, 180 }; const float *histRanges = { range }; Mat h_hist; calcHist(&hue, 1, 0, Mat(), h_hist, 1, &bins, &histRanges, true, false); normalize(h_hist, h_hist, 0, 255, NORM_MINMAX, -1, Mat()); Mat backPrjImage; calcBackProject(&hue, 1, 0, h_hist, backPrjImage, &histRanges, 1, true); imshow("BackProj", backPrjImage); int hist_h = 400; int hist_w = 400; Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0)); int bin_w = (hist_w / bins); for (int i = 1; i < bins; i++) { rectangle(histImage, Point((i - 1)*bin_w, (hist_h - cvRound(h_hist.at<float>(i - 1) * (400 / 255)))), //Point(i*bin_w, (hist_h - cvRound(h_hist.at<float>(i) * (400 / 255)))), Point(i*bin_w, hist_h), Scalar(0, 0, 255), -1); } imshow("Histogram", histImage); return; }
void mixChannels( const Mat* src, //输入数组或向量矩阵,所有矩阵的大小和深度必须相同。 size_t nsrcs, //矩阵的数量 Mat* dst, //输出数组或矩阵向量,大小和深度必须与src相同 size_t ndsts,//矩阵的数量 const int* fromTo,//指定被复制通道与要复制到的位置组成的索引对 size_t npairs //fromTo中索引对的数目 );
26 模板匹配(Template Match)
2 相关API①模板匹配介绍
R(x,y)=x′,y′∑(T(x′,y′)−I(x+x′,y+y′))2
R(x,y)=x′,y′∑(T(x′,y′)⋅I(x+x′,y+y′))
R(x,y)=x′,y′∑(T(x′,y′)⋅I(x+x′,y+y′))
T′(x′,y′)=T(x′,y′)−w⋅h1⋅xn,yn∑T(xn,yn)
I′(x+x′,y+y′)=I(x+x′,y+y′)−w⋅h1⋅xn,yn∑T(x+x′′,y+y′′)
R(x,y)=∑x′,y′T(x′,y′)2⋅∑x′,y′I(x+x′,y+y′)2∑x′,y′(T(x′,y′)−I(x+x′,y+y′))2
R(x,y)=∑x′,y′T(x′,y′)2⋅∑x′,y′I(x+x′,y+y′)2∑x′,y′(T(x′,y′)⋅I(x+x′,y+y′))2
R(x,y)=∑x′,y′T′(x′,y′)2⋅∑x′,y′I′(x+x′,y+y′)2∑x′,y′(T′(x′,y′)⋅I′(x+x′,y+y′))2②相关API
matchTemplate( InputArray image, //原图像,必须是8-bit或者32-bit浮点数图像 InputArray templ, //模板图像,类型与输入图像一致 OutputArray result, //输出结果,必须是单通道32位浮点数,假设原图像W*H,模板图像w*h,结果必须为W-w+1,H-h+1的大小 int method, //使用的匹配方法 InputArray mask=noArray() ) enum cv::TemplateMatchModes { cv::TM_SQDIFF = 0, cv::TM_SQDIFF_NORMED = 1, cv::TM_CCORR = 2, cv::TM_CCORR_NORMED = 3, cv::TM_CCOEFF = 4, cv::TM_CCOEFF_NORMED = 5 } minMaxLoc(src, minVal, maxVal, minLoc, maxLoc, mask) /* 在一个数组中找到全局最小值和全局最大值 minMaxLoc函数找到最小值和最大值元素值以及它们的位置。 */
③示例代码
#include <opencv2/opencv.hpp> #include <iostream> #include <math.h> using namespace std; using namespace cv; Mat src, temp, dst; int match_method = TM_SQDIFF; int max_track = 5; const char* INPUT_T = "input image"; const char* OUTPUT_T = "result image"; const char* match_t = "template match-demo"; void Match_Demo(int, void*); int main(int argc, char** argv) { // 待检测图像 src = imread("D:/vcprojects/images/flower.png"); // 模板图像 temp = imread("D:/vcprojects/images/t2.png"); if (src.empty() || temp.empty()) { printf("could not load image...n"); return -1; } namedWindow(INPUT_T, CV_WINDOW_AUTOSIZE); namedWindow(OUTPUT_T, CV_WINDOW_NORMAL); namedWindow(match_t, CV_WINDOW_AUTOSIZE); imshow(INPUT_T, temp); const char* trackbar_title = "Match Algo Type:"; createTrackbar(trackbar_title, OUTPUT_T, &match_method, max_track, Match_Demo); Match_Demo(0, 0); waitKey(0); return 0; } void Match_Demo(int, void*) { int width = src.cols - temp.cols + 1; int height = src.rows - temp.rows + 1; Mat result(width, height, CV_32FC1); matchTemplate(src, temp, result, match_method, Mat()); normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat()); Point minLoc; Point maxLoc; double min, max; src.copyTo(dst); Point temLoc; minMaxLoc(result, &min, &max, &minLoc, &maxLoc, Mat()); if (match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED) { temLoc = minLoc; } else { temLoc = maxLoc; } // 绘制矩形 rectangle(dst, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8); rectangle(result, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8); imshow(OUTPUT_T, result); imshow(match_t, dst); }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算