条码方向定位

news/2024/11/25 18:50:45/

参考了一篇论文的思想,主要思路就是通过分块求取各窗口内的梯度方向,利用密度阈值过滤。缺点是要手动定义窗口大小和密度值。

具体代码如下:

//窗口内计算边缘密度特征
struct EdgeDensity
{int num;	//边缘点数float orient; //边缘梯度方向
};
//排序
bool pairSortFun3(EdgeDensity elem1, EdgeDensity elem2)
{return elem1.num > elem2.num;	//降序
}
//求取主梯度方向
float GetCodeRegionOrient(Mat MatGray, int w, int h, int thre_gradient_density)
{//滤波blur(MatGray, MatGray, Size(3, 3));//求梯度cv::Mat magX = cv::Mat(MatGray.rows, MatGray.cols, CV_32F);cv::Mat magY = cv::Mat(MatGray.rows, MatGray.cols, CV_32F);cv::Sobel(MatGray, magX, CV_32F, 1, 0, 3);cv::Sobel(MatGray, magY, CV_32F, 0, 1, 3);Mat magnitude = Mat(MatGray.size(), CV_32FC1);	        // 梯度幅值Mat slopes = Mat(MatGray.size(), CV_32FC1);		// 梯度方向int i, j;float v1, v2, v, direc;for (i = 0; i < MatGray.rows; i++){for (j = 0; j < MatGray.cols; j++){v1 = magX.at<float>(i, j);v2 = magY.at<float>(i, j);v = sqrt(v1*v1 + v2*v2);  //求出梯度magnitude.at<float>(i, j) = v;if (v1 == 0){if (v2 != 0){direc = 90;}else{direc = 255;}}else{direc = atan(v2 / v1)* (180 / CV_PI);if (direc < 0){direc += 180;}int t = direc / 2;if (direc - t * 2 < (t + 1) * 2 - direc){direc = t * 2;}else{direc = (t + 1) * 2;}}slopes.at<float>(i, j) = direc;}}
Mat magtmp;magnitude.convertTo(magnitude, CV_8U);cv::threshold(magnitude, magnitude, 30, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);magnitude.convertTo(magtmp, CV_32F);//矩形窗口Mat dstM = Mat::zeros(magnitude.size(), CV_8UC1);for (i = 1; i < magnitude.rows - 1; i++){for (j = 1; j < magnitude.cols - 1; j++){for (int m = -1; m <= 1; m++)   // 3*3{for (int n = -1; n <= 1; n++){if ((magtmp.at<float>(i, j) == 255) && ((slopes.at<float>(i + m, j + n) == slopes.at<float>(i, j)) && slopes.at<float>(i, j) != 255)){if (m != 0 && n != 0){dstM.at<uchar>(i + m, j + n) = 255;dstM.at<uchar>(i, j) = 255;}}}}}}//分块计算主方向vector<EdgeDensity> dirVec;dirVec.clear();for (i = h; i < dstM.rows - h;){for (j = w; j < dstM.cols - w;){//计算块的主方向vector<float> d;d.clear();for (int m = -h; m <= h; m++){for (int n = -w; n <= w; n++){if (dstM.at<uchar>(i + m, j + n) == 255){float ori = slopes.at<float>(i + m, j + n);d.push_back(ori);}}}if (d.size() < 2){j += (2 * w + 1);continue;}std::sort(d.begin(), d.end());int index = 0, seqIndex = 0;int index_begin, seqIndex_begin = 0;for (int q = 0; q < d.size(); q++){if (q == d.size() - 1){if (d[q] == d[q - 1] && index != 0){if (index > seqIndex){seqIndex = index;seqIndex_begin = index_begin;}}break;}if (d[q + 1] == d[q]){if (index == 0){index_begin = q;}index++;}else{if (index > seqIndex){seqIndex = index;seqIndex_begin = index_begin;}index = 0;}}int len = d.size();if (seqIndex_begin < len){EdgeDensity ey;ey.num = seqIndex + 1;ey.orient = d[seqIndex_begin];dirVec.push_back(ey);}j += (2 * w + 1);}i += (2 * h + 1);}//找出主方向vector<float> orientVec;orientVec.clear();std::sort(dirVec.begin(), dirVec.end(), pairSortFun3);for (int c = 0; c < dirVec.size(); c++){if (dirVec[c].num > thre_gradient_density) // 剔除密度低的块{orientVec.push_back(dirVec[c].orient);}}if (orientVec.size() < 1){return -1;}std::sort(orientVec.begin(), orientVec.end());//标记seqIndex_begin 为主方向的索引int cnt = 0, seqCnt = 0;int index_begin, seqIndex_begin = 0;if (orientVec.size() == 1){seqIndex_begin = 0;seqCnt = 1;}else{for (int q = 0; q < orientVec.size(); q++){if (q == orientVec.size() - 1){if (orientVec[q] == orientVec[q - 1] && cnt != 0){if (cnt > seqCnt){seqCnt = cnt;seqIndex_begin = index_begin;}}break;}if (orientVec[q + 1] == orientVec[q]){if (cnt == 0){index_begin = q;}cnt++;}else{if (cnt > seqCnt){seqCnt = cnt;seqIndex_begin = index_begin;}cnt = 0;}}}return  orientVec[seqIndex_begin];
}

效果图如下:



http://www.ppmy.cn/news/263897.html

相关文章

双目立体视觉及正交偏振 3D 显示

人眼的双目立体视觉成像人类最神秘最完美的身体构造之一&#xff0c;了解人眼的基本构造和视觉成像处理过程&#xff0c;对于 3D 显示技术具有极大的启发。本文主要对人眼的基本构造、视觉成像系统进行简单介绍&#xff0c;并对基于此立体视觉原理的偏光式 3D 显示系统的结构和…

3D手办设备全彩彩色打印图像采集拍照拍摄设备相机矩阵

设备参数 镜头数量&#xff1a;90个 输出画质&#xff1a;1080p 包含配件&#xff1a;灯带、拍摄软件 材质&#xff1a;铝合金

永年激光金属3D打印新产品和科技成果通过鉴定——国内领先、国际先进

航天领域大尺寸结构件通常为单件或小批量&#xff0c;开发专用模具十分耗时&#xff0c;且费用昂贵&#xff0c;增材制造通过逐层累加的制造方式&#xff0c;具有制造流程短、不受零件复杂程度的影响&#xff0c;可实现复杂、大尺寸结构件快速制造&#xff0c;已受到航天制造领…

条形码类型和标准指南:一维、二维条码符号

条形码标签是跨组织和整个供应链跟踪资产和库存的有用工具&#xff0c;但哪种类型的条形码最适合您的需求&#xff1f;存在多种条形码符号系统&#xff0c;其中一些比其他符号更适合不同类型的应用。此外&#xff0c;一些行业制定了旨在规范资产和实物库存标签的标准&#xff0…

SpringBoot整合ShardingSphere5.x实现数据加解密功能

环境&#xff1a;Springboot2.6.14 ShardingSphere5.3.0 准备环境 添加依赖 <dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core</artifactId><version>${shardingsphere.version}</ve…

iOS View 生命周期

现在来看看View的生命周期 显示过程 -(void)willMoveToSuperview:(UIView *)newSuperview -(void)didMoveToSuperview -(void)willMoveToWindow:(UIWindow *)newWindow -(void)didMoveToWindow -(void)layoutSubviews 移除过程 -(void)willMoveToSuperview:(UIView *)ne…

老人跌倒检测识别预警算法 yolov7

老人跌倒检测识别预警系统采用yolov7网络模型技术&#xff0c;老人跌倒检测识别预警算法对老人的行为进行实时监测。当老人发生跌倒时&#xff0c;系统将自动发出警报&#xff0c;及时通知现场护理人员进行处理。YOLOv7 的发展方向与当前主流的实时目标检测器不同&#xff0c;研…

Django - 页面静态化基本使用(一)

一. 前言 一个网页会有很多数据是不需要经常变动的&#xff0c;比如说首页&#xff0c;变动频率低而访问量大&#xff0c;我们可以把它静态化&#xff0c;这样就不需要每次有请求都要查询数据库再返回&#xff0c;可以减少服务器压力 我们可以使用Django的模板渲染功能完成页面…