今天在家无聊,终于有时间写下我的第一篇CSDN博客啦,前段时间帮一个老师做一个项目,用摄像头检测地上的色带,输出角度帮助机器人寻迹。就想到用opencv来做,可以我不会啊,怎么办?看呗。这里对opencv点个赞!函数通俗易懂,环境配置也比较简单,英语阅读能力好的人都不用买书的,看文档就可以用得飞起啊~~

看了几天就把程序写好了,用得不好大家不喜勿碰,思路如下:

程序如下:

// camera.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>  
#include <opencv2/opencv.hpp>  
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include "stdio.h"
#include "findtape.h"

using namespace cv;
using namespace std;

int minVotenum=50;

int _tmain(int argc, _TCHAR* argv[])
{
VideoCapture cap0(0);//打开一个摄像头  
VideoCapture cap1(1);//打开一个摄像头 笔记本必须要两个,否则打不开外置摄像头
vector<Vec4i> lines,resultlines;//存储视频中直线的起点和终点
Mat source_frame,source_frame1,gray_frame;//新建两帧图像 
int frame_width,frame_height;
namedWindow("视频",WINDOW_AUTOSIZE);//新建一个图像窗口

if(!cap0.isOpened()) //判断是否打开 
    {  
cerr<<"Can not open a camera or file."<<endl;
        return -1;  
    }
//获取视频的宽和高
frame_height=(int)cap0.get(CV_CAP_PROP_FRAME_HEIGHT);
frame_width=(int)cap0.get(CV_CAP_PROP_FRAME_WIDTH);

//namedWindow("灰度视频",WINDOW_AUTOSIZE);//新建一个图像窗口
    bool stop = false;  
    while(!stop)  
    {  
        cap0>>source_frame;//从视频一副图片 
cap1>>source_frame1;//从视频一副图片  这句没用的,为了打开外置摄像头而已

cvtColor(source_frame, gray_frame, CV_BGR2GRAY);//转换成灰度图像  
        GaussianBlur(gray_frame, gray_frame, Size(7,7), 1.5, 1.5,BORDER_DEFAULT); //高斯滤波 
Canny(gray_frame, gray_frame, 50, 150, 3); //边缘检测 内部用到sobel计算梯度 可以调整阈值 想想怎么弄成自动阈值
//Hough变换
//检测直线,最小投票为50,线条不短于50,间隙不小于20
HoughLinesP( gray_frame, lines,1,CV_PI/360,minVotenum,50,20);
//找出目标直线 并计算角度 距离
if(findColoredTape(lines,resultlines))
{
drawDetectLines(source_frame,resultlines,Scalar(0,0,255));//画线

if((lines.size()>10)&&(minVotenum<200))
{
minVotenum++;
}
}
else
{
if(minVotenum>20)
{
minVotenum--;
}
//drawDetectLines(source_frame,lines,Scalar(0,255,0));//画线
}

display_information(source_frame,frame_width,frame_height, lines.size(),countAngel(resultlines),countLocation(resultlines));
        imshow("视频",source_frame);
//imshow("灰度视频",gray_frame);

if(waitKey(30) >=0)  
            stop = true;  
    }  
return 0;
}

findtape.h

#ifndef _FINDTAPE_H
#define _FINDTAPE_H
 
#include <opencv2/core/core.hpp>

using namespace cv;
using namespace std;

void drawDetectLines(Mat& image,const vector<Vec4i>& lines,Scalar & color);//画线
float countAngel(vector<Vec4i>& resultlines);
Point countLocation(vector<Vec4i>& resultlines);

uchar findColoredTape(vector<Vec4i>& sourcelines,vector<Vec4i>& resultlines);
void display_information(Mat Frame,int width,int height,int linesnum,float angle,Point location);//在视频里显示信息

#endif

findtape.cpp

#include "stdafx.h"
#include "findtape.h"
#include<iostream>  
#include <opencv2/opencv.hpp>  
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include "stdio.h"
#include "math.h"

double ParallelThreshold=0.2;//平行阈值,小于这个值认为是平行 0-1 越小要求越高
double intersectThreshold=0.3;//相交阈值,大于这个值认为是相交 0-1 越大要求越高

//画直线,将目标的两条直线用红色。其余用绿色
void drawDetectLines( Mat& image,const vector<Vec4i>& lines,Scalar & color)
{
    
// 将检测到的直线在图上画出来
vector<Vec4i>::const_iterator it=lines.begin();
while(it!=lines.end())
{
Point pt1((*it)[0],(*it)[1]);
Point pt2((*it)[2],(*it)[3]);
line(image,pt1,pt2,color,2); 
//  线条宽度设置为2
++it;
}
}

