精华内容
下载资源
问答
  • 检测图中多个四边形的四个角点 /* 工程在69那个例程文件目录 检测四边形轮廓以及角点 */ #include <opencv.hpp> #include <iostream> #include&...

    检测图中多个四边形的四个角点

    原图:

    检测后效果图

    /*
    工程在69那个例程文件目录
    
    检测四边形轮廓以及角点
    */
    
    
    
    
    
    
    
    
    
    #include <opencv.hpp>  
    #include <iostream>  
    #include<time.h>
    #include<math.h>
    #include <iostream>  
    #include <set>
    using namespace cv;
    using namespace std;
    
    RNG rng(12345);
    
    float getDistance(CvPoint pointO, CvPoint pointA);
    float getAngle(CvPoint pointM, CvPoint pointL, CvPoint pointR);
    int main()
    {
    	Mat srcImage = Mat::zeros(600, 800, CV_8UC3);
    	Mat srcImage0 = imread("10.jpg", 0);
    	resize(srcImage0, srcImage, srcImage.size());
    	srcImage = srcImage > 200;//二值化
    
    	imshow("原图", srcImage);
    	//getStructuringElement函数会返回指定形状和尺寸的结构元素
    	Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
    	//morphologyEx(srcImage, srcImage, MORPH_CLOSE, element);//闭运算滤波
    	vector<vector<Point>> contours, RectContours;//轮廓,为点向量,新的轮廓
    	findContours(srcImage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);//找轮廓
    	vector<vector<Point>> hull(contours.size());//用于存放凸包
    	Mat drawing(srcImage.size(), CV_8UC3, cv::Scalar(0));
    	int i = 0;
    	vector<float> length(contours.size());//用于保存每个轮廓的长度
    	vector<float> Area_contours(contours.size()), Area_hull(contours.size()), Rectangularity(contours.size()), circularity(contours.size());
    	for (i = 0; i < contours.size(); i++)
    	{//把所有的轮廓画出来
    		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
    		length[i] = arcLength(contours[i], true);//轮廓的长度
    		if (length[i] >200 && length[i] <2000)
    		{//通过长度匹配滤除小轮廓
    			convexHull(Mat(contours[i]), hull[i], false);//把凸包找出来,寻找凸包函数
    			Area_contours[i] = contourArea(contours[i]);   //轮廓面积
    			Area_hull[i] = contourArea(hull[i]);           //凸包面积
    			Rectangularity[i] = Area_contours[i] / Area_hull[i]; //矩形度
    			circularity[i] = (4 * 3.1415*Area_contours[i]) / (length[i] * length[i]);//圆形度
    			if (Rectangularity[i]>0.9&&circularity[i]<0.7)
    			{//通过矩形度和圆形度滤除数字
    				//drawContours(drawing, contours, i, Scalar(255, 255, 255), 1);
    				RectContours.push_back(hull[i]);//把提取出来的方框导入到新的轮廓组
    				drawContours(drawing, hull, i, color, 1);//得到方框
    			}
    		}
    	}
    	float distance = 0, distanceMax = 0;
    	Point connorPoint1, connorPoint2, connorPoint3, connorPoint4;
    	int j = 0, k = 0;
    	vector<float>Theta(30);
    	vector<Point>ConnorPoint(4);
    	for (k = 0; k < RectContours.size(); k++)
    	{//历遍每个轮廓找角点
    		j = 0;
    		for (i = 0; i < RectContours[k].size(); i++)
    		{//历遍当个轮廓各点间夹角
    			if (i == 0)
    			{
    				Theta[i] = getAngle(RectContours[k][i], RectContours[k][RectContours[k].size() - 1], RectContours[k][i + 1]);
    			}
    			else if (i == RectContours[k].size() - 1)
    			{
    				Theta[i] = getAngle(RectContours[k][i], RectContours[k][i - 1], RectContours[k][0]);
    			}
    			else
    			{
    				Theta[i] = getAngle(RectContours[k][i], RectContours[k][i - 1], RectContours[k][i + 1]);
    			}
    			if (Theta[i] / 3.1415 * 180 < 170)
    			{//两点间夹角小于170度
    				if (getDistance(RectContours[k][i], ConnorPoint[0])>10 && getDistance(RectContours[k][i], ConnorPoint[1])>10
    					&& getDistance(RectContours[k][i], ConnorPoint[2])>10 && getDistance(RectContours[k][i], ConnorPoint[3])>10)
    				{//新找到的角点与已经保存的角点间距离要大于10
    					ConnorPoint[j] = RectContours[k][i]; //四个角点
    				//	circle(drawing, RectContours[k][i], 3, Scalar(255, 255, 255), FILLED, LINE_AA);
    					circle(drawing, ConnorPoint[j], 3, Scalar(255, 255, 255), FILLED, LINE_AA);
    					//每个四边形的角点显示逻辑这里还是有些问题
    					cout << "\n轮廓 " << j << "  的四个角点坐标分别为:\n" << ConnorPoint[0] << ConnorPoint[1] << ConnorPoint[2] << ConnorPoint[3] << endl;
    					j++;
    				}
    			}
    
    		}
    	}
    
    	
    	for (int i = 0; i < ConnorPoint.size(); i++)
    	{
    		cout << "\n\t\t毛哥好\n" << endl;
    	}
    		
    
    
    	imshow("轮廓", drawing);
    	/********透视变换过程*************************************************************************/
    	检测是否是四边形,很多图片检测不到
    	//	if (approx.size() != 4)
    	//	{
    	//		std::cout << "The object is not quadrilateral(四边形)!" << std::endl;
    	//		return -1;
    	//	}
    	//	//get mass center  寻找四边形中点
    	//	for (unsigned int i = 0; i < corners.size(); i++)
    	//	{
    	//		center += corners[i];
    	//	}
    	//	center *= (1. / corners.size());
    	//
    	//	//确定四个点的中心线
    	//	sortCorners(corners, center);
    	//
    	//	cv::Mat dst = src.clone();
    	//
    	//	//Draw Lines  画直线
    	//	for (unsigned int i = 0; i<lines.size(); i++)
    	//	{
    	//		cv::Vec4i v = lines[i];
    	//		cv::line(dst, cv::Point(v[0], v[1]), cv::Point(v[2], v[3]), CV_RGB(0, 255, 0));    //目标版块画绿线   
    	//	}
    	//
    	//	//draw corner points  画角点
    	//	cv::circle(dst, corners[0], 3, CV_RGB(255, 0, 0), 2);
    	//	cv::circle(dst, corners[1], 3, CV_RGB(0, 255, 0), 2);
    	//	cv::circle(dst, corners[2], 3, CV_RGB(0, 0, 255), 2);
    	//	cv::circle(dst, corners[3], 3, CV_RGB(255, 255, 255), 2);
    	//
    	//	//draw mass center  画出四边形中点
    	//	cv::circle(dst, center, 3, CV_RGB(255, 255, 0), 2);
    	//
    	//	cv::Mat quad = cv::Mat::zeros(300, 220, CV_8UC3);//设定校正过的图片从320*240变为300*220  
    	//
    	//	//corners of the destination image  
    	//	std::vector<cv::Point2f> quad_pts;
    	//	quad_pts.push_back(cv::Point2f(0, 0));
    	//	quad_pts.push_back(cv::Point2f(quad.cols, 0));//(220,0)  
    	//	quad_pts.push_back(cv::Point2f(quad.cols, quad.rows));//(220,300)  
    	//	quad_pts.push_back(cv::Point2f(0, quad.rows));
    	//
    	//	// Get transformation matrix  
    	//	cv::Mat transmtx = cv::getPerspectiveTransform(corners, quad_pts);   //求源坐标系(已畸变的)与目标坐标系的转换矩阵  
    	//
    	//	// Apply perspective transformation透视转换  
    	//	cv::warpPerspective(src, quad, transmtx, quad.size());
    
    	//	cv::namedWindow("image", 0);
    	//	cv::imshow("image", dst);
    	//
    	//	cv::namedWindow("quadrilateral", 0);
    	//	cv::imshow("quadrilateral", quad);
    
    
    	waitKey(0);
    	return 0;
    }
    
    
    
    
    
    float getDistance(CvPoint pointO, CvPoint pointA)
    {//求两点之间距离
    	float distance;
    	distance = powf((pointO.x - pointA.x), 2) + powf((pointO.y - pointA.y), 2);
    	distance = sqrtf(distance);
    
    	return distance;
    }
    
    float getAngle(CvPoint pointM, CvPoint pointL, CvPoint pointR)
    {//求三点之间的夹角
    	CvPoint L, R;
    	float dist_L, dist_R, Theta;
    	L.x = pointL.x - pointM.x;
    	L.y = pointL.y - pointM.y;
    	R.x = pointR.x - pointM.x;
    	R.y = pointR.y - pointM.y;
    	dist_L = getDistance(pointL, pointM);
    	dist_R = getDistance(pointR, pointM);
    	Theta = acos((L.x*R.x + L.y*R.y) / (dist_L*dist_R));
    	return Theta;
    }
    
    展开全文
  • 检测四边形轮廓以及角点 */ /*晚上调好模板匹配以及透视变换,再试试OCR库 */ #pragma warning(disable:4996) // #include &amp;lt;opencv.hpp&amp;gt; #include &amp;lt;opencv2/video.hpp...

    这里写图片描述

    /*
    工程在69那个例程文件目录
    
    检测四边形轮廓以及角点
    */
    
    
    /*晚上调好模板匹配以及透视变换,再试试OCR库
    
    
    */
    
    
    #pragma warning(disable:4996)
    
    
    
    
    //
    
    #include <opencv.hpp>  
    #include <opencv2/video.hpp>
    #include <opencv2/imgPRoc//imgproc.hpp>
    #include <opencv2/ml/ml.hpp>
    #include <opencv2/imgproc/imgproc.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    
    #include <iostream>  
    #include<time.h>
    #include<math.h>
    #include <set>
    
    
    using namespace cv;
    using namespace std;
    
    
    
    //-----------------------------------【命名空间声明部分】--------------------------------------
    //          描述:包含程序所使用的命名空间
    //-----------------------------------------------------------------------------------------------
    using namespace cv;
    using namespace std;
    
    
    RNG rng(12345);
    
    float getDistance(CvPoint pointO, CvPoint pointA);
    float getAngle(CvPoint pointM, CvPoint pointL, CvPoint pointR);
    
    float getDist_P2L(CvPoint pointP, CvPoint pointA, CvPoint pointB);
    int list_connor(int i1, int i2, int i3);
    
    
    
    
    //-----------------------------------【全局函数声明部分】--------------------------------------
    //   描述:全局函数的声明
    //-----------------------------------------------------------------------------------------------
    static void ShowHelpText();
    
    
    //-----------------------------------【main( )函数】--------------------------------------------
    //   描述:控制台应用程序的入口函数,我们的程序从这里开始执行
    //-----------------------------------------------------------------------------------------------
    
    int main()
    {
        int iiii = 1000;
        int n = 1;//保存图片名称末尾
    
        int geshu = 0;
        Mat frame;
        Mat srcImage = Mat::zeros(600, 800, CV_8UC3);
        //【0】显示欢迎和帮助文字
        ShowHelpText();
    
        char strangerName[2000];//截取的四边形矩形图片名字
        //定义一些参数3
        Mat threshold_output;
        vector<vector<Point>> contours;
        vector<Vec4i> hierarchy;
    
    
    
        //【1】从摄像头读入视频
        VideoCapture capture(1);  //该参数为0,则打开计算机自带摄像头,如果为1则打开外置USB摄像头
    
    
        //capture.set(CAP_PROP_FRAME_WIDTH, 1920.0);//设置摄像头采集图像分辨率
       //  capture.set(CAP_PROP_FRAME_HEIGHT, 1080.0);
    
    
    
        while (1)
        {
    
    
            iiii++;
    
    
    
    
    
            //隔一段时间保存一张图片
            if (iiii >= 500)//通过改变i后面的值来刷新图片界面
            {
                clock_t start = clock();
                iiii = 0;
                capture >> frame;// //读取当前帧,capture >> frame与capture.read(frame)功能一样,
                if (frame.empty())
                {
                    return 0;
                }
                char* cstr = new char[120];
    
    
    
                //Mat srcImage0 = imread("10.jpg", 0);
                resize(frame, srcImage, srcImage.size());
            //  srcImage = srcImage > 200;//二值化
    
    
    
                //灰度化
                cvtColor(srcImage, srcImage, CV_BGR2GRAY);//灰度化
    
                //二值化
                  threshold(srcImage, srcImage, 200, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
    
    
    
    
    
    
    
                  namedWindow("原图", 1);
                imshow("原图", srcImage);
                waitKey(30);
                //getStructuringElement函数会返回指定形状和尺寸的结构元素
                Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
                //morphologyEx(srcImage, srcImage, MORPH_CLOSE, element);//闭运算滤波
                vector<vector<Point>> contours, RectContours;//轮廓,为点向量,
                findContours(srcImage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);//找轮廓
                vector<vector<Point>> hull(contours.size());//用于存放凸包
                Mat drawing(srcImage.size(), CV_8UC3, cv::Scalar(0));
                int i = 0;
                vector<float> length(contours.size());//用于保存每个轮廓的长度
                vector<float> Area_contours(contours.size()), Area_hull(contours.size()), Rectangularity(contours.size()), circularity(contours.size());
                for (i = 0; i < contours.size(); i++)
                {//把所有的轮廓画出来
                    Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
                    length[i] = arcLength(contours[i], true);//轮廓的长度
                    if (length[i] >200 && length[i] <2000)
                    {//通过长度匹配滤除小轮廓
                        convexHull(Mat(contours[i]), hull[i], false);//把凸包找出来,寻找凸包函数
                        Area_contours[i] = contourArea(contours[i]);   //轮廓面积
                        Area_hull[i] = contourArea(hull[i]);           //凸包面积
                        Rectangularity[i] = Area_contours[i] / Area_hull[i]; //矩形度
                        circularity[i] = (4 * 3.1415*Area_contours[i]) / (length[i] * length[i]);//圆形度
                        //drawContours(drawing, contours, i, color, 1);//得到方框
    
                        if (Rectangularity[i]>0.8&&circularity[i]<0.95)
                        {//通过矩形度和圆形度滤除数字
                            //drawContours(drawing, contours, i, Scalar(255, 255, 255), 1);
                            RectContours.push_back(hull[i]);//把提取出来的方框导入到新的轮廓组
                            drawContours(drawing, hull, i, color, 1);//得到四边形
    
    
                        }
                    }
                }
                /**********************     自己添加的用于切割四边形     **************************************************************************************************************/
                /**********************     自己添加的     **************************************************************************************************************/
    
                // 多边形逼近轮廓 + 获取矩形和圆形边界框
                vector<vector<Point> > contours_poly(RectContours.size());
                vector<Rect> boundRect(RectContours.size()); //最小矩形
                vector<Point2f>center(RectContours.size()); //圆心
                vector<float>radius(RectContours.size()); //半径
    
                //一个循环,遍历所有部分,进行本程序最核心的操作
                for (unsigned int i = 0; i < RectContours.size(); i++)
                {
                    approxPolyDP(RectContours[i], contours_poly[i], 3, true);//用指定精度逼近多边形曲线 
                    boundRect[i] = boundingRect(Mat(contours_poly[i]));//计算点集的最外面(up-right)矩形边界
                    minEnclosingCircle(contours_poly[i], center[i], radius[i]);//对给定的 2D点集,寻找最小面积的包围圆形 
                }
    
                // 绘制多边形轮廓 + 包围的矩形框 + 圆形框
                Mat drawing1 = Mat::zeros(srcImage.size(), CV_8UC3);
    
                Mat image_cut[100];      //从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy  
                Mat image_copy[100];   //clone函数创建新的图片 
                int geshu = 0;
                for (int unsigned i = 0; i < RectContours.size(); i++)
                {
    
                    Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));//随机设置颜色
                    //drawContours(drawing1, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point());//绘制轮廓
                    Point text_lb;//中点
    
    
                    //circle(drawing, center[i], (int)radius[i], color, 2, 8, 0);//绘制圆
                    //if (radius[i]<39 && radius[i]>20 && center[i].y>300 && center[i].x>200 && center[i].x<400)
                    //if (radius[i]<39 && radius[i]>20 && center[i].y>300 && center[i].x>350 && center[i].x<400)
                    //中间下面的点
                    //  if (radius[i]<39 && radius[i]>20 && center[i].y > 200 && center[i].x > 100 && center[i].x < 650)
                    //{
                    geshu++;
                    rectangle(drawing1, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);//绘制矩形
                    text_lb = Point((boundRect[i].tl().x + boundRect[i].br().x)*0.5, (boundRect[i].tl().y + boundRect[i].br().y)*0.5);
                    //putTextZH(drawing, "中点", center[i], Scalar(0, 0, 255), 10, "Arial");
                    int width = abs(boundRect[i].tl().x - boundRect[i].br().x);
                    int height = abs(boundRect[i].tl().y - boundRect[i].br().y);
    
    
    
                    Rect rect(boundRect[i].tl().x, boundRect[i].tl().y, width, height);   //创建一个Rect框,属于cv中的类,四个参数代表x,y,width,height  
    
                    image_cut[i] = Mat(srcImage, rect);      //从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy  
                    image_copy[i] = image_cut[i].clone();   //clone函数创建新的图片  
                    sprintf_s(strangerName, "数字%d", geshu);
                    namedWindow(strangerName, 0);//参数为零,则可以自由拖动strangerName
                    imshow(strangerName, image_copy[i]);
    
    
    
    
                    //}
    
                }
    
                namedWindow("找到四边形外接矩形", 1);
                imshow("找到四边形外接矩形", drawing1);
                waitKey(30);
    
                ///****************************************************************************************************************************************/
                ///****************************************************************************************************************************************/
    
    
    
                float distance = 0, distanceMax = 0;
                Point connorPoint1, connorPoint2, connorPoint3, connorPoint4, point_add;
                vector<Point> connor4_add(3);  //先找到的三个角点
                int conP_i1, conP_i2, conP_i3, conP_i_add;
                int j = 0, flag = 0;
    
                Point  finally_contours[80][4];//轮廓,为点向量,新的轮廓
                for (j = 0; j < RectContours.size(); j++)  //四边形轮廓个数
                {
                    distance = 0;
                    distanceMax = 0;
                    for (i = 0; i < RectContours[j].size(); i++) //每个轮廓点的个数11到19点不等
                    {//找第一个角点
                        distance = getDistance(RectContours[j][i], RectContours[j][0]);
                        if (distance>distanceMax)
                        {
                            distanceMax = distance;
                            connorPoint1 = RectContours[j][i]; //第一个角点
                            conP_i1 = i;
                        }
                    }
                    distance = 0;
                    distanceMax = 0;
                    for (i = 0; i < RectContours[j].size(); i++)
                    {//找第二个角点
                        distance = getDistance(RectContours[j][i], connorPoint1);
                        if (distance>distanceMax)
                        {
                            distanceMax = distance;
                            connorPoint2 = RectContours[j][i]; //第二个角点
                            conP_i2 = i;
                        }
                    }
                    distance = 0;
                    distanceMax = 0;
                    for (i = 0; i < RectContours[j].size(); i++)
                    {//找第三个角点
                        distance = getDistance(RectContours[j][i], connorPoint1) + getDistance(RectContours[j][i], connorPoint2);
                        if (distance>distanceMax)
                        {
                            distanceMax = distance;
                            connorPoint3 = RectContours[j][i]; //第三个角点
                            conP_i3 = i;
                        }
                    }
                    flag = list_connor(conP_i1, conP_i2, conP_i3);//对三个角点由大到小排序
                    switch (flag)
                    {//对三个角点排序
                    case 0:break;
                    case 123:break;
                    case 132:point_add = connorPoint2; connorPoint2 = connorPoint3; connorPoint3 = point_add; break;//2,3交换
                    case 213:point_add = connorPoint1; connorPoint1 = connorPoint2; connorPoint2 = point_add; break;//1,2交换
                    case 231:point_add = connorPoint1; connorPoint1 = connorPoint2; connorPoint2 = point_add;
                        point_add = connorPoint2; connorPoint2 = connorPoint3; connorPoint3 = point_add; break;//1,2交换+2,3交换
                    case 321:point_add = connorPoint3; connorPoint3 = connorPoint1; connorPoint1 = point_add; break;//1,3交换
                    case 312:point_add = connorPoint3; connorPoint3 = connorPoint1; connorPoint1 = point_add;
                        point_add = connorPoint2; connorPoint2 = connorPoint3; connorPoint3 = point_add; break;//1,3交换+2,3交换
                    }
                    switch (flag)
                    {//对三个角点排序
                    case 0:break;
                    case 123:break;
                    case 132:conP_i_add = conP_i2; conP_i2 = conP_i3; conP_i3 = conP_i_add; break;//2,3交换
                    case 213:conP_i_add = conP_i1; conP_i1 = conP_i2; conP_i2 = conP_i_add; break;//1,2交换
                    case 231:conP_i_add = conP_i1; conP_i1 = conP_i2; conP_i2 = conP_i_add;
                        conP_i_add = conP_i2; conP_i2 = conP_i3; conP_i3 = conP_i_add; break;//1,2交换+2,3交换
                    case 321:conP_i_add = conP_i3; conP_i3 = conP_i1; conP_i1 = conP_i_add; break;//1,3交换
                    case 312:conP_i_add = conP_i3; conP_i3 = conP_i1; conP_i1 = conP_i_add;
                        conP_i_add = conP_i2; conP_i2 = conP_i3; conP_i3 = conP_i_add; break;//1,3交换+2,3交换
                    }
                    distance = 0;
                    distanceMax = 0;
                    for (i = conP_i3; i < conP_i2; i++)
                    {//相隔两角点之间找到怀疑是4角点的点
                        distance = getDistance(RectContours[j][i], connorPoint3) + getDistance(RectContours[j][i], connorPoint2);
                        if (distance>distanceMax)
                        {
                            distanceMax = distance;
                            connor4_add[0] = RectContours[j][i];
                        }
                    }
                    distance = 0;
                    distanceMax = 0;
                    for (i = conP_i2; i < conP_i1; i++)
                    {//相隔两角点之间找到怀疑是4角点的点
                        distance = getDistance(RectContours[j][i], connorPoint1) + getDistance(RectContours[j][i], connorPoint2);
                        if (distance>distanceMax)
                        {
                            distanceMax = distance;
                            connor4_add[1] = RectContours[j][i];
                        }
                    }
                    distance = 0;
                    distanceMax = 0;
                    for (i = conP_i1; i < RectContours[j].size() + conP_i3; i++)
                    {//相隔两角点之间找到怀疑是4角点的点
                        if (i< RectContours[j].size())
                        {
                            distance = getDistance(RectContours[j][i], connorPoint1) + getDistance(RectContours[j][i], connorPoint3);
                            if (distance>distanceMax)
                            {
                                distanceMax = distance;
                                connor4_add[2] = RectContours[j][i];
                            }
                        }
                        else
                        {
                            distance = getDistance(RectContours[j][i - RectContours[j].size()], connorPoint1) + getDistance(RectContours[j][i - RectContours[j].size()], connorPoint3);
                            if (distance>distanceMax)
                            {
                                distanceMax = distance;
                                connor4_add[2] = RectContours[j][i - RectContours[j].size()];
                            }
                        }
                    }
                    if (getDist_P2L(connor4_add[0], connorPoint3, connorPoint2)>10)
                    {
                        connorPoint4 = connor4_add[0];
                    }
                    else if (getDist_P2L(connor4_add[1], connorPoint2, connorPoint1)>10)
                    {
                        connorPoint4 = connor4_add[1];
                    }
                    else if (getDist_P2L(connor4_add[2], connorPoint1, connorPoint3)>10)
                    {
                        connorPoint4 = connor4_add[2];
                    }
    
                    circle(drawing, connorPoint1, 3, Scalar(255, 255, 255), FILLED, LINE_AA);
                    circle(drawing, connorPoint2, 3, Scalar(255, 255, 255), FILLED, LINE_AA);
                    circle(drawing, connorPoint3, 3, Scalar(255, 255, 255), FILLED, LINE_AA);
                    circle(drawing, connorPoint4, 3, Scalar(255, 255, 255), FILLED, LINE_AA);
    
                    finally_contours[j][0] = connorPoint1;
                    finally_contours[j][1] = connorPoint2;
                    finally_contours[j][2] = connorPoint3;
                    finally_contours[j][3] = connorPoint4;
    
                    cout << "\n轮廓 " << j + 1 << "  的四个角点坐标分别为:\n" << finally_contours[j][0] << finally_contours[j][1] << finally_contours[j][2] << finally_contours[j][3] << endl;
    
                }
    
    
                namedWindow("轮廓", 1);
                imshow("轮廓", drawing);
    
                clock_t ends = clock();
    
                cout << "Running Time : " << (double)(ends - start) / CLOCKS_PER_SEC << endl;
    
    
            }
    
        }
    
        return 0;
    }
    
    
    
    
    float getDist_P2L(CvPoint pointP, CvPoint pointA, CvPoint pointB)
    {//点到直线的距离:P到AB的距离
        //求直线方程
        int A = 0, B = 0, C = 0;
        A = pointA.y - pointB.y;
        B = pointB.x - pointA.x;
        C = pointA.x*pointB.y - pointA.y*pointB.x;
        //代入点到直线距离公式
        float distance = 0;
        distance = ((float)abs(A*pointP.x + B*pointP.y + C)) / ((float)sqrtf(A*A + B*B));
        return distance;
    }
    
    
    //对角点进行排序,因为之前检测出的轮廓是带序号的
    int list_connor(int i1, int i2, int i3)
    {//排序
        int flag = 0;
        Point point_add;
        if (i1 >= i2&&i2 >= i3)
            flag = 123;
        else if (i1 >= i3&& i3 >= i2)
            flag = 132;
        else if (i2 >= i1&&i1 >= i3)
            flag = 213;
        else if (i2 >= i3&&i3 >= i1)
            flag = 231;
        else if (i3 >= i2&&i2 >= i1)
            flag = 321;
        else if (i3 >= i1&&i1 >= i2)
            flag = 312;
        return flag;
    }
    
    
    
    float getDistance(CvPoint pointO, CvPoint pointA)
    {//求两点之间距离
        float distance;
        distance = powf((pointO.x - pointA.x), 2) + powf((pointO.y - pointA.y), 2);
        distance = sqrtf(distance);
    
        return distance;
    }
    
    float getAngle(CvPoint pointM, CvPoint pointL, CvPoint pointR)
    {//求三点之间的夹角
        CvPoint L, R;
        float dist_L, dist_R, Theta;
        L.x = pointL.x - pointM.x;
        L.y = pointL.y - pointM.y;
        R.x = pointR.x - pointM.x;
        R.y = pointR.y - pointM.y;
        dist_L = getDistance(pointL, pointM);
        dist_R = getDistance(pointR, pointM);
        Theta = acos((L.x*R.x + L.y*R.y) / (dist_L*dist_R));
        return Theta;
    }
    
    
    
    
    
    //-----------------------------------【ShowHelpText( )函数】----------------------------------  
    //      描述:输出一些帮助信息  
    //----------------------------------------------------------------------------------------------  
    static void ShowHelpText()
    {
        //输出欢迎信息和OpenCV版本
        printf("\n\n\t\t\t检测四边形角点\n");
        printf("\n\n\t\t\t   当前使用的OpenCV版本为:" CV_VERSION);
        printf("\n\n  ----------------------------------------------------------------------------\n");
    
        //输出一些帮助信息  
        printf("\n\n\n\t毛哥好\n\n");
        printf("\n\n\t按键操作说明: \n\n"
            "\t\t键盘按键【ESC】- 退出程序\n\n"
            "\t\t毛哥2018/5/24\n\n");
    }
    
    
    
    展开全文
  • 2017_2018学年八年级数学下册第6章平行四边形课题1平行四边形角特征当堂检测课件新版北师大版
  • 检测四边形轮廓以及角点,新版 */ #include &lt;opencv.hpp&gt; #include &lt;iostream&gt; #include&lt;time.h&gt; #include&lt;math.h&gt; #include &lt;iostre.....

    这里写图片描述

    这里写图片描述

    这里写图片描述

    效果很不错,至于原理,以后再慢慢整理一下,最近太忙。

    
    工程在69那个例程文件目录!
    检测四边形轮廓以及角点,新版
    */
    
    
    
    
    
    
    
    
    
    #include <opencv.hpp>  
    #include <iostream>  
    #include<time.h>
    #include<math.h>
    #include <iostream>  
    #include <set>
    using namespace cv;
    using namespace std;
    
    RNG rng(12345);
    
    float getDistance(CvPoint pointO, CvPoint pointA);
    float getAngle(CvPoint pointM, CvPoint pointL, CvPoint pointR);
    
    float getDist_P2L(CvPoint pointP, CvPoint pointA, CvPoint pointB);
    int list_connor(int i1, int i2, int i3);
    int main()
    {
    	Mat srcImage = Mat::zeros(600, 800, CV_8UC3);
    	Mat srcImage0 = imread("10.jpg", 0);
    	resize(srcImage0, srcImage, srcImage.size());
    	srcImage = srcImage > 200;//二值化
    
    	imshow("原图", srcImage);
    	//getStructuringElement函数会返回指定形状和尺寸的结构元素
    	Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
    	//morphologyEx(srcImage, srcImage, MORPH_CLOSE, element);//闭运算滤波
    	vector<vector<Point>> contours, RectContours;//轮廓,为点向量,
    	findContours(srcImage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);//找轮廓
    	vector<vector<Point>> hull(contours.size());//用于存放凸包
    	Mat drawing(srcImage.size(), CV_8UC3, cv::Scalar(0));
    	int i = 0;
    	vector<float> length(contours.size());//用于保存每个轮廓的长度
    	vector<float> Area_contours(contours.size()), Area_hull(contours.size()), Rectangularity(contours.size()), circularity(contours.size());
    	for (i = 0; i < contours.size(); i++)
    	{//把所有的轮廓画出来
    		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
    		length[i] = arcLength(contours[i], true);//轮廓的长度
    		if (length[i] >200 && length[i] <2000)
    		{//通过长度匹配滤除小轮廓
    			convexHull(Mat(contours[i]), hull[i], false);//把凸包找出来,寻找凸包函数
    			Area_contours[i] = contourArea(contours[i]);   //轮廓面积
    			Area_hull[i] = contourArea(hull[i]);           //凸包面积
    			Rectangularity[i] = Area_contours[i] / Area_hull[i]; //矩形度
    			circularity[i] = (4 * 3.1415*Area_contours[i]) / (length[i] * length[i]);//圆形度
    			//drawContours(drawing, contours, i, color, 1);//得到方框
    
    			if (Rectangularity[i]>0.8&&circularity[i]<0.9)
    			{//通过矩形度和圆形度滤除数字
    				//drawContours(drawing, contours, i, Scalar(255, 255, 255), 1);
    				RectContours.push_back(hull[i]);//把提取出来的方框导入到新的轮廓组
    				drawContours(drawing, hull, i, color, 1);//得到方框
    			}
    		}
    	}
    
    
    	float distance = 0, distanceMax = 0;
    	Point connorPoint1, connorPoint2, connorPoint3, connorPoint4, point_add;
    	vector<Point> connor4_add(3);  //先找到的三个角点
    	int conP_i1, conP_i2, conP_i3, conP_i_add;
    	int j = 0, flag = 0;
    
         Point  finally_contours[80][4];//轮廓,为点向量,新的轮廓
    	for (j = 0; j < RectContours.size(); j++)  //四边形轮廓个数
    	{
    		distance = 0;
    		distanceMax = 0;
    		for (i = 0; i < RectContours[j].size(); i++) //每个轮廓点的个数11到19点不等
    		{//找第一个角点
    			distance = getDistance(RectContours[j][i], RectContours[j][0]);
    			if (distance>distanceMax)
    			{
    				distanceMax = distance;
    				connorPoint1 = RectContours[j][i]; //第一个角点
    				conP_i1 = i;
    			}
    		}
    		distance = 0;
    		distanceMax = 0;
    		for (i = 0; i < RectContours[j].size(); i++)
    		{//找第二个角点
    			distance = getDistance(RectContours[j][i], connorPoint1);
    			if (distance>distanceMax)
    			{
    				distanceMax = distance;
    				connorPoint2 = RectContours[j][i]; //第二个角点
    				conP_i2 = i;
    			}
    		}
    		distance = 0;
    		distanceMax = 0;
    		for (i = 0; i < RectContours[j].size(); i++)
    		{//找第三个角点
    			distance = getDistance(RectContours[j][i], connorPoint1) + getDistance(RectContours[j][i], connorPoint2);
    			if (distance>distanceMax)
    			{
    				distanceMax = distance;
    				connorPoint3 = RectContours[j][i]; //第三个角点
    				conP_i3 = i;
    			}
    		}
    		flag = list_connor(conP_i1, conP_i2, conP_i3);//对三个角点由大到小排序
    		switch (flag)
    		{//对三个角点排序
    		case 0:break;
    		case 123:break;
    		case 132:point_add = connorPoint2; connorPoint2 = connorPoint3; connorPoint3 = point_add; break;//2,3交换
    		case 213:point_add = connorPoint1; connorPoint1 = connorPoint2; connorPoint2 = point_add; break;//1,2交换
    		case 231:point_add = connorPoint1; connorPoint1 = connorPoint2; connorPoint2 = point_add;
    			point_add = connorPoint2; connorPoint2 = connorPoint3; connorPoint3 = point_add; break;//1,2交换+2,3交换
    		case 321:point_add = connorPoint3; connorPoint3 = connorPoint1; connorPoint1 = point_add; break;//1,3交换
    		case 312:point_add = connorPoint3; connorPoint3 = connorPoint1; connorPoint1 = point_add;
    			point_add = connorPoint2; connorPoint2 = connorPoint3; connorPoint3 = point_add; break;//1,3交换+2,3交换
    		}
    		switch (flag)
    		{//对三个角点排序
    		case 0:break;
    		case 123:break;
    		case 132:conP_i_add = conP_i2; conP_i2 = conP_i3; conP_i3 = conP_i_add; break;//2,3交换
    		case 213:conP_i_add = conP_i1; conP_i1 = conP_i2; conP_i2 = conP_i_add; break;//1,2交换
    		case 231:conP_i_add = conP_i1; conP_i1 = conP_i2; conP_i2 = conP_i_add;
    			conP_i_add = conP_i2; conP_i2 = conP_i3; conP_i3 = conP_i_add; break;//1,2交换+2,3交换
    		case 321:conP_i_add = conP_i3; conP_i3 = conP_i1; conP_i1 = conP_i_add; break;//1,3交换
    		case 312:conP_i_add = conP_i3; conP_i3 = conP_i1; conP_i1 = conP_i_add;
    			conP_i_add = conP_i2; conP_i2 = conP_i3; conP_i3 = conP_i_add; break;//1,3交换+2,3交换
    		}
    		distance = 0;
    		distanceMax = 0;
    		for (i = conP_i3; i < conP_i2; i++)
    		{//相隔两角点之间找到怀疑是4角点的点
    			distance = getDistance(RectContours[j][i], connorPoint3) + getDistance(RectContours[j][i], connorPoint2);
    			if (distance>distanceMax)
    			{
    				distanceMax = distance;
    				connor4_add[0] = RectContours[j][i];
    			}
    		}
    		distance = 0;
    		distanceMax = 0;
    		for (i = conP_i2; i < conP_i1; i++)
    		{//相隔两角点之间找到怀疑是4角点的点
    			distance = getDistance(RectContours[j][i], connorPoint1) + getDistance(RectContours[j][i], connorPoint2);
    			if (distance>distanceMax)
    			{
    				distanceMax = distance;
    				connor4_add[1] = RectContours[j][i];
    			}
    		}
    		distance = 0;
    		distanceMax = 0;
    		for (i = conP_i1; i < RectContours[j].size() + conP_i3; i++)
    		{//相隔两角点之间找到怀疑是4角点的点
    			if (i< RectContours[j].size())
    			{
    				distance = getDistance(RectContours[j][i], connorPoint1) + getDistance(RectContours[j][i], connorPoint3);
    				if (distance>distanceMax)
    				{
    					distanceMax = distance;
    					connor4_add[2] = RectContours[j][i];
    				}
    			}
    			else
    			{
    				distance = getDistance(RectContours[j][i - RectContours[j].size()], connorPoint1) + getDistance(RectContours[j][i - RectContours[j].size()], connorPoint3);
    				if (distance>distanceMax)
    				{
    					distanceMax = distance;
    					connor4_add[2] = RectContours[j][i - RectContours[j].size()];
    				}
    			}
    		}
    		if (getDist_P2L(connor4_add[0], connorPoint3, connorPoint2)>10)
    		{
    			connorPoint4 = connor4_add[0];
    		}
    		else if (getDist_P2L(connor4_add[1], connorPoint2, connorPoint1)>10)
    		{
    			connorPoint4 = connor4_add[1];
    		}
    		else if (getDist_P2L(connor4_add[2], connorPoint1, connorPoint3)>10)
    		{
    			connorPoint4 = connor4_add[2];
    		}
    
    		circle(drawing, connorPoint1, 3, Scalar(255, 255, 255), FILLED, LINE_AA);
    		circle(drawing, connorPoint2, 3, Scalar(255, 255, 255), FILLED, LINE_AA);
    		circle(drawing, connorPoint3, 3, Scalar(255, 255, 255), FILLED, LINE_AA);
    		circle(drawing, connorPoint4, 3, Scalar(255, 255, 255), FILLED, LINE_AA);
         
    		finally_contours[j][0] = connorPoint1;
    		finally_contours[j][1] = connorPoint2;
    		finally_contours[j][2] = connorPoint3;
    		finally_contours[j][3] = connorPoint4;
    
    		cout << "\n轮廓 " << j+1 << "  的四个角点坐标分别为:\n" << finally_contours[j][0] << finally_contours[j][1] << finally_contours[j][2] << finally_contours[j][3] << endl;
    
    	}
    
    
    
    
    
    	//float distance = 0, distanceMax = 0;
    	//Point connorPoint1, connorPoint2, connorPoint3, connorPoint4;
    	//int j = 0, k = 0;
    	//vector<float>Theta(30);
    	//vector<Point>ConnorPoint(4);
    	//for (k = 0; k < RectContours.size(); k++)
    	//{//历遍每个轮廓找角点
    	//	j = 0;
    	//	for (i = 0; i < RectContours[k].size(); i++)
    	//	{//历遍当个轮廓各点间夹角
    	//		if (i == 0)
    	//		{
    	//			Theta[i] = getAngle(RectContours[k][i], RectContours[k][RectContours[k].size() - 1], RectContours[k][i + 1]);
    	//		}
    	//		else if (i == RectContours[k].size() - 1)
    	//		{
    	//			Theta[i] = getAngle(RectContours[k][i], RectContours[k][i - 1], RectContours[k][0]);
    	//		}
    	//		else
    	//		{
    	//			Theta[i] = getAngle(RectContours[k][i], RectContours[k][i - 1], RectContours[k][i + 1]);
    	//		}
    	//		if (Theta[i] / 3.1415 * 180 < 170)
    	//		{//两点间夹角小于170度
    	//			if (getDistance(RectContours[k][i], ConnorPoint[0])>10 && getDistance(RectContours[k][i], ConnorPoint[1])>10
    	//				&& getDistance(RectContours[k][i], ConnorPoint[2])>10 && getDistance(RectContours[k][i], ConnorPoint[3])>10)
    	//			{//新找到的角点与已经保存的角点间距离要大于10
    	//				ConnorPoint[j] = RectContours[k][i]; //四个角点
    	//			//	circle(drawing, RectContours[k][i], 3, Scalar(255, 255, 255), FILLED, LINE_AA);
    	//				circle(drawing, ConnorPoint[j], 3, Scalar(255, 255, 255), FILLED, LINE_AA);
    	//				//每个四边形的角点显示逻辑这里还是有些问题
    	//				cout << "\n轮廓 " << j << "  的四个角点坐标分别为:\n" << ConnorPoint[0] << ConnorPoint[1] << ConnorPoint[2] << ConnorPoint[3] << endl;
    	//				j++;
    	//			}
    	//		}
    
    	//	}
    	//}
    
    	//
    	/*for (int i = 0; i < ConnorPoint.size(); i++)
    	{
    		cout << "\n\t\t毛哥好\n" << endl;
    	}
    		*/
    
    
    	imshow("轮廓", drawing);
    	/********透视变换过程*************************************************************************/
    	检测是否是四边形,很多图片检测不到
    	//	if (approx.size() != 4)
    	//	{
    	//		std::cout << "The object is not quadrilateral(四边形)!" << std::endl;
    	//		return -1;
    	//	}
    	//	//get mass center  寻找四边形中点
    	//	for (unsigned int i = 0; i < corners.size(); i++)
    	//	{
    	//		center += corners[i];
    	//	}
    	//	center *= (1. / corners.size());
    	//
    	//	//确定四个点的中心线
    	//	sortCorners(corners, center);
    	//
    	//	cv::Mat dst = src.clone();
    	//
    	//	//Draw Lines  画直线
    	//	for (unsigned int i = 0; i<lines.size(); i++)
    	//	{
    	//		cv::Vec4i v = lines[i];
    	//		cv::line(dst, cv::Point(v[0], v[1]), cv::Point(v[2], v[3]), CV_RGB(0, 255, 0));    //目标版块画绿线   
    	//	}
    	//
    	//	//draw corner points  画角点
    	//	cv::circle(dst, corners[0], 3, CV_RGB(255, 0, 0), 2);
    	//	cv::circle(dst, corners[1], 3, CV_RGB(0, 255, 0), 2);
    	//	cv::circle(dst, corners[2], 3, CV_RGB(0, 0, 255), 2);
    	//	cv::circle(dst, corners[3], 3, CV_RGB(255, 255, 255), 2);
    	//
    	//	//draw mass center  画出四边形中点
    	//	cv::circle(dst, center, 3, CV_RGB(255, 255, 0), 2);
    	//
    	//	cv::Mat quad = cv::Mat::zeros(300, 220, CV_8UC3);//设定校正过的图片从320*240变为300*220  
    	//
    	//	//corners of the destination image  
    	//	std::vector<cv::Point2f> quad_pts;
    	//	quad_pts.push_back(cv::Point2f(0, 0));
    	//	quad_pts.push_back(cv::Point2f(quad.cols, 0));//(220,0)  
    	//	quad_pts.push_back(cv::Point2f(quad.cols, quad.rows));//(220,300)  
    	//	quad_pts.push_back(cv::Point2f(0, quad.rows));
    	//
    	//	// Get transformation matrix  
    	//	cv::Mat transmtx = cv::getPerspectiveTransform(corners, quad_pts);   //求源坐标系(已畸变的)与目标坐标系的转换矩阵  
    	//
    	//	// Apply perspective transformation透视转换  
    	//	cv::warpPerspective(src, quad, transmtx, quad.size());
    
    	//	cv::namedWindow("image", 0);
    	//	cv::imshow("image", dst);
    	//
    	//	cv::namedWindow("quadrilateral", 0);
    	//	cv::imshow("quadrilateral", quad);
    
    
    	waitKey(0);
    	return 0;
    }
    
    float getDist_P2L(CvPoint pointP, CvPoint pointA, CvPoint pointB)
    {//点到直线的距离:P到AB的距离
    	//求直线方程
    	int A = 0, B = 0, C = 0;
    	A = pointA.y - pointB.y;
    	B = pointB.x - pointA.x;
    	C = pointA.x*pointB.y - pointA.y*pointB.x;
    	//代入点到直线距离公式
    	float distance = 0;
    	distance = ((float)abs(A*pointP.x + B*pointP.y + C)) / ((float)sqrtf(A*A + B*B));
    	return distance;
    }
    
    
    //对角点进行排序,因为之前检测出的轮廓是带序号的
    int list_connor(int i1, int i2, int i3)
    {//排序
    	int flag = 0;
    	Point point_add;
    	if (i1 >= i2&&i2 >= i3)
    		flag = 123;
    	else if (i1 >= i3&& i3 >= i2)
    		flag = 132;
    	else if (i2 >= i1&&i1 >= i3)
    		flag = 213;
    	else if (i2 >= i3&&i3 >= i1)
    		flag = 231;
    	else if (i3 >= i2&&i2 >= i1)
    		flag = 321;
    	else if (i3 >= i1&&i1 >= i2)
    		flag = 312;
    	return flag;
    }
    
    
    
    float getDistance(CvPoint pointO, CvPoint pointA)
    {//求两点之间距离
    	float distance;
    	distance = powf((pointO.x - pointA.x), 2) + powf((pointO.y - pointA.y), 2);
    	distance = sqrtf(distance);
    
    	return distance;
    }
    
    float getAngle(CvPoint pointM, CvPoint pointL, CvPoint pointR)
    {//求三点之间的夹角
    	CvPoint L, R;
    	float dist_L, dist_R, Theta;
    	L.x = pointL.x - pointM.x;
    	L.y = pointL.y - pointM.y;
    	R.x = pointR.x - pointM.x;
    	R.y = pointR.y - pointM.y;
    	dist_L = getDistance(pointL, pointM);
    	dist_R = getDistance(pointR, pointM);
    	Theta = acos((L.x*R.x + L.y*R.y) / (dist_L*dist_R));
    	return Theta;
    }
    
    

    程序思路

    二值化——找轮廓——轮廓剔除(留下四边形,去除其他不相关轮廓)——根据相关数学思路寻找角点(比如最简单的左上角、右下角,需要很多优化)——对角点进行排序,每个四边形的角点进行顺时针或者逆时针的排序。

    展开全文
  • 利用goodFeaturesToTrack()角点检测: 利用findChessboardCorners()检测棋盘板内角,cornerSubPix()亚像素精细化检测结果: goodFeaturesToTrack()和findChessboardCorners()区别: 利用goodFeaturesToTrack()...

    目录

    利用goodFeaturesToTrack()角点检测:

    利用findChessboardCorners()检测棋盘板内角点,cornerSubPix()亚像素精细化检测结果:

     goodFeaturesToTrack()和findChessboardCorners()区别:


    利用goodFeaturesToTrack()角点检测:

    函数的参数说明:

    def goodFeaturesToTrack(image: Any【输入图像,是八位的或者32位浮点型,单通道图像,所以有时候用灰度图】,
                            maxCorners: Any【返回最大的角点数,是最有可能的角点数,如果这个参数不大于0,那么表示没有角点数的限制】,
                            qualityLevel: Any【图像角点的最小可接受参数,质量测量值乘以这个参数就是最小特征值,小于这个数的会被抛弃】,
                            minDistance: Any【返回的角点之间最小的欧式距离】,
                            corners: Any = None,
                            mask: Any = None【检测区域。如果图像不是空的(它需要具有CV_8UC1类型和与图像相同的大小),它指定检测角的区域】,
                            blockSize: Any = None【用于计算每个像素邻域上的导数协变矩阵的平均块的大小】,
                            useHarrisDetector: Any = None【选择是否采用Harris角点检测,默认是false. k: Harris检测的自由参数】,
                            k: Any = None) -> None

    实验图片:

     实验结果:

    测试代码: 

    import cv2
    import numpy as np
    """
    角点检测 goodFeaturesToTrack()
    """
    img = cv2.imread("E:/Users/raychiu/Desktop/825.bmp")
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    corners = cv2.goodFeaturesToTrack(gray, 150, 0.3, 50)
    corners = np.int0(corners)
    
    for corner in corners:
        x, y = corner.ravel()
        cv2.circle(img, (x, y), 5, (0, 0, 255), -1)
    
    # 缩小图像
    height, width = img.shape[:2]
    size = (int(width * 0.4), int(height * 0.4))
    img = cv2.resize(img, size, interpolation=cv2.INTER_AREA)
    
    cv2.imshow("img", img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    利用findChessboardCorners()检测棋盘板内角点,cornerSubPix()亚像素精细化检测结果:

    findChessboardCorners(image: Any,patternSize: Any,corners: Any = None,flags: Any = None) 三个参数:

    image:输入原始的棋盘板图像。该图像必须是一张8位的灰度图或色彩图。
    patternSize:(w,h),棋盘上每一排和每一列的内角数。w=棋盘板一行上黑白块的数量-1,h=棋盘板一列上黑白块的数量-1,例如:10x6的棋盘板,则(w,h)=(9,5)
    corners:array,检测到的角点的输出数组。
    flags:int,不同的操作标记,能够为0或者下述值的组合:

    •     CALIB_CB_ADAPTIVE_THRESH 使用自适应阈值法把图像转换为黑白图,而不是使用一个固定的阈值。
    •     CALIB_CB_NORMALIZE_IMAGE 在利用固定阈值或自适应阈值法二值化图像之前,利用直方图均衡化图像。
    •     CALIB_CB_FILTER_QUADS 使用额外的标准(如轮廓面积,周长,正方形形状)来过滤掉在轮廓检索阶段提取的假四边形。
    •     CALIB_CB_FAST_CHECK 对图像运行一个快速检查机制以查找棋盘板的角点,如果没有找到角点则返回一个快捷提醒。当没有观察到棋盘时,可以极大地加快在退化条件下的调用。

    cornerSubPix(image: Any,corners: Any,winSize: Any,zeroZone: Any,criteria: Any)五个参数:

    第一个参数 是输入图像,灰度左图
    第二个参数是检测到的角点,即是输入也是输出。
    第三个参数是计算亚像素角点时考虑的区域的大小,大小为NXN; N=(winSize*2+1)。
    第四个参数作用类似于winSize,但是总是具有较小的范围,通常忽略(即Size(-1, -1))。
    第五个参数用于表示计算亚像素时停止迭代的标准

    测试图片:

    测试结果:

     测试代码:

    # -*- coding: utf-8 -*-
    import cv2
    
    # 查找棋盘格 角点
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.1)
    
    # 棋盘格参数
    corners_vertical = 6    # 纵向角点个数;
    corners_horizontal = 7  # 横向角点个数;
    pattern_size = (corners_vertical, corners_horizontal)
    
    
    def find_corners_sb(img):
        """
        查找棋盘格角点函数 SB升级款
        :param img: 处理原图
        """
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        # 查找棋盘格角点;
        ret, corners = cv2.findChessboardCornersSB(gray, pattern_size, cv2.CALIB_CB_EXHAUSTIVE + cv2.CALIB_CB_ACCURACY)
        if ret:
            # 精细查找角点
            corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
            # 显示角点
            cv2.drawChessboardCorners(img, pattern_size, corners2, ret)
    
    
    def find_corners(img):
        """
        查找棋盘格角点函数
        :param img: 处理原图
        """
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
        # 查找棋盘格角点;
        ret, corners = cv2.findChessboardCorners(gray, pattern_size, cv2.CALIB_CB_ADAPTIVE_THRESH +
                                                 cv2.CALIB_CB_FAST_CHECK +
                                                 cv2.CALIB_CB_FILTER_QUADS)
        if ret:
            # 精细查找角点
            corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
            # 显示角点
            cv2.drawChessboardCorners(img, pattern_size, corners2, ret)
    
    
    def main():
        # 1.创建显示窗口
        cv2.namedWindow("img", 0)
        cv2.resizeWindow("img", 1075, 900)
    
        file_path = ('./1.jpg')
        img_src = cv2.imread(file_path)
    
        if img_src is not None:
            # 执行查找角点算法
            find_corners_sb(img_src)
            # find_corners(img_src)
    
            # 显示图片
            cv2.imshow("img", img_src)
            cv2.waitKey(0)
    
        cv2.destroyAllWindows()
    
    
    if __name__ == '__main__':
        main()
    
    

     goodFeaturesToTrack()和findChessboardCorners()区别:

     goodFeaturesToTrack()是针对全幅图像找角点的,findChessboardCorners()是专门检测棋盘板内角点的函数

    展开全文
  • 首先通过选得到待测角外接四边形的4个角点坐标,接着利用单应性矩阵映射得到所有角点的初始位置,最后综合内插值法、Harris算子、Forstner算子、SVD方法等方法对所有角点进一步精确定位。实验表明,该方法对棋盘...
  • 【Python+OpenCV】基于Harris角点的边缘提取以及矩形四角点检测开始之前必须要说的一些事一、参考文章二、实验目标三、局限性声明开始说正事了,所以标题一定要比第一个一级标题长一、思路(一)基于Harris角点检测...
  • opencv——检测四边形的四个角点

    万次阅读 2016-07-21 11:08:00
    //定义直线的终点和起点,直线上每一个应该满足直线方程r=xcos(threta)+ysin(threta); pt1.y = cvRound(y0 + 100 * (a)); pt2.x = cvRound(x0 - 1200 * (-b)); pt2.y = cvRound(y0 - 1200 * (a)); ...
  • 函数简介   ...OpenCV中的findChessboardCorners()函数即用于棋盘格角点检测。 参数说明 findChessboardCorners(InputArray image, Size patternSize,OutputArray corners, int flags=CAL
  • yy++)//统计边缘图像中共有多少个黑色像素 { for ( int xx = 0 ; xx < edge->width; xx++) { // CvScalar ss = ( 255 ); double ds = cvGet2D(edge, yy, xx).val[ 0 ]; if (ds == 0 ) count++; }...
  • 本科毕业论文中的角点检测 包含moravec、harris、Nobel、Shi-tomasi角点检测算法 包含拟合亚像素角点、向量点乘亚像素角点算法 此外还有矩阵的通常运算加减乘除、求逆等 程序采用opencv+Qt5 GUI
  • 分割结果容易受到血液伪影和支架内部断裂的影响,而导致支架轮廓分割准确度不高的问题,利用IVOCT影像中可降解支架具有四边形外观的先验信息,提出一种使用支架的4个角点得到支架轮廓的算法。实验结果显示:所提出的支架...
  • Harris角点检测实现角点检测的案例 Harris角点检测实现的原理 Harris角点检测实现的步骤 Shi-Tomasi角点检测(Harris算法的改进) 亚像素角点检测 角点检测的相关概念 (1)特征(兴趣/关键) 对于一幅图像...
  • 2017_2018学年八年级数学下册第6章平行四边形课题2平行四边形线特征当堂检测课件新版北师大版
  • 基于hough变换的思想,检测四边形的四条边的斜率和截距,从而将四边形的形成检测出来,
  • 目标 在本章中, 我们将了解FAST算法的基础知识。 我们将使用OpenCV功能对FAST算法进行探索。 理论 我们看到了几个特征检测器,其中很多真的很棒。但是,从实时应用程序的角度来看,...选择图像中是否要识别为兴趣
  • 图1 :原始图片 第一步,局部平均自适应阈值化方法对亮度不均匀情况适应性...第三步,检测四边形,计算每个轮廓的凸包,多边形检测,以及判断是否只有四个顶点,若是则为四边形,再用长宽比、周长和面积等约束去除一...
  • 【opencv】棋盘格角点检测

    千次阅读 2019-12-10 16:05:06
    使用了棋盘格进行相机标定,在此之前首先要对棋盘格角点进行检测。opencv中封装了一个寻找角点的函数cv::findChessboardCorners()以及绘制棋盘角点函数cv::drawChessboardCorners()。下面对两函数进行总结介绍,并贴...
  • 【南方新中考】(南粤专用)2015中考数学 第二部分 专题突破 专题八 三角形和四边形检测复习
  • 接着上一篇基于生长的棋盘格角点检测方法–(2)代码详解(上),来看一下第二个重要函数chessboardsFromCorners。 该函数的目的是用上一步骤中找到的角点恢复出棋盘结构。首先初始化一个3x3的角点矩阵,也就是一个...
  • opencv棋盘格角点检测原理总结

    万次阅读 2018-02-06 18:13:27
    第一步,局部平均自适应阈值化方法对亮度不均匀情况适应性强,因此...第三步,检测四边形,计算每个轮廓的凸包,多边形检测,以及判断是否只有四个顶点,若是则为四边形,再用长宽比、周长和面积等约束去除一些干扰...
  • opencv4 角点检测

    2020-07-13 16:01:23
    if (found) { //亚像素点检测 cornerSubPix(imageGray, corners, Size(5, 5), Size(-1, -1), TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 30, 0.1)); drawChessboardCorners(image, boardSize, Mat...
  • opencv——角点检测

    2016-07-13 20:08:40
    cvGoodFeaturesToTrack()#include"cv.h" #include"highgui.h" #include"stdio.h"#define max_corners 50 int main(int argc, char** argv) { int cornerCount = max_corners; CvPoint2D32f corners[max_corne
  • opencv检测四边形/多边形

    万次阅读 2016-05-16 14:25:46
    如何用检测由直线构成的四边形(多边形)? 这个问题自己困扰了十来天, 查了相关的算法书 (a modern approach, algorithms and applications, computer and machine vision, Feature Extraction & Image Processing ),...
  • show_image("image_dst", img_dst) cv2.waitKey() cv2.destroyAllWindows() if __name__ == '__main__': main() 角点检测 import cv2 as cv # 1.加载图片 original = cv.imread('./box.png') cv.imshow('Original', ...
  • 2017_2018学年八年级数学下册第6章平行四边形课题5三角形的中位线当堂检测课件新版北师大版
  • 思路是,采用L1、L2、L3和L4四条线,按照如图所示方向依次扫过图形,遇到角点停止,返回坐标。 (该方法只对部分规则的四边形适用) 问题是A和B的识别程序通不过,请问问大家是怎么回事,该如何解决? 源代码...
  • import cv2 import numpy as np #读入图片 img = cv2.imread('444.png') ...# 原图中的四个角点(左上、右上、左下、右下),与变换后矩阵位置 pts1 = np.float32([[140, 60], [566, 42], [10, 360]...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,982
精华内容 1,192
关键字:

四边形角点检测