//【1】Mat变量定义
Mat midImage;//目标图的定义
//【2】转为灰度图并进行图像平滑
cvtColor(frame,midImage, CV_BGR2GRAY);//转化边缘检测后的图为灰度图
GaussianBlur( midImage, midImage, Size(9, 9), 2, 2 );
//【3】进行霍夫圆变换
vector
HoughCircles( midImage, circles, CV_HOUGH_GRADIENT,1.5, 10, 200, 100, 0, 0 );
//【4】依次在图中绘制出圆
for( size_t i = 0; i < circles.size(); i++ )
{
//参数定义
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
//绘制圆心
circle( frame, center, 3, Scalar(0,255,0), -1, 8, 0 );
//绘制圆轮廓
circle( frame, center, radius, Scalar(155,50,255), 3, 8, 0 );
//打印圆心坐标
printf("x = %d,y = %d\n",cvRound(circles[i][0]),cvRound(circles[i][1]));
}
//【5】显示效果图
namedWindow("效果");
imshow("效果", frame2);
c = cvWaitKey(30);
if (c == 27)//Esc键退出
{
break;
}
}
return 0;
}
/*----------------------------------------各参数的意思----------------------------------------
cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 );
InputArray src: 输入图像即要进行颜色空间变换的原图像,可以是Mat类
OutputArray dst: 输出图像即进行颜色空间变换后存储图像,也可以Mat类
int code: 转换的代码或标识,即在此确定将什么制式的图片转换成什么制式的图片
int dstCn = 0: 目标图像通道数,如果取值为0,则由src和code决定
cvThreshold(src, dst,120, 255, CV_THRESH_BINARY)
cvtColor(frame,midImage, CV_BGR2GRAY);//转化边缘检测后的图为灰度图
cvCvtColor (img, img1, CV_RGB2GRAY); //转为单通道
GaussianBlur( midImage, midImage, Size(9, 9), 2, 2 );
gaus = cv.GaussianBlur(img, (3, 3), 0)
C++: void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT )
参数解释:
. InputArray src: 输入图像,可以是Mat类型,图像深度为CV_8U、CV_16U、CV_16S、CV_32F、CV_64F。
. OutputArray dst: 输出图像,与输入图像有相同的类型和尺寸。
. Size ksize: 高斯内核大小,这个尺寸与前面两个滤波kernel尺寸不同,ksize.width和ksize.height可以不相同但是这两个值必须为正奇数,如果这两个值为0,他们的值将由sigma计算。
. double sigmaX: 高斯核函数在X方向上的标准偏差
. double sigmaY: 高斯核函数在Y方向上的标准偏差,如果sigmaY是0,则函数会自动将sigmaY的值设置为与sigmaX相同的值,如果sigmaX和sigmaY都是0,这两个值将由ksize.width和ksize.height计算而来。具体可以参考getGaussianKernel()函数查看具体细节。建议将size、sigmaX和sigmaY都指定出来。
. int borderType=BORDER_DEFAULT: 推断图像外部像素的某种便捷模式,有默认值BORDER_DEFAULT,如果没有特殊需要不用更改,具体可以参考borderInterpolate()函数。
为了能更直观的观察到四个变量对滤波的影响,建立四个轨迹条分别调节,所以最后运行结果图片有点丑,示例代码如下:
参数解释:
. InputArray src: 输入图像,图像为1、3、4通道的图像,当模板尺寸为3或5时,图像深度只能为CV_8U、CV_16U、CV_32F中的一个,如而对于较大孔径尺寸的图片,图像深度只能是CV_8U。
. OutputArray dst: 输出图像,尺寸和类型与输入图像一致,可以使用Mat::Clone以原图像为模板来初始化输出图像dst
. int ksize: 滤波模板的尺寸大小,必须是大于1的奇数,如3、5、7……
————————————————
版权声明:本文为CSDN博主「梧桐栖鸦」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/keith_bb/article/details/54426920
http://blog.sina.com.cn/s/blog_13fa7509b0102xhmk.html
laplace = cv2.Laplacian(gray, cv2.CV_8U, ksize=3)
sobel = cv2.Sobel(gray, cv2.CV_8U, 1, 1)
def Canny(image,threshold1,threshold2,edges=None,apertureSize=None,L2gradient=None)
threshold1:int类型的,低阈值
threshold2:int类型的,高阈值
edeges:单通道存储边缘的输出图像
apertureSize:Sobel算子内核(kSize)大小
L2gradiend:Bool类型的,为真表示使用更精确的L2范数进行计算(两个方向的倒数的平方再开放),为假表示用L1范数(直接将两个方向导数的绝对值相加)
Mat edges;
Canny(edges, edges, 40, 120, 3);
OpenCV Sobel()函数
复制代码
1 C++: void Sobel (
2 InputArray src,//输入图
3 OutputArray dst,//输出图
4 int ddepth,//输出图像的深度
5 int dx,
6 int dy,
7 int ksize=3,
8 double scale=1,
9 double delta=0,
10 int borderType=BORDER_DEFAULT );
复制代码
第一个参数,InputArray 类型的src,为输入图像,填Mat类型即可。
第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
第三个参数,int类型的ddepth,输出图像的深度,支持如下src.depth()和ddepth的组合:
若src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F
若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F
若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F
若src.depth() = CV_64F, 取ddepth = -1/CV_64F
第四个参数,int类型dx,x 方向上的差分阶数。
第五个参数,int类型dy,y方向上的差分阶数。
第六个参数,int类型ksize,有默认值3,表示Sobel核的大小;必须取1,3,5或7。
第七个参数,double类型的scale,计算导数值时可选的缩放因子,默认值是1,表示默认情况下是没有应用缩放的。
我们可以在文档中查阅getDerivKernels的相关介绍,来得到这个参数的更多信息。
第八个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
第九个参数, int类型的borderType,我们的老朋友了(万年是最后一个参数),边界模式,默认值为BORDER_DEFAULT。
这个参数可以在官方文档中borderInterpolate处得到更详细的信息。
一般情况下,都是用ksize x ksize内核来计算导数的。
然而,有一种特殊情况——当ksize为1时,往往会使用3 x 1或者1 x 3的内核。
且这种情况下,并没有进行高斯平滑操作。
Mat hline = getStructuringElement(MORPH_RECT, Size(dstImage.cols / 33, 1), Point(-1, -1));
Mat vline = getStructuringElement(MORPH_RECT, Size(1, dstImage.rows / 19), Point(-1, -1));
Mat rect = getStructuringElement(MORPH_RECT, Size(1, 1), Point(-1, -1));
erode(dstImage, temp, rect);
dilate(temp, dst1, rect);
dilate(const Mat &src, Mat &dst, Mat kernel, Point anchor=Point(-1,-1), int iterations=1)
利用opencv进行图像处理,提取椭圆圆心处理
写这个是因为项目正好在做这个,所以简单写写提取椭圆圆心坐标的代码,用的软件是VS。
首先介绍一下步骤,直接从图像处理开始
1,二值化处理(threhold())
2,高斯滤波(GaussianBlur())
3,轮廓提取(canny算子)
4,寻找闭合轮廓(findContours())
https://blog.csdn.net/hust_bochu_xuchao/article/details/52230694
上面介绍的是提取椭圆轮廓过程,下面介绍的是过滤干扰图像的过程,分三步,不过,这三部也不都是必须的,看个人需求:
1,像素点数量过滤(size)
2,面积过滤
3,长宽比过滤
代码如下,比较简单,就不过多介绍了,欢迎留言:
原文链接:https://blog.csdn.net/weixin_44540503/article/details/88597691
二值化:cvThreshold(src, src,120, 255, CV_THRESH_BINARY); // 二值化
cvThreshold
cvWaitKey(0);
cv::WaitKey(0);
#include
if (src->nChannels == 1) { dst = cvCloneImage (src); }
else
{
cvCvtColor (src, dst, CV_RGB2GRAY);
}
CvMemStorage* storage = cvCreateMemStorage (0); cvSmooth (dst, dst, CV_GAUSSIAN, 5, 5);
CvSeq* circles = cvHoughCircles (dst, storage, CV_HOUGH_GRADIENT, 2, dst->width / 3, 300, 100, 0, 200);
color = cvCreateImage (cvGetSize(src), IPL_DEPTH_8U, 3);
cvCvtColor (dst, color, CV_GRAY2RGB);
for (int i = 0; i < circles->total; i++) { float* p = (float*)cvGetSeqElem (circles, i);
CvPoint pt = cvPoint (cvRound(p[0]), cvRound(p[1]));
cvCircle (color, pt, cvRound(p[2]), CV_RGB(255, 0, 0), 3, 8, 0); }
cvNamedWindow ("src", 1);
cvShowImage ("src", src);
cvNamedWindow ("circle", 1);
cvShowImage ("circle", color);
cvWaitKey (0);
cvReleaseMemStorage (&storage);
cvReleaseImage (&src);
cvReleaseImage (&dst);
cvReleaseImage (&color); return 0;}
霍夫圆变换的函数为:
HoughCircles
利用 Hough 变换在灰度图像中找圆
CvSeq* cvHoughCircles( CvArr* image, void* circle_storage, int method, double dp, double min_dist, double param1=100, double param2=100, int min_radius=0, int max_radius=0 );
image
输入 8-比特、单通道灰度图像.
circle_storage
检测到的圆存储仓. 可以是内存存储仓 (此种情况下,一个线段序列在存储仓中被创建,并且由函数返回)或者是包含圆参数的特殊类型的具有单行/单列的CV_32FC3型矩阵(CvMat*). 矩阵头为函数所修改,使得它的 cols/rows 将包含一组检测到的圆。如果 circle_storage 是矩阵,而实际圆的数目超过矩阵尺寸,那么最大可能数目的圆被返回
. 每个圆由三个浮点数表示:圆心坐标(x,y)和半径.
method
Hough 变换方式,目前只支持CV_HOUGH_GRADIENT, which is basically 21HT, described in [Yuen03].
累加器图像的分辨率。这个参数允许创建一个比输入图像分辨率低的累加器。(这样做是因为有理由认为图像中存在的圆会自然降低到与图像宽高相同数量的范畴)。如果dp设置为1,则分辨率是相同的;如果设置为更大的值(比如2),累加器的分辨率受此影响会变小(此情况下为一半)。dp的值不能比1小。
Resolution of the accumulator used to detect centers of the circles. For example, if it is 1, the accumulator will have the same resolution as the input image, if it is 2 - accumulator will have twice smaller width and height, etc.
min_dist
该参数是让算法能明显区分的两个不同圆之间的最小距离。
Minimum distance between centers of the detected circles. If the parameter is too small, multiple neighbor circles may be falsely detected in addition to a true one. If it is too large, some circles may be missed.
param1
用于Canny的边缘阀值上限,下限被置为上限的一半。
The first method-specific parameter. In case of CV_HOUGH_GRADIENT it is the higher threshold of the two passed to Canny edge detector (the lower one will be twice smaller).
param2
累加器的阀值。
The second method-specific parameter. In case of CV_HOUGH_GRADIENT it is accumulator threshold at the center detection stage. The smaller it is, the more false circles may be detected. Circles, corresponding to the larger accumulator values, will be returned first.
min_radius
最小圆半径。
Minimal radius of the circles to search for.
max_radius
最大圆半径。
Maximal radius of the circles to search for. By default the maximal radius is set to max(image_width, image_height).
The function cvHoughCircles finds circles in grayscale image using some modification of Hough transform.
img1,
storage,
CV_HOUGH_GRADIENT,
1, //累加器图像的分辨率,增大则分辨率变小
18, //很重要的一个参数,告诉两个圆之间的距离的最小距离,如果已知一副图像,可以先行计
//算出符合自己需要的两个圆之间的最小距离。
100, //canny算法的阈值上限,下限为一半(即100以上为边缘点,50以下抛弃,中间视是否相连而//定)
25, //决定成圆的多寡 ,一个圆上的像素超过这个阈值,则成圆,否则丢弃
32,//最小圆半径,这个可以通过图片确定你需要的圆的区间范围
45 //最大圆半径
);
img2 = cvCreateImage (cvGetSize(img), IPL_DEPTH_8U, 3); //用一个三通道的图片来显示红色的
https://blog.csdn.net/weixin_41695564/article/details/80099917
https://blog.csdn.net/MnisRain/article/details/82048840?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.nonecase
https://blog.csdn.net/weixin_44540503/article/details/88597691
https://blog.csdn.net/gdut2015go/article/details/46430699
定义:Vec2b,Vec3b,Vec2s,Vec3s
//【1】向量模板类Vec的实例化,并且给相应实例的Vec向量模板类实例---指定新的名字
//【1】Vec2b--这是一个具体的--类类型---这个类类型实例话的类对象表示如下所示:
//【1】Vec2b---表示每个Vec2b对象中,可以存储2个char(字符型)数据
typedef Vec
//【2】Vec3b---表示每一个Vec3b对象中,可以存储3个char(字符型)数据,比如可以用这样的对象,去存储RGB图像中的一个像素点
typedef Vec
//【3】Vec4b---表示每一个Vec4b对象中,可以存储4个字符型数据,可以用这样的类对象去存储---4通道RGB+Alpha的图像中的像素点
typedef Vec
//【1】Vec2s---表示这个类的每一个类对象,可以存储2个short int(短整型)的数据
typedef Vec
typedef Vec
vector<Vec3f> pcircles;
Point center((pcircles[i][0]), (pcircles[i][1]));圆心 cvRound 返回和参数最接近的整数值
int radius = (pcircles[i][2]); //提取半径
v.resize(3); /*reserve表示容器预留空间,但并不是真正的创建对象,需要通过insert()或push_back()等创建对象,默认对象为0*/
for (int i = 0; i < v.size(); i++)
v[i] = i;
v.resize(5) /*resize容器v的大小为5,前三个初始化的值不变,0/1/2,后面的默认为0*/
v.size() /*v的size为5*/
v.push_back(6) /*在v的最后面添加一个6*/
v.size() /* v的size为6,v的值分别是0/1/2/0/0/6 */
对于vector的全体排序,我们知道sort(vv.begin(),vv.end())来进行的。
Scalar(0,0,255))
CvScalar color = CV_RGB(255,0,0);是什么意思,其中color是自己定义的吗?
是自己定义的,你可以随便写,但是一般都用color,为了便于认知。在Opencv中,cvScalar是CV_RGB的宏,cvScalar的储存顺序是B-G-R,而CV_RGB的储存顺序是R-G-B,两者正好相反,所以你的cvScalar(255,0,0),实际意思是B=255,当然是蓝色的
————————————————
版权声明:本文为CSDN博主「zqx951102」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zqx951102/article/details/82797484
操作 例子(3可以换成2)
默认构造方法 cv::Point3i p;
拷贝构造方法 cv::Point3f p2( p1 );
带初始化值的构造方法 cv::Point3d p( x0, x1, x2 );
转换到固定向量类 (cv::Vec3f) p;
成员访问 p.x; p.y;p.z(2的时候没有z)
点积操作 float x = p1.dot( p2 )
双精度点积操作 double x = p1.ddot( p2 )
矢量积操作 p1.cross( p2 )(只针对3维point)
判断point是否在矩阵r中 p.inside( r )(只针对2维point)
————————————————
版权声明:本文为CSDN博主「yuanCruise」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qiu931110/article/details/85174246
Point(int x, int y) //建構式
Point pt1(20,30);
Point pt2;
pt2.x = 20;
pt2.y = 30;
Rect:矩形類別,成員有x、y、width、height,分別表示左上角頂點的x座標,左上角頂點的y座標,矩形寬、矩形高,可用area()函式得到面積,以下為建構式和最基本的兩種賦值方法:
Rect(int x, int y, int width, int height) //建構式
Rect rect1(20,30,150,100);
Rect rect2;
rect2.x = 20;
rect2.y = 30;
rect2.width = 150;
rect2.height = 100;
int myRectArea = rect2.area();
Size:尺寸類別,成員有width和height,分別表示寬和長(int型態),可用area()函式得到面積,以下為建構式最基本兩種賦值方法:
Size(int width, int height) //建構式
Size size1(150, 100);
Size size2;
size2.width = 150;
size2.height = 100;
int myArea = size2.area();
Size2f:尺寸類別,和Size用法雷同,只是width和height為float型態。
RotatedRect:斜矩形類別,成員有矩形的質心center(Point2f類別),四周長size(Size2f類別)、旋轉角度angle(float類別),可用points()函式得到四個頂點,以下為建構式和最基本的兩種賦值方法:
RotatedRect(const Point2f ¢er, const Size2f &size, float angle) //建構式
RotatedRect rRect1(Point2f(150,150), Size2f(100,50), 30.0);
RotatedRect rRect2;
rRect2.center = Point2f(150,150);
rRect2.size = Size2f(100,50);
rRect2.angle = 30.0;
Point2f vertices[4];
rRect2.points(vertices);
Mat rawImg(600, 500, CV_8U, Scalar(0)); //这个Scalar函数有啥作用呢?,我们我猜想是灰度值 ,0是全黑图。255是全白。
//Mat resultImg;
namedWindow("Raw Image");
imshow("Raw Image", rawImg);
waitKey(0);
destroyAllWindows();
imwrite("图像.jpg",rawImg);
Mat rawImg(600, 500, CV_8UC3, Scalar(255, 0, 0)); 彩色3单通道图
https://www.cnblogs.com/Jack-Lee/p/3652957.html
cv::Mat mz = cv::Mat::zeros(cv::Size(5,5),CV_8UC1); // 全零矩阵
cv::Mat mo = cv::Mat::ones(cv::Size(5,5),CV_8UC1); // 全1矩阵
cv::Mat me = cv::Mat::eye(cv::Size(5,5),CV_32FC1); // 对角线为1的对角矩阵