//比较两条直线的长度
bool compareLine(Vec4i line1,Vec4i line2)
{
long int length1,length2;
length1= (line1[0]-line1[2])*(line1[0]-line1[2])+(line1[1]-line1[3])*(line1[1]-line1[3]);
length2= (line2[0]-line2[2])*(line2[0]-line2[2])+(line2[1]-line2[3])*(line2[1]-line2[3]);
if(length1>length2)
return 1;
else
return 0;
}
//判断两条直线是否平行
bool judgeParallel(Vec4i line1,Vec4i line2)
{
double slope1,slope2,slope3;//斜率
slope1=abs(line1[0]-line1[2]) / (abs(line1[1]-line1[3])+1);//两条直线的斜率
slope2=abs(line2[0]-line2[2]) / (abs(line2[1]-line2[3])+1);
slope3=abs(line1[0]-line2[0]) / (abs(line1[1]-line2[1])+1);//第一条直线的第一个点和第二条直线的第一个点,判断是否在延长线上
if((abs(slope1-slope2)<ParallelThreshold)&&(abs(slope1-slope3)>intersectThreshold))//这两个阈值可以改变
{
return 1;
}
else
{
return 0;
}
}

//找出色带
uchar findColoredTape(vector<Vec4i>& sourcelines,vector<Vec4i>& resultlines)
{
Vec4i temp;
int compare_lines;//进行比较的线的条数

//进行比较的直线数 最多为 compare_lines条
if(sourcelines.size()>=2)
{
compare_lines=sourcelines.size();
}
else
{
return 0;
}

//冒泡排序
//将所有直线按长度排序
for(int i=0;i<compare_lines-1;++i)
{
for(int j=i+1;j<compare_lines;++j)
{
//判断长度
if(compareLine(sourcelines[j],sourcelines[i])==1)
{
//容器类型的赋值
temp=sourcelines[i];
sourcelines[i] = sourcelines[j];
sourcelines[j]=temp;
}
}
}

//若检测到的直线数大于等于2,则取长度最长的compare_lines条两两进行匹配
//找出最接近平行,不是延长线,总长度最长的两条直线
for(int i=0;i<compare_lines-1;++i)
{
for(int j=i+1;j<compare_lines;++j)
{
if(judgeParallel(sourcelines[i],sourcelines[j]))
{
resultlines.clear();
resultlines.push_back(sourcelines[i]);
resultlines.push_back(sourcelines[j]);
return 1;
}
}
}
return 0;
}

float countAngel(vector<Vec4i>& resultlines)
{
float angle;
if(resultlines.size()==2)
{
Vec4i line;
float x,y;
line[0]=(resultlines[0][0]+resultlines[1][0])/2;
line[1]=(resultlines[0][1]+resultlines[1][1])/2;
line[2]=(resultlines[0][2]+resultlines[1][2])/2;
line[3]=(resultlines[0][3]+resultlines[1][3])/2;
x=line[0]-line[2];
y=line[1]-line[3];
angle=atan2f(y,x)*180/CV_PI-90;
if(angle<-180)
{
angle+=180;
}
else if(angle>180)
{
angle-=180;
}
return angle;
}
else
{
return 0;
}
}

//计算位置
Point countLocation(vector<Vec4i>& resultlines)
{
Point location;
if(resultlines.size()==2)
{
location.x=(resultlines[0][0]+resultlines[0][2]+resultlines[1][0]+resultlines[1][2])/4;
location.y=(resultlines[0][1]+resultlines[0][3]+resultlines[1][1]+resultlines[1][3])/4;
return location;
}
else
{
location.x=0;
location.y=0;
return location;
}
}

//在视频里显示信息
void display_information(Mat Frame,int width,int height,int linesnum,float angle,Point location)
{
    char strFrameSize[30],strLineNum[20],Angle[20];

//显示直线 信息
sprintf_s(strLineNum, "strLineNum: %0d",linesnum);
putText(Frame,strLineNum,Point(0,20),2,1,CV_RGB(25,200,25));

sprintf_s(Angle, "Angle: %.2f ",angle);
    putText(Frame,Angle,Point(0,50),2,1,CV_RGB(25,200,25));

if(location.x>width/2)
{
putText(Frame,"Right",Point(0,80),2,1,CV_RGB(25,200,25));
}
else
{
putText(Frame,"left",Point(0,80),2,1,CV_RGB(25,200,25));
}
}

效果如下:

检测的效果还可以,不足有以下几个:

1.没有进行颜色检测,所以遇到多条平行线的时候会检测错误

2.虽然阈值选择会自动改变,但是有时候还是会检测不出边缘

