日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

OPENCV实现色带检测

發(fā)布時(shí)間:2024/3/12 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OPENCV实现色带检测 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

今天在家無(wú)聊,終于有時(shí)間寫下我的第一篇CSDN博客啦,前段時(shí)間幫一個(gè)老師做一個(gè)項(xiàng)目,用攝像頭檢測(cè)地上的色帶,輸出角度幫助機(jī)器人尋跡。就想到用opencv來(lái)做,可以我不會(huì)啊,怎么辦?看唄。這里對(duì)opencv點(diǎn)個(gè)贊!函數(shù)通俗易懂,環(huán)境配置也比較簡(jiǎn)單,英語(yǔ)閱讀能力好的人都不用買書(shū)的,看文檔就可以用得飛起啊~~

看了幾天就把程序?qū)懞昧?#xff0c;用得不好大家不喜勿碰,思路如下:


程序如下:

// camera.cpp : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。
//
#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);//打開(kāi)一個(gè)攝像頭 ?
VideoCapture cap1(1);//打開(kāi)一個(gè)攝像頭 筆記本必須要兩個(gè),否則打不開(kāi)外置攝像頭
vector<Vec4i> lines,resultlines;//存儲(chǔ)視頻中直線的起點(diǎn)和終點(diǎn)
Mat source_frame,source_frame1,gray_frame;//新建兩幀圖像?
int frame_width,frame_height;
namedWindow("視頻",WINDOW_AUTOSIZE);//新建一個(gè)圖像窗口


? ? if(!cap0.isOpened()) //判斷是否打開(kāi)?
? ? { ?
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);//新建一個(gè)圖像窗口
? ? bool stop = false; ?
? ? while(!stop) ?
? ? { ?
? ? ? ? cap0>>source_frame;//從視頻一副圖片?
cap1>>source_frame1;//從視頻一副圖片 ?這句沒(méi)用的,為了打開(kāi)外置攝像頭而已

cvtColor(source_frame, gray_frame, CV_BGR2GRAY);//轉(zhuǎn)換成灰度圖像 ?
? ? ? ? GaussianBlur(gray_frame, gray_frame, Size(7,7), 1.5, 1.5,BORDER_DEFAULT); //高斯濾波?
Canny(gray_frame, gray_frame, 50, 150, 3); //邊緣檢測(cè) 內(nèi)部用到sobel計(jì)算梯度 可以調(diào)整閾值 想想怎么弄成自動(dòng)閾值
//Hough變換
//檢測(cè)直線,最小投票為50,線條不短于50,間隙不小于20
HoughLinesP( gray_frame, lines,1,CV_PI/360,minVotenum,50,20);
//找出目標(biāo)直線 并計(jì)算角度 距離
if(findColoredTape(lines,resultlines))
{
drawDetectLines(source_frame,resultlines,Scalar(0,0,255));//畫(huà)線


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


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);//畫(huà)線
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;//平行閾值,小于這個(gè)值認(rèn)為是平行 0-1 越小要求越高
double intersectThreshold=0.3;//相交閾值,大于這個(gè)值認(rèn)為是相交 0-1 越大要求越高


//畫(huà)直線,將目標(biāo)的兩條直線用紅色。其余用綠色
void drawDetectLines( Mat& image,const vector<Vec4i>& lines,Scalar & color)
{
? ??
// 將檢測(cè)到的直線在圖上畫(huà)出來(lái)
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);?
// ?線條寬度設(shè)置為2
++it;
}
}


//比較兩條直線的長(zhǎng)度
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);//第一條直線的第一個(gè)點(diǎn)和第二條直線的第一個(gè)點(diǎn),判斷是否在延長(zhǎng)線上
if((abs(slope1-slope2)<ParallelThreshold)&&(abs(slope1-slope3)>intersectThreshold))//這兩個(gè)閾值可以改變
{
return 1;
}
else
{
return 0;
}
}




//找出色帶
uchar findColoredTape(vector<Vec4i>& sourcelines,vector<Vec4i>& resultlines)
{
Vec4i temp;
int compare_lines;//進(jìn)行比較的線的條數(shù)


//進(jìn)行比較的直線數(shù) 最多為 compare_lines條
if(sourcelines.size()>=2)
{
compare_lines=sourcelines.size();
}
else
{
return 0;
}

//冒泡排序
//將所有直線按長(zhǎng)度排序
for(int i=0;i<compare_lines-1;++i)
{
for(int j=i+1;j<compare_lines;++j)
{
//判斷長(zhǎng)度
if(compareLine(sourcelines[j],sourcelines[i])==1)
{
//容器類型的賦值
temp=sourcelines[i];
sourcelines[i] = sourcelines[j];
sourcelines[j]=temp;
}
}
}


//若檢測(cè)到的直線數(shù)大于等于2,則取長(zhǎng)度最長(zhǎng)的compare_lines條兩兩進(jìn)行匹配
//找出最接近平行,不是延長(zhǎng)線,總長(zhǎng)度最長(zhǎng)的兩條直線
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;
}
}


//計(jì)算位置
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));
}
}

效果如下:


檢測(cè)的效果還可以,不足有以下幾個(gè):

1.沒(méi)有進(jìn)行顏色檢測(cè),所以遇到多條平行線的時(shí)候會(huì)檢測(cè)錯(cuò)誤

2.雖然閾值選擇會(huì)自動(dòng)改變,但是有時(shí)候還是會(huì)檢測(cè)不出邊緣

3. 對(duì)光線要求較強(qiáng),在房間里比較暗效果不好

總結(jié)

以上是生活随笔為你收集整理的OPENCV实现色带检测的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。