반응형

이전 포스팅에서 다루었던 이미지에서 도형을 검출하는 예제 코드를 웹캠 기반으로 수정하여 테스트해 본 과정을 설명합니다.



OpenCV 사용해서 실시간으로 도형 검출하기(shape detection) 1 / 2 -  이미지에서 검출

http://webnautes.tistory.com/1097


OpenCV 사용해서 실시간으로 도형 검출하기(shape detection) 2 / 2 -  웹캠에서 검출




2016. 12. 29   최초 작성

2018.   6. 30 도형 판정하는 방법 변경(  내각 체크 → Convex polygon 여부 검사 )

                      webcam으로 테스트 추가




프린트한 이미지에 있는 도형들을 검출해본 테스트  결과입니다.












이전 포스팅에서 사용했던 도형 검출 코드를 수정하여  웹캠에서 가져온 이미지를 사용하도록 했습니다.

다음 부분들이 변경되었습니다.


  • 이진화 방법을 adaptiveThreshold 함수로 변경

  • GaussianBlur 함수 추가

  • 노란색과 연두색 도형이 인식이 잘안되어 색깔 변경


parameter 1,  2, 3은 테스트시 이 값들을 조정하면 더 좋은 결과를 얻을 수 있을 거 같아 추가한 주석입니다.



웹캠으로부터 영상가져오는 기본 코드는 아래 소스 코드를 참고하였습니다.

https://github.com/opencv/opencv/blob/master/samples/cpp/videocapture_basic.cpp



#include "opencv2/opencv.hpp"
#include <iostream>  
#include <string>


using namespace cv;
using namespace std;



//Contour 영역 내에 텍스트 쓰기
//https://github.com/bsdnoobz/opencv-code/blob/master/shape-detect.cpp
void setLabel(Mat& image, string str, vector<Point> contour)
{
int fontface = FONT_HERSHEY_SIMPLEX;
double scale = 0.5;
int thickness = 1;
int baseline = 0;

Size text = getTextSize(str, fontface, scale, thickness, &baseline);
Rect r = boundingRect(contour);

Point pt(r.x + ((r.width - text.width) / 2), r.y + ((r.height + text.height) / 2));
rectangle(image, pt + Point(0, baseline), pt + Point(text.width, -text.height), CV_RGB(200, 200, 200), FILLED);
putText(image, str, pt, fontface, scale, CV_RGB(0, 0, 0), thickness, 8);
}



int main(int, char**)
{
Mat img_input, img_result, img_gray;


//--- INITIALIZE VIDEOCAPTURE
VideoCapture cap;
// open the default camera using default API
// cap.open(0);
// OR advance usage: select any API backend
int deviceID = 0;             // 0 = open default camera
int apiID = cv::CAP_ANY;      // 0 = autodetect default API
     // open selected camera using selected API
cap.open(deviceID + apiID);
// check if we succeeded
if (!cap.isOpened()) {
cerr << "ERROR! Unable to open camera\n";
return -1;
}



for (;;)
{

cap.read(img_input);
// check if we succeeded
if (img_input.empty()) {
cerr << "ERROR! blank frame grabbed\n";
break;
}


Mat img_temp;
//그레이스케일 이미지로 변환  
cvtColor(img_input, img_temp, COLOR_BGR2GRAY);
GaussianBlur(img_temp, img_temp, Size(5, 5), 0, 0);   


//이진화 이미지로 변환
adaptiveThreshold(img_temp, img_gray,
255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV,
201, 7);                                  // <-----------------------   parameter 1, 2


//contour를 찾는다.
vector<vector<Point> > contours;
findContours(img_gray, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);

//contour를 근사화한다.
vector<Point2f> approx;
img_result = img_input.clone();

for (size_t i = 0; i < contours.size(); i++)
{
approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);

if (fabs(contourArea(Mat(approx))) > 1000 && fabs(contourArea(Mat(approx)))< 10000)  // <-----------------------   parameter 3
{

int size = approx.size();
const char *name[]= { "none", "none", "none", "triangle", "quadrangle", "pentagon", "hexagon", "heptagon", "octagon", "nonagon", "decagon"  };

switch (size){

case 3: case 4: case 5:
case 6: case 10:
if (isContourConvex(Mat(approx))) { // convex 인지 검사


//Contour를 근사화한 직선을 그린다.
if (size % 2 == 0) {
line(img_result, approx[0], approx[approx.size() - 1], Scalar(0, 255, 0), 3);

for (int k = 0; k < size - 1; k++)
line(img_result, approx[k], approx[k + 1], Scalar(0, 255, 0), 3);

for (int k = 0; k < size; k++)
circle(img_result, approx[k], 3, Scalar(0, 0, 255));
}
else {
line(img_result, approx[0], approx[approx.size() - 1], Scalar(0, 255, 0), 3);

for (int k = 0; k < size - 1; k++)
line(img_result, approx[k], approx[k + 1], Scalar(0, 255, 0), 3);

for (int k = 0; k < size; k++)
circle(img_result, approx[k], 3, Scalar(0, 0, 255));
}

//검출된 도형에 대한 라벨을 출력한다.

setLabel(img_result, name[size], contours[i]);
}

break;



deafult:

break;
}


}



}


// show window and wait for a key with timeout long enough to show images
imshow("result", img_result);
imshow("binary", img_gray);

if (waitKey(5) == 27) //ESC 키 누를 때 까지 대기
break;

}

return 0;
}





문제 발생시 지나치지 마시고 댓글 남겨주시면 가능한 빨리 답장드립니다.


제가 쓴 책도 한번 검토해보세요 ^^

+ Recent posts