opencv 实战,钢板焊接点寻找3

第三张图:



方法:轮廓检测后亚像素级角点检测 ,得出角点坐标,再提取

          个人感觉这种方法抗干扰能力最好。

代码:

//第三张,轮廓检测后亚像素级角点检测 ,得出角点坐标

#include <opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <cstdlib>
using namespace cv;
using namespace std;

#define WINDOW_NAME "【亚像素级角点检测】"        

Mat g_srcImage, g_grayImage;
int g_maxCornerNumber = 20;                             //点数初始值
int g_maxTrackbarNumber = 500;                          //点数上线
														//RNG g_rng(12345);                                      //初始化随机数生成器


void on_GoodFeaturesToTrack(int, void*)                //响应滑动条移动的回调函数
{
	if (g_maxCornerNumber <= 7) { g_maxCornerNumber = 7; }                      //对变量小于等于1时的处理

	vector<Point2f> corners;                                                    //Shi-Tomasi算法(goodFeaturesToTrack函数)的参数准备
	double qualityLevel = 0.01;                                                 //角点检测可接受的最小特征值
	double minDistance = 10;                                                    //角点之间的最小距离
	int blockSize = 3;                                                          //计算导数自相关矩阵时指定的邻域范围
	double k = 0.04;                                                            //权重系数

	Mat copy = g_srcImage.clone();

	//进行Shi-Tomasi角点检测
	goodFeaturesToTrack
	(g_grayImage,               //输入图像
		corners,                                   //检测到的角点的输出向量
		g_maxCornerNumber,                         //角点的最大数量
		qualityLevel,                              //角点检测可接受的最小特征值
		minDistance,                               //角点之间的最小距离
		Mat(),                                     //感兴趣区域
		blockSize,                                  //计算导数自相关矩阵时指定的邻域范围
		false,                                      //不使用Harris角点检测
		k);                                         //权重系数

	cout << "\n\t>-此次检测到的角点数量为:" << corners.size() << endl;

	//亚像素角点检测的参数设置
	Size winSize = Size(5, 5);
	Size zeroZone = Size(-1, -1);
	TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001);

	//计算出亚像素角点位置
	cornerSubPix(g_grayImage, corners, winSize, zeroZone, criteria);
	Point2f lowstpoint, nextpoint, uppoint, mid;                         //初始化最下方点,下一个点,最下方上面的点,中间点
	lowstpoint = corners[0];
	uppoint = corners[0];

	for (int i = 0; i < corners.size(); i++)                                  //找出最低点
	{
		nextpoint = corners[i];
		if (nextpoint.y > lowstpoint.y) { lowstpoint = nextpoint; }

		if (i == corners.size() - 1)
		{
			for (int j = 0; j < corners.size(); j++)                          //已找到最后一个点,开始找竖直方向最近点
			{
				nextpoint = corners[j];
				float a = abs(nextpoint.x - lowstpoint.x);
				float b = abs(uppoint.x - lowstpoint.x);

				if (nextpoint != lowstpoint)                                  //除去最下方的点
				{
					if (a < b) { uppoint = nextpoint; }
				}

				if (j == corners.size() - 1)                                  //已找到竖直方向最近点,得到中间点
				{
					mid.x = (uppoint.x + lowstpoint.x) / 2;
					mid.y = (uppoint.y + lowstpoint.y) / 2;
					circle(copy, mid, 3, Scalar(0, 255, 0), -1, 8, 0);
					cout << " \t>>中间点坐标" << " (" << mid.x << "," << mid.y << ")" << endl;
				}

			}

		}

	}

	imshow(WINDOW_NAME, copy);

}


int main(int argc, char** argv)
{
	Mat srcImage = imread("3.jpg", 0);                                         //载入原始图二值图模式
	imshow("原始图", srcImage);

	Mat element = getStructuringElement(MORPH_RECT, Size(2, 2));               //定义核,开运算
	morphologyEx(srcImage, srcImage, MORPH_OPEN, element);                    //进行形态学开运算操作

	Mat dstImage = Mat::zeros(srcImage.rows, srcImage.cols, CV_8UC3);         //初始化结果图

	srcImage = srcImage > 50;                                                 //srcImage取大于阈值。。。那部分
	imshow("取阈值后的原始图", srcImage);

	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;

	findContours(srcImage, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);

	int index = 0;                                                           //遍历所有顶层的轮廓, 以随机颜色绘制出每个连接组件颜色
	for (; index >= 0; index = hierarchy[index][0])
	{
		Scalar color(rand() & 255, rand() & 255, rand() & 255);
		drawContours(dstImage, contours, index, color, FILLED, 8, hierarchy);
	}

	system("color 2F");

	g_srcImage = dstImage;
	cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);

	namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE);                                                                           //创建窗口和滑动条,并进行显示和回调函数初始化
	createTrackbar("最大角点数", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack);

	//imshow(WINDOW_NAME, g_srcImage);
	on_GoodFeaturesToTrack(0, 0);

	waitKey(0);
	return 0;
}


结果图:



位置图:



希望有其他方法的小伙伴可以留言。大家相互学习。



  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
前言: 开源的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 也能直接编译。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值