目标: 利用opencv图像识别技术实现从摄像头视频中自动识别飞机门开关动作。
相关技术:OpenCV,图像识别,C++。
实现基本原理:通过识别飞机舱门上的小圆窗位置变化来判断门状态。
效果图片:
核心代码:
//检测圆窗,返回检测到的圆心坐标值
Point houghCircleDetec(Mat frame) {
Mat roiImage(frame, Rect(X, Y, WIDTH, HEIGHT));
Mat grayImage;
cvtColor(roiImage, grayImage, CV_BGR2GRAY);
vector<Vec3f> circles;
//霍夫圆检测
HoughCircles(grayImage, circles, CV_HOUGH_GRADIENT, 1.5, 20, 200, 75, 20, 35);
//绘制出检测到的圆
if (isDebug) {
for (size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0])+X, cvRound(circles[i][1])+Y);
int radius = cvRound(circles[i][2]);
circle(frame, center, radius, Scalar(155, 50, 255), 1, 8, 0);
putText(frame,to_string(radius),center,FONT_HERSHEY_PLAIN,6,Scalar(255,100,40),1,8,false);
}
}
if (circles.size() > 0) {
Point center(cvRound(circles[0][0]), cvRound(circles[0][1]));
return center;
}
else
{
Point temp(0, 0);
return temp;
}
}
/**
*滑动门状态检测
*@param values 圆心坐标值集合
*@return 门的状态值
*/
int doorStyle_centerPoint(queue<int> values)
{
int firstX = values.front();
int lastX = values.back();
int subtractionValue = firstX - lastX;
if (subtractionValue > 100)
return OPEN;
else if (subtractionValue < -100) {
return CLOSE;
}
return UNKNOW;
}
/**门状态识别
*@param f 回调函数
*@param videoName 为视频文件的全名称
*@return 返回运行结果值。
*/
int DoorRecognition(callback_t f, const char* videoName)
{
VideoCapture capture;
capture.open(videoName);
if (!capture.isOpened())
{
cout << "视频不能打开\n";
return 0;
}
// deque<int> deqCircleCenterpoints;
queue<int> queueDebugData;
bool isOk = false;
int style = 0;
for (;;)
{
Mat frame;
capture >> frame;
if (frame.empty())
{
break;
}
//绘制检测的ROI矩形框边界
if(isDebug)
rectangle(frame, Rect(X, Y, WIDTH, HEIGHT), Scalar(255, 0, 255));
if (!isOk) {
//进行霍夫圆检测
Point centerPoint = houghCircleDetec(frame);
if (centerPoint.x == 0 && centerPoint.y == 0) {//没有检测到圆
//进行圆形拱形检测
}
else {//检测到圆
queueDebugData.push(centerPoint.x);
int doorStyle = doorStyle_centerPoint(queueDebugData);
if (doorStyle > 0)
isOk = true;
/*
deqCircleCenterpoints.push_back(centerPoint.x);
if (deqCircleCenterpoints.size() > 40)
{
deqCircleCenterpoints.pop_front();
}
*/
}
}
if (isOk) {
f(style);
//break;
}
imshow("frame", frame);
if (waitKey(30) >= 0) break;
}
//显示圆心数据序列内容
if (isDebug)
{
int pointNum = queueDebugData.size();
for (size_t i = 0; i < pointNum; i++)
{
double temp= queueDebugData.front();
cout << temp<< endl;
queueDebugData.pop();
}
}
waitKey(0);
capture.release();
return 1;
}
实现缺陷:图片识别之前没有经过滤波处理,判断条件过于单一,容易误判等。