目標: 利用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;
}
實現缺陷:圖片識別之前沒有經過濾波處理,判斷條件過於單一,容易誤判等。