c++ 图像标定时 格子定位的opencv代码

5 篇文章 0 订阅

写了好多年opencv 有好多解决问题的手段 项目中用完了过后又会忘记
记录一下吧,争取不做遗忘黑熊

这段c++代码目的是将图片中的黑白标定板定位出来,想要得到四个角点
在这里插入图片描述

bool _CompairPointXX(Point2f &a, Point2f &b)
{
	return a.x > b.x;
}
bool _CompairPointYY(Point2f &a, Point2f &b)
{
	return a.y > b.y;
}
bool GetPoint_Data(Mat imageInput, Size board_size, vector<Point2f>&newarr)
{
	//ofstream fout("caliberation_result.txt");                       // 保存标定结果的文件 

	cout << "开始提取角点………………" << endl;
	int image_count = 0;                                            // 图像数量 
	vector<Point2f> image_points;                                   // 缓存每幅图像上检测到的角点
	vector<vector<Point2f>> image_points_seq;                       // 保存检测到的所有角点


	vector<Point2f>fourpoint;
	/* 提取角点 */
	bool ok = cv::findChessboardCorners(imageInput, board_size, image_points, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_NORMALIZE_IMAGE);
	//board_size 是你标定板的行列的 “有效”格子数目(例如我是(9,13))
	if (0 == ok)
	{
		cout << "照片提取角点失败,请删除后,重新标定!" << endl; //找不到角点
		/*imshow("失败照片", imageInput);
		waitKey(0);*/
		image_points.clear();
		image_points_seq.clear();
		return false;
	}
	else
	{
		Mat view_gray;
		if (imageInput.channels()==3)
		{
			cvtColor(imageInput, view_gray, CV_RGB2GRAY);
		}
		else
		{
			imageInput.copyTo(view_gray);
		}
		cout << "imageInput.channels()=" << imageInput.channels() << endl;


		/* 亚像素精确化 */
		//find4QuadCornerSubpix(view_gray, image_points, Size(5, 5)); //对粗提取的角点进行精确化
		cv::cornerSubPix(view_gray, image_points, cv::Size(11, 11), cv::Size(-1, -1), cv::TermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 20, 0.01));

		image_points_seq.push_back(image_points);  //保存亚像素角点

		///* 在图像上显示角点位置 */
		//drawChessboardCorners(view_gray, board_size, image_points, true);
		//这里的image_points是标定板格子所有角点,需要继续筛选我要的四个角点。
		
		std::sort(image_points.begin(), image_points.end(), _CompairPointXX);
		vector<int>pointxAy;
		int adnum;
		for (int i = 0; i < image_points.size(); i++)
		{
			adnum = image_points[i].x + image_points[i].y;
			pointxAy.push_back(adnum);
		}
		int minPosition = min_element(pointxAy.begin(), pointxAy.end()) - pointxAy.begin();
		int maxPosition = max_element(pointxAy.begin(), pointxAy.end()) - pointxAy.begin();
		pointxAy.clear();
		Point2f temppt;

		int minxx = image_points[minPosition].x;//左上点
		int minxy = image_points[minPosition].y;
		temppt.x = minxx;
		temppt.y = minxy;
		fourpoint.push_back(temppt);
		int maxxx = image_points[maxPosition].x;//右下点
		int maxxy = image_points[maxPosition].y;
		temppt.x = maxxx;
		temppt.y = maxxy;
		fourpoint.push_back(temppt);

		//右上点的筛选  不做这个操作的时候获取到的点吧,它有时候就不是准确的右上点,因为拍摄标定板子本身放置角度的问题 图像上 一行格子的水平像素和竖直像素并不在同一行或者列
		std::sort(image_points.begin(), image_points.end(), _CompairPointYY);
		//排序后;获取在一定范围内的最大值的位置,由位置索取值
		vector<int>pointy;
		int maxsize = 0;
		maxsize = image_points.size();
		for (int i = image_points.size() - 1; i >= 0; i--)
		{
			if (i<maxsize - 1 && (abs(image_points[i].y - image_points[maxsize - 1].y) <= 50.0))
			//50.0根据你自己图像的实际情况设置改掉
			{
				pointy.push_back(image_points[i].x);
			}
			else if (i == (maxsize - 1))
			{
				pointy.push_back(image_points[i].x);
			}
			else
			{
				break;
			}
		}

		int maxPosy = max_element(pointy.begin(), pointy.end()) - pointy.begin();
		pointy.clear();
		int minyx = image_points[maxsize - maxPosy - 1].x;
		int minyy = image_points[maxsize - maxPosy - 1].y;
		temppt.x = minyx;
		temppt.y = minyy;
		fourpoint.push_back(temppt);
		int maxyx, maxyy;
		vector<int>pointx;
		for (int i = 0; i < image_points.size(); i++)
		{
			if (i>0 && (abs(image_points[i].y - image_points[0].y) <= 100.0))
			//100.0  根据你自己的实际情况试试改掉
			{
				pointx.push_back(image_points[i].x);
			}
			else if (i == 0)
			{
				pointx.push_back(image_points[i].x);
			}
			else
			{
				break;
			}
		}

		int minPosx = min_element(pointx.begin(), pointx.end()) - pointx.begin();
		pointx.clear();
		maxyx = image_points[minPosx].x;
		maxyy = image_points[minPosx].y;

		temppt.x = maxyx;
		temppt.y = maxyy;
		fourpoint.push_back(temppt);
		for (int i = 0; i < 4; i++)
		{
			circle(view_gray, fourpoint[i],10,180,3,8,0); //把点画到图像上,看看结果
		}
		imwrite("view_gray.jpg", view_gray);
		view_gray.release();
	}

	newarr = fourpoint;
	fourpoint.clear();
	image_points.clear();
	image_points_seq.clear();
	//cout << "角点提取完成!!!" << endl;
	return true;
}

