机器视觉算法与应用 4.3锯片检测 习题 C++ 实现

这篇博客介绍了如何使用C++实现机器视觉算法,特别是针对锯片检测的应用。内容包括亚像素精度的阈值分割、轮廓提取(目前实现了MMP最小周长多边形近似)、轮廓长度计算和鲁棒的线段拟合。通过双线性插值优化,提高了单通道处理速度。此外,还提到了动态阈值获取、图像二值化和边界追踪算法,但外边框检测和完整边界处理尚未完成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

应用算法:

1、亚像素精度阈值分割

2、将轮廓分割为线和圆  (当前只做到该部分的 轮廓提取  MMP最小周长多边形近似,还未分割,后边继续......)

3、轮廓长度

4、鲁棒的线段拟合

 

亚像素(其实与图像整数倍放大时一样的效果,只是少了右侧和下侧一个像素的整数倍,其他都一样)的处理 双线性插值:

/*亚像素处理*(以图像左顶点为原点)/
/***************
 nterval: 每两个像素之间的间隔亚像素个数
说明 屏蔽部分是用SSE学习练习的
***************/
void CPicShowDlg::SubPix(cv::Mat& src, cv::Mat& dst, int nterval/*每两个像素之间的间隔亚像素个数*/)
{
	if (nterval == 0)	// 无间隔
		return;
	nterval += 1;
	//构造输出图像
	int dst_rows = round((src.rows - 1) * nterval);//图像高度
	int dst_cols = round((src.cols - 1) * nterval);//图像宽度

	if (src.channels() == 1) 
	{
		dst = cv::Mat::zeros(dst_rows, dst_cols, CV_8UC1); //灰度图初始
	}
	else 
	{
		dst = cv::Mat::zeros(dst_rows, dst_cols, CV_8UC3); //RGB图初始
	}
	// 
	for (int i = 0; i < dst_rows; i++)
	{
		uchar* ptr = m_dstimg.ptr(i);
		for (int j = 0; j < dst_cols; j++)
		{
			if (j % nterval != 0 || i % nterval != 0)
			{
				// 双线性插值
				// 后面双线性插值用  的四个顶角
				int top = i / nterval, bottom = i / nterval + 1, left = j / nterval, right = j / nterval + 1;
				 //与映射到原图坐标相邻的四个像素点的坐
				/*双线性插值*/
				// 判断是否越界
				float pw = (float(i)) / 4 - top; //pw为坐标 行 的小数部分(坐标偏差)
				float pv = (float(j)) / 4 - left; //pv为坐标 列 的小数部分(坐标偏差)
				if (src.channels() == 1)
				{
					// 四个顶角的灰度值
					//float grey[] = { src.at<uchar>(top, left), src.at<uchar>(top, right), src.at<uchar>(bottom, left), src.at<uchar>(bottom, right) };
					//__m128 oldgrey = _mm_load_ps(grey);
					 针对四个顶角的 权重 
					//float a[4] = { 1 - pw, 1 - pw, pw, pw };
					//float b[4] = { 1 - pv , pv, 1-pv, pv };					
					//__m128  w0 = _mm_load_ps(a);
					//__m128  w1 = _mm_load_ps(b);
					//__m128 ret = _mm_mul_ps(w0, w1);
					//__m128 ret1 = _mm_mul_ps(ret, oldgrey);
					//float result[4];
					 存储 将寄存器中内容保存到内存中
					//_mm_store_ps(result, ret1);
					//灰度图像
					*ptr = (1 - pw) * (1 - pv) * src.at<uchar>(top, left) + (1 - pw) * pv * src.at<uchar>(top, right) + pw * (1 - pv) * src.at<uchar>(bottom, left) + pw * pv * src.at<uchar>(bottom, right);					
				}
				else
				{
					//彩色图像
					dst.at<cv::Vec3b>(i, j)[0] = (1 - pw)*(1 - pv)*src.at<cv::Vec3b>(top, left)[0] + (1 - pw)*pv*src.at<cv::Vec3b>(top, right)[0] + pw * (1 -pv)*src.at<cv::Vec3b>(bottom, left)[0] + pw * pv*src.at<cv::Vec3b>(bottom, right)[0];
					dst.at<cv::Vec3b>(i, j)[1] = (1 - pw)*(1 - pv)*src.at<cv::Vec3b>(top, left)[1] + (1 - pw)*pv*src.at<cv::Vec3b>(top, right)[1] + pw * (1 -pv)*src.at<cv::Vec3b>(bottom, left)[1] + pw * pv*src.at<cv::Vec3b>(bottom, right)[1];
					dst.at<cv::Vec3b>(i, j)[2] = (1 - pw)*(1 - pv)*src.at<cv::Vec3b>(top, left)[2] + (1 - pw)*pv*src.at<cv::Vec3b>(top, right)[2] + pw * (1 -pv)*src.at<cv::Vec3b>(bottom, left)[2] + pw * pv*src.at<cv::Vec3b>(bottom, right)[2];
				}
			}
			else if(j % nterval == 0 || i % nterval == 0) // 目标图像中的像素值 是 源图像中的 j / 3位置的像素值
			{
				*ptr = src.at<uchar>(i / nterval, j / nterval);
				
			}
			++
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值