学习笔记(九)opencv3颜色分割与坐标显示

这篇学习笔记详细记录了使用OpenCV进行颜色分割和坐标显示的过程,包括从打开摄像头到HSV转换,再到颜色识别和形态学操作。作者在识别黄色绣球时遇到彩带干扰和轮廓识别不准确的问题,通过不断试验调整HSV范围、应用滤波和闭运算改进了效果。最终实现了计算轮廓矩、质心和显示坐标,但未能解决完全排除干扰物和识别多种颜色的问题。

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

上传一下一直记在有道云笔记里的东西

××——2017.11.3
目前已经可以实现
1.打开摄像头显示画面
2.使用cvtColor()将画面由BGR转为HSV

3.分割图像,保留红色像素
在这里插入图片描述
4.形态学运算膨胀图像(dilate) 使红色更明显
5.利用hough,变换提取图像中的圆形
6.绘制圆形

问题:
但事实证明用霍夫变换是不对的
霍夫变换只能识别边界明确的圆形
而实际的球周围有许多彩带干扰有可能导致难以识别完整的圆边界
用Circle绘制的圆形轮廓也不太正确
需要重新编写能生成包围整个球的圆形轮廓

2017-11-4
今日完成:
1.使用吸管工具吸取黄球照片中的16个不同程度的黄色,
在这里插入图片描述
使用取色软件Pipette得到HSV数值范围
在这里插入图片描述
在这里插入图片描述
(再结合实际摄像头测试,这种方法得到的颜色范围数据还是无法分割出绣球黄色部分,
最后还是一次次测试最后手动调成功的较为准确的HSV数值范围, Scalar(15, 60, 150), Scalar(45, 255, 255),写入程序中)
进而可以将识别官方黄球颜色,并在画面中分割出黄色部分
在这里插入图片描述
2.使用dilate()使黄色区域更加明显,element SIZE为10
3.使用Threshold检测边缘,阈值为5,findContours找出轮廓,并绘制最小面积包围圆形,
在这里插入图片描述
在这里插入图片描述
问题:
1.距离越近彩带的干扰越大,需要对图像进一步处理
2.目前只能识别一种颜色的球

2017-11-5
今日完成:
1.加了均值滤波去噪,element SIZE(20,20)
2.将膨胀改为闭运算,可以消除目标不连续空洞,element SIZE(40,40),使绣球的轮廓更清晰

均值滤波核为5时:
在这里插入图片描述
均值滤波核为20时:
在这里插入图片描述
由此可见,20时可以较大减少彩带的干扰
在这里插入图片描述
接下来要尝试获取绣球的位置信息
3.计算轮廓矩和质心并显示坐标,左上角为坐标原点
在这里插入图片描述
4.干扰太多,需要想办法只显示绣球坐标
使用if(area > 150){ }的方法剔除了小面积轮廓
在这里插入图片描述

因为实验室的任务变更,就没有继续优化这个代码了,目前为止的代码在下面贴一下

#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;

RNG g_rng(12345);

int main(int argc, char** argv)
{
	VideoCapture sensor(1); //capture the video from web cam  
	 if ( !sensor.isOpened() )  // if not success, exit program  
    {  
         cout << "Cannot open the web cam" << endl;  
         return -1;  
    }  

	  while (true)  
    {  
        Mat frameOriginal;  
  
        bool bSuccess = sensor.read(frameOriginal); // read a new frame from video  
  
         if (!bSuccess) //if not success, break loop  
        {  
             cout << "Cannot read a frame from video stream" << endl;  
             break;  
        }  

     
   Mat frameHSV;  
   vector<Mat> hsvSplit;  
   cvtColor(frameOriginal, frameHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV  


   Mat frameThresholded;  
   inRange(frameHSV, Scalar(15, 60, 150), Scalar(45, 255, 255), frameThresholded); //Threshold the image 

    
   //均值滤波去噪
   Mat frameBLUR;
   blur(frameThresholded, frameBLUR, Size(20, 20), Point(-1, -1)); 

      //闭运算消除目标不连续空洞

   Mat element= getStructuringElement(MORPH_RECT,Size(40,40));
   Mat frameCLOSE;
   morphologyEx(frameBLUR, frameCLOSE, MORPH_CLOSE, element); 

   //定义一些参数
	Mat threshold_output;
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;

	// 使用Threshold检测边缘
	threshold( frameThresholded, threshold_output, 5, 255, THRESH_BINARY );

	// 找出轮廓
	findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

    //计算轮廓矩       
    vector<Moments> mu(contours.size() );       
    for( int i = 0; i < contours.size(); i++ )     
    {   
        mu[i] = moments( contours[i], false );   
    }     
    //计算轮廓的质心     
    vector<Point2f> mc( contours.size() );      
    for( int i = 0; i < contours.size(); i++ )     
    {   
        mc[i] = Point2d( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 );   
    }     
    // 直接使用CONTOUR中的矩形来画轮廓  
    int order = 1;  
    Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );         
    for( int i = 0; i< contours.size(); i++ )      
    {         
        Scalar color = Scalar( 255, 0, 0);   
        double area = mu[i].m00;//面积  
        Rect ret1 = boundingRect(Mat(contours[i]));   //获取目标序列号放置位置  
        if(area > 150)           //剔除小面积轮廓  
        {  
            drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );         
            circle( drawing, mc[i], 5, Scalar( 0, 0, 255), -1, 8, 0 );                
            rectangle(drawing, boundingRect(contours.at(i)), cvScalar(0,255,0));   
              
            char tam[100];   
            sprintf(tam, "(%0.0f,%0.0f)",mc[i].x,mc[i].y);   
            putText(drawing, tam, Point(mc[i].x, mc[i].y), FONT_HERSHEY_SIMPLEX, 0.8, cvScalar(255,0,255),1);  
  
            char tam1[100];   
            sprintf(tam1, "%d",order++);   
            putText(drawing, tam1, Point(ret1.x+ret1.width, ret1.y+ret1.height), FONT_HERSHEY_SIMPLEX, 0.3, cvScalar(0,255,255),1);  
        }  
  
    } 

   imshow("Original", frameOriginal); 
   imshow("Out", drawing); 

   char key = (char) waitKey(300);  
   if(key == 27)  
         break;  
    }   
  
  
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值