3. 对光线要求较强,在房间里比较暗效果不好

OPENCV实现色带检测相关推荐

  1. 使用Python,OpenCV和Scikit-Image检测低对比度图像

    使用Python,OpenCV和Scikit-Image检测低对比度图像 1. 效果图 2. 原理 3. 源码 参考 这篇博客将介绍如何使用Python,OpenCV和Scikit-Image检测低对 ...

  2. python目标检测与识别_Python 使用Opencv实现目标检测与识别的示例代码

    在上章节讲述到图像特征检测与匹配 ,本章节是讲述目标检测与识别.后者是在前者的基础上进一步完善. 在本章中,我们使用HOG算法,HOG和SIFT.SURF同属一种类型的描述符.功能代码如下: impo ...

  3. 仅使用OpenCV实现活体检测!(附源码)

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 我们先来看一个网络留言 △ 来自虾米妈咪 小朋友用妈妈的一寸照片通 ...

  4. OpenCV直线拟合检测

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:opencv学堂 OpenCV直线拟合检测 霍夫直线检测 ...

  5. 10分钟学会使用YOLO及Opencv实现目标检测

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:新机器视觉 计算机视觉领域中,目标检测一直是工业应用上比 ...

  6. 使用opencv训练目标检测模型基于cascade模型

    使用opencv训练目标检测模型基于cascade模型 基于Haar特征的cascade分类器(classifiers) 是Paul Viola和 Michael Jone在2001年,论文" ...

  7. Python图像处理,cv2模块,OpenCV实现人脸检测蔡徐坤

    前言 利用Python实现OpenCV实现人脸检测,废话不多说~ 让我们愉快地开始吧~ 开发工具 Python版本: 3.6.4 相关模块: cv2模块: 以及一些Python自带的模块. 环境搭建 ...

  8. flutter 人脸检测_【转载】opencv实现人脸检测

    全文转载自CSDN的博客(不知道怎么将CSDN的博客转到博客园,应该没这功能吧,所以直接复制全文了),转载地址如下 http://blog.csdn.net/lsq2902101015/article ...

  9. opencv 图像阴影检测

    opencv 图像阴影检测  GarfieldEr007 2017-01-09  原文 参数说明: IplImage *workImg-当前全局变量,表示正在显示的图片. downleft, upri ...

最新文章

  1. 7 虚拟磁盘恢复虚拟机
  2. 关于String.Intern()的一道题
  3. 基于@Bean声明lazy-queue
  4. datatable 动态显示/隐藏列
  5. Unity3D 学习教程 14 C# 旋转镜头
  6. 华为全场景AI计算框架MindSpore正式开源,赋能开发者昇腾万里
  7. shiro身份验证失败捕获的异常对应信息
  8. MatConvnet工具箱文档翻译理解三
  9. 超小型遥控直升机飞行姿态稳定器的设计
  10. 超级炫酷个人引导页自适应HTML源码
  11. 斐讯n1 无线打印服务器,斐讯N1 设置旁路由(网关)的方法 | nas2x
  12. (超详细)手把手带你爬取南邮毛概马原思修题库
  13. 动态路由和tab页切换路由
  14. 2411681-89-3,Thalidomide-O-amido-PEG4-azide是一种PROTAC连接剂,通过点击化学与炔烃或DBCO、BCN连接的分子反应
  15. 北大暑期学校学习总结
  16. 考研专业课,到底要不要报辅导班?
  17. Markdown文本编辑
  18. 母亲从大专到考上985高校全日制博士,成了儿子的“学妹”
  19. 天美服务器维护,王者荣耀出现锦鲤Bug?莫名其妙送英雄和皮肤,玩家:天美成熟了...
  20. linux时间同步命令shell,LINUX时间同步脚本或命令

热门文章

  1. RNA-ATTO 390|RNA-ATTO 425|RNA-ATTO 465|RNA-ATTO 488|RNA-ATTO 495|RNA-ATTO 520近红外荧光染料标记核糖核酸RNA
  2. fishhook-动态修改MachO文件
  3. 【程序员股民系列】如何用python, pandas, numpy, matplotlib绘制每日个股成交额图
  4. 赛车自行车什么牌子好辐轮王土拨鼠全世界碳纤维自行车品牌排行榜
  5. android手机性能优化,安卓手机性能怎么优化 安卓手机性能方法汇总
  6. 台式计算机用u盘给电脑安装系统,如何在台式计算机上用U盘重新安装Win7系统
  7. [LTTng学习之旅]------环境搭建
  8. 理解锁相环的工作原理
  9. LuoguP1240 诸侯安置
  10. could not load library cudnn_ops_infer64_8.dll. Error code 126