图有点糊,能明白意思就行(如果想得到最边界的值,那就根据现有的很多点的xy像素值,想上下左右扩一下,就可以得到最边上的点了)
在这里插入图片描述

自己弄个标定板吧,我当时阴天室内,光线不好。上图便于理解。

点赞奥,收藏奥。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前言: 开源的opencv真是一件伟大的产品,那么多个函数跟变量(具体多少还没数过)。要是结合起来综合运用几乎可以胜任任何有关图像识别和处理方面的工作。如果能更深入一点根据具体需要修改或优化里面的源码那更是如虎添翼。 花了点时间浏览了www.opencv.org.cn论坛里的所有贴子,还好不多才200多页。总体上对opencv里的一些常用函数功能作用大致有点了解,筛选一些跟元件识别有关的运用内容,但它论坛里的贴子回复的内容点到即止的居多。从网上下载了能搜到的教程跟代码全学习了解测试了一下,图像处理流程通常先开始都是要进行滤波,除燥,灰度,二值化后再轮廓识别等。 开始动手 经过多次好多次运行测试组合,终于有一次显示出意外的惊人效果,而且相当简单只是调用了几个函数而以,就可以有这样效果实在出人意料。第一个是进行元件中心点获取,也是直接调用函数再加点东西就可以得出元件的四个矩形顶点坐,有这几个坐就可以直接算出元件中间点所在的坐了。如果要检测元件摆放角度是否是垂直90度,只要判断边宽的长度为最小或最大时就是垂直90度。 但这个矩形框无法测出元件具体角度。如截图: 测试视频地址:https://v.youku.com/v_show/id_XMjU5NzY5NTI0.html 不过,还有另外一个函数可以提供这个功能,调用后可以直接求出最小外接矩形和角度 如截图: 测试视频地址:https://v.youku.com/v_show/id_XMjYwMDMzMDc2.html 说明:里面的光源不行,临时用手电筒,和在光盘上插几个LED做环形灯做照明,无法做到无阴影显示。如果光源做的好,效果应该是非常精确稳定。 识别包含下面2种做法: opencv里需要的头文件跟库文件都已编译好放在和设置在当前程序目录下,就可不用安装opencv 也能直接编译。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值