前言 

目前地铁上检修螺丝后,会涂抹一种红色标记线,来代表检测完成,日后检修员就可以通过肉眼来观察螺丝是否松动,这样可以大大提高检修的效率问题。所以我们参照这个思路,通过opencv来实现螺丝是否松动检测。

            

正文

  1. 首先我们通过目标检测算法,识别出图像中螺丝的区域。这里不实现了就,自行通过yolo等算法实现。
  2. 识别出目标区域后,我们首先提取图像中的红色区域(假设我们用红色标记)
    void extract_red_area(const cv::Mat &image, cv::Mat &redMat) {
    	int width = image.cols;
    	int height = image.rows;
    	int x, y;
    	double B = 0.0, G = 0.0, R = 0.0, H = 0.0, S = 0.0, V = 0.0;
    	redMat = Mat::zeros(image.size(), CV_8UC1);
    	for (x = 0; x < height; x++)
    	{
    		for (y = 0; y < width; y++)
    		{
    			B = image.at<Vec3b>(x, y)[0];
    			G = image.at<Vec3b>(x, y)[1];
    			R = image.at<Vec3b>(x, y)[2];
    			RGB2HSV(R, G, B, H, S, V);
    			//红色范围,范围参考的网上。可以自己调
    			if ((H >= 312 && H <= 360) && (S >= 17 && S <= 100) && (V > 18 && V < 100))
    				redMat.at<uchar>(x, y) = 255;
    		}
    	}
    }

          

  3. 提取红色区域轮廓信息,这里我们需要过滤一些,因为有一些轮廓是我们不需要的。(根据实际情况来过滤)

    	// 2.提取轮廓
    	std::vector<std::vector<cv::Point>> contours;
    	std::vector<cv::Vec4i> hierarchy;
    	cv::findContours(
    		redMat,               // 输入二值图
    		contours,             // 存储轮廓的向量
    		hierarchy,            // 轮廓层次信息
    		RETR_TREE,            // 检索所有轮廓并重建嵌套轮廓的完整层次结构
    		CHAIN_APPROX_NONE);   // 每个轮廓的全部像素
    	printf("find %d contours \n", contours.size());
    
    
    // 过滤轮廓
    void filter_contours(std::vector<cv::Vec4i> &hierarchy, std::vector<std::vector<cv::Point>> &contours) {
    	std::vector<std::vector<cv::Point>>::iterator itc = contours.begin();
    	std::vector<cv::Vec4i>::iterator itc_hierarchy = hierarchy.begin();
    	int i = 0;
    	int min_size = 20;
    	int max_size = 500;
    	while (itc_hierarchy != hierarchy.end())
    	{
    		//验证轮廓大小
    		//if (!(hierarchy[i][2] < 0 && hierarchy[i][3] < 0)) // 存在子轮廓/父轮廓
    		if (hierarchy[i][3] > 0) // 存在父轮廓
    		{
    			itc = contours.erase(itc);
    			itc_hierarchy = hierarchy.erase(itc_hierarchy);
    		}
    		else
    		{
    			//验证轮廓大小
    			if (itc->size() < min_size || itc->size() > max_size)
    			{
    				itc = contours.erase(itc);
    				itc_hierarchy = hierarchy.erase(itc_hierarchy);
    			}
    			else
    			{
    				++itc;
    				++itc_hierarchy;
    			}
    
    			++i;
    		}
    	}
    }

  4.  提取每一个轮廓的最小外接矩形,并绘制最小外接矩形的每条边和中心点,并计算每一个区域的角度,最后通过每一个区域的角度来判断是否对齐。

    void draw_center(cv::Mat &dstImg, std::vector<std::vector<cv::Point>> &contours, std::vector<cv::Point> &vec) {
    	std::vector<RotatedRect> box(contours.size()); //定义最小外接矩形集合
    	Point2f rect[4];
    	for (int i = 0; i < contours.size(); i++)
    	{
    		box[i] = minAreaRect(Mat(contours[i])); 
    		cv::circle(dstImg, Point(box[i].center.x, box[i].center.y), 2, cv::Scalar(0, 255, 255), cv::FILLED);
    		box[i].points(rect);
    		for (int j = 0; j < 4; j++)
    		{
    			line(dstImg, rect[j], rect[(j + 1) % 4], Scalar(255, 0, 255), 1, 8);  //绘制最小外接矩形每条边
    		}
    		std::cout << "angel:" << box[i].angle << std::endl;
    	}
    }

     

     5. 以上差不多就是大概实现过程。主要实现思路就是: 识别螺丝 -> 提取红色区域 -> 识别轮廓 -> 筛选轮廓 -> 计算最小外接矩形、中心点、角度 -> 通过角度来判断是否对齐,从而来判断螺丝是否松动。

             

demo:基于opencv,实现螺丝防松动检测_螺丝松动检测-互联网文档类资源-CSDN下载

最后

以上实现思路都是个人想法,所以如果有小伙伴有更好的算法,欢迎楼下留言,非常感谢。最后祝大家新年快乐,在新的一年里工作顺利,技能大长。

GitHub 加速计划 / opencv31 / opencv
77.38 K
55.71 K
下载
OpenCV: 开源计算机视觉库
最近提交(Master分支:2 个月前 )
c3747a68 Added Universal Windows Package build to CI. 5 天前
9b635da5 - 5 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