설명

마우스로 상자를 만들면, 그 상자에 있는 도형을 Detection해준다.
아직까지는 삼각형, 사각형, 오각형, 육각형, 원만 Detection해준다.

코드

#include "opencv2/opencv.hpp"  

#include <iostream>  

#include <string.h>


using namespace cv;

using namespace std;



bool ldown = false, lup = false;

Mat img_input, img_gray;

Point corner1, corner2;

Rect box;


char * name = "polygons";


Point2f weightCenter(vector<Point> contour);

float distance(Point2f a, Point2f b);

int GetAngle(Point a, Point b, Point c);

void detection(String name, int size, Mat img_result, vector<Point2f> approx, vector<vector<Point>> contours, int index);

void polygonDetection(Mat img_input);

static void mouse_callback(int event, int x, int y, int, void* param);



//무게중심

Point2f weightCenter(vector<Point> contour) {

Point2f result;


for (int i = 0; i < contour.size(); i++) {

result.x += contour[i].x;

result.y += contour[i].y;

}

result.x /= contour.size();

result.y /= contour.size();


return result;

}



//거리구하기

float distance(Point2f a, Point2f b) {

return sqrt(pow(abs(a.x - b.x), 2) + pow(abs(a.y - b.y), 2));

}


//세 점이 주어질 때 사이 각도 구하기

int GetAngle(Point a, Point b, Point c)

{

Point ab = { b.x - a.x, b.y - a.y };

Point cb = { b.x - c.x, b.y - c.y };


float dot = (ab.x * cb.x + ab.y * cb.y); // dot product

float cross = (ab.x * cb.y - ab.y * cb.x); // cross product


float alpha = atan2(cross, dot);


return (int)floor(alpha * 180.0 / CV_PI + 0.5);

}


//변의 길이

void detection(String name, int size, Mat img_result, vector<Point2f> approx, vector<vector<Point>> contours, int index) {

cout << name << endl;

int last = 0;

for (int k = 0; k < size - 1; k++) {

line(img_result, approx[k], approx[k + 1], Scalar(0, 255, 0), 3);

cout << "lenght : [" << k << "] : " << distance(approx[k], approx[k + 1]) << endl;

last = k;

}


line(img_result, approx[0], approx[approx.size() - 1], Scalar(0, 255, 0), 3);

cout << "lenght : [" << size - 1 << "]" << " : " << distance(approx[0], approx[approx.size() - 1]) << endl;

cout << "weight Center : " << weightCenter(contours[index]) << endl;

}


//도형 Detection

void polygonDetection(Mat img_input) {


cvtColor(img_input, img_gray, COLOR_BGR2GRAY);

threshold(img_gray, img_gray, 125, 255, THRESH_BINARY_INV | THRESH_OTSU);

vector<vector<Point>> contours;

findContours(img_gray, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);


//contour를 근사화한다.

Mat img_result;

img_result = img_input.clone();


vector<Point2f> approx;

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))) > 10) {

int size = approx.size();


vector<int> angle;


for (int k = 0; k < size; k++) {

int ang = GetAngle(approx[k], approx[(k + 1) % size], approx[(k + 2) % size]);

angle.push_back(ang);

}


sort(angle.begin(), angle.end());


int minAngle = angle.front();

int maxAngle = angle.back();

int threshold = 50;


//도형을 판정

if (size == 3 && (minAngle >= 0 - threshold && maxAngle <= 90 + threshold)) {

detection("traingle", size, img_result, approx, contours, i);

}

else if (size == 4 && minAngle >= 90 - threshold && maxAngle <= 90 + threshold) {


detection("rectangle", size, img_result, approx, contours, i);

}

else if (size == 5 && minAngle >= 108 - threshold && maxAngle <= 108 + threshold) {

detection("pentagon", size, img_result, approx, contours, i);


}

else if (size >= 6 && minAngle >= 120 - threshold && maxAngle <= 120 + threshold) {

cout << "circle" << endl;

cout << "Center : " << weightCenter(contours[i]) << endl;

cout << "radius : " << distance(weightCenter(contours[i]), approx[0]) << endl;

circle(img_result, weightCenter(contours[i]), distance(weightCenter(contours[i]), approx[0]),                                                                                                                                  Scalar(0, 255, 0), 3);

}

printf("\n");

}

}

destroyWindow("Detection Polygons");

namedWindow("Detection Polygons", WINDOW_AUTOSIZE);

imshow("Detection Polygons", img_result);

}


static void mouse_callback(int event, int x, int y, int, void* param) {

if (event == EVENT_LBUTTONDOWN) {

ldown = true;

corner1.x = x;

corner1.y = y;

}

if (event == EVENT_LBUTTONUP) {

if (abs(x - corner1.x) > 20 && abs(y - corner1.y) > 20) {

lup = true;

corner2.x = x;

corner2.y = y;

}

else {

ldown = false;

}

}

if (ldown == true && lup == false) {

Point pt;

pt.x = x;

pt.y = y;


Mat locale_img = img_input.clone();


rectangle(locale_img, corner1, pt, Scalar(255, 0, 0));

imshow(name, locale_img);

}


if (ldown == true && lup == true) {

box.width = abs(corner1.x - corner2.x);

box.height = abs(corner1.y - corner2.y);


box.x = min(corner1.x, corner2.x);

box.y = min(corner1.y, corner2.y);


Mat crop(img_input, box);

polygonDetection(crop);



ldown = false; lup = false;

}

}



int main(int args, char *argv[]){

img_input = imread("polygons/all_pologon.png", CV_LOAD_IMAGE_COLOR);

if (img_input.empty())

{

cout << "Could not open or find the image" << std::endl;

return -1;

}

namedWindow(name, WINDOW_AUTOSIZE);

imshow(name, img_input);

setMouseCallback(name, mouse_callback);

waitKey(0);


return 0;

}


결과영상




'Programming > openCV' 카테고리의 다른 글

사진 인식  (0) 2017.04.22
open cv 요약  (0) 2017.04.18
BGR별 히스토그램 구하기  (0) 2017.04.11
vector에 접근하는 두가지 방법  (0) 2017.04.11
13. Hough Circles  (0) 2017.04.04

코드

#include <opencv2/opencv.hpp>

#include <opencv2/highgui.hpp>


using namespace cv;

using namespace std;


int x_ = 0;

int y_ = 0;


Mat tImage1; Mat tImage2; Mat tImage3; Mat tImage4;

Mat dstImage; Mat srcImage;



void find() {


double minVal, maxVal;

Point minLoc, maxLoc;

Mat result;


matchTemplate(srcImage, tImage1, result, TM_CCOEFF_NORMED);

minMaxLoc(result, NULL, &maxVal, NULL, &maxLoc);



if (maxLoc.x <= x_

&& maxLoc.y <= y_

&& maxLoc.x + tImage1.cols >= x_

&& maxLoc.y + tImage1.rows >= y_) {

printf("A \n");

}



matchTemplate(srcImage, tImage2, result, TM_CCOEFF_NORMED);

minMaxLoc(result, NULL, &maxVal, NULL, &maxLoc);


if (maxLoc.x <= x_

&& maxLoc.y <= y_

&& maxLoc.x + tImage1.cols >= x_

&& maxLoc.y + tImage1.rows >= y_) {

printf("S \n");

}



matchTemplate(srcImage, tImage3, result, TM_CCOEFF_NORMED);

minMaxLoc(result, NULL, &maxVal, NULL, &maxLoc);


if (maxLoc.x <= x_

&& maxLoc.y <= y_

&& maxLoc.x + tImage1.cols >= x_

&& maxLoc.y + tImage1.rows >= y_) {

printf("b \n");

}



matchTemplate(srcImage, tImage4, result, TM_CCOEFF_NORMED);

minMaxLoc(result, NULL, &maxVal, NULL, &maxLoc);


if (maxLoc.x <= x_

&& maxLoc.y <= y_

&& maxLoc.x + tImage1.cols >= x_

&& maxLoc.y + tImage1.rows >= y_) {

printf("m \n");

}


}


static void mouse_callback(int event, int x, int y, int, void* param) {


if (event == EVENT_LBUTTONDOWN) {

x_ = x;

y_ = y;

find();

}

}



int main()

{

srcImage = imread("image4/alphabet.bmp", CV_LOAD_IMAGE_GRAYSCALE);

if (srcImage.empty())

return -1;


tImage1 = imread("image4/A.bmp", CV_LOAD_IMAGE_GRAYSCALE);

tImage2 = imread("image4/S.bmp", CV_LOAD_IMAGE_GRAYSCALE);

tImage3 = imread("image4/b.bmp", CV_LOAD_IMAGE_GRAYSCALE);

tImage4 = imread("image4/m.bmp", CV_LOAD_IMAGE_GRAYSCALE);


cvtColor(srcImage, dstImage, COLOR_GRAY2BGR);


imshow("dstImage", dstImage);

setMouseCallback("dstImage", mouse_callback);


waitKey();

return 0;

}


코드해석

인식할 문자(A,S,b,m)와 전체 영상(alphabet)을 load하여 마우스 콜백이 일어나면 템플릿 매칭을 시킨다.

인식한 영상의 MinLoc과 MaxLoc을 알아와서 영역을 설정해준다.

그리고 마우스 좌표가 해당영역안이면 콘솔에 문자를 입력한다.



마우스의 영역을 찾는것이 이 문제의 해결 방법인것 같다.


결과화면


'Programming > openCV' 카테고리의 다른 글

polygon Detection  (0) 2017.05.03
open cv 요약  (0) 2017.04.18
BGR별 히스토그램 구하기  (0) 2017.04.11
vector에 접근하는 두가지 방법  (0) 2017.04.11
13. Hough Circles  (0) 2017.04.04

이미지 읽기 &저장

Mat img_color = imread("sample.jpg"); // color load

Mat img_gray = imread("sample.jpg", 0); // gray load

imwrite("fname.jpg", img);


이미지 생성, 복사, 형변환, 색상변환, roi 설정

int w = 320; // width

int h = 240; // height


// 생성

Mat img(h,w,CV_8UC1);                    //1채널 unsigned char

Mat img(h,w,CV_8UC3);                    //3채널 unsigned char

Mat img = Mat::zeros(h,w,CV_32FC1);//1채널 float

Mat img = Mat::ones(h,w,CV_64FC3);//3채널 double


unsigned char * img_buffer;            // 이미지버퍼 포인터

Mat img(h, w, CV_8UC3, img_buffer);//메모리 공유


// 원소 초기화

Mat img(h,w,CV_8UC1);

img = Scalar(3);                 // img 모든 원소값 3으로 초기화


// 참조, 복사

Mat img2 = img;                 // 메모리 공유

Mat img2 = img.clone();       // 별도 메모리

Mat img2; img.copyTo(img2);//별도 메모리


// 형변환 복사

Mat img1(h,w,CV_32FC1);

Mat img2;

img1.convertTo(img2, CV_8U);


// gray-color 변환

cvtColor(color, gray, CV_BGR2GRAY);

cvtColor(gray, color, CV_GRAY2BGR);


// roi 설정

Rect roi;

Mat sub_img = img(roi);                //메모리공유

Mat sub_img = img(roi).clone();    //별도메모리


영상 크기변경 및 상하좌우 반전

// 크기 변경

Mat dst;

resize(img, dst, Size(new_w,new_h));

resize(img, dst, Size(), 0.5, 0.5);    //scalex, scaley


// 영상 반전(flip)

flip(img, dst, 0);        // vertical flip

flip(img, dst, 1);        // horizontal flip

flip(img, dst, -1);       // vertial &horizontal flip


이미지에 그리기 (drawing)

Rect rc(x,y,w,h);

Scalar color(B,G,R);

int thickness=1;         // line thickness


line(img, Point(x1,y1), Point(x2,y2), color, thickness);


rectangle(img, rc, color, thickness);

rectangle(img, rc.tl(), rc.br(), color, thickness);

rectangle(img, rc, color, CV_FILLED);// filled rectangle


Point center(rc.x+rc.width/2, rc.y+rc.height/2);

Size radius(rc.width/2, rc.height/2);

double rot_deg = 0;     // rotation of ellipse

double s_deg = 0;     // start angle of arc

double e_deg = 360;     // end angle of arc

ellipse(img,center,radius,rot_deg,s_deg,e_deg,color,thickness);

ellipse(img,center,radius,rot_deg,s_deg,e_deg,color,CV_FILLED);


int circle_radius = 10;

circle(img, center, circle_radius, color, thickness);

circle(img, center, circle_radius, color, CV_FILLED);


putText(img, "text", Point(x,y), FONT_HERSHEY_SIMPLEX, 1., color, thickness);

putText(img, "text", Point(x,y), FONT_HERSHEY_DUPLEX, 1., color, thickness);


이미지 디스플레이하기 (display)

namedWindow("name");                                 // auto resized

namedWindow("name",CV_WINDOW_NORMAL); // manual resize


imshow("name", img);

char ch = waitKey();     // 무한 대기

char ch = waitKey(10);    // 10 msec 대기

if(ch == 27) ...             // ESC key

if(ch == 32) ...             // SPACE key


destroyWindow("name");

destroyAllWindows();


웹캠 연결하기

VideoCapture vc(0);

if (!vc.isOpened()) return; // 연결실패

vc.set(CV_CAP_PROP_FRAME_WIDTH, 640);

vc.set(CV_CAP_PROP_FRAME_HEIGHT, 480);


Mat img;

while(1){

vc >>img;

if(img.empty()) break;

imshow("cam",img);

if(waitKey(10)==27) break; //ESC

}

destroyAllWindows();


avi 비디오 파일 읽어오기

VideoCapture vc("sample.avi");

if (!vc.isOpened()) return; // 불러오기 실패


Mat img;

while(1){

vc >>img;

if(img.emplty()) break;

imshow("video",img);

if(waitKey(10)==27) break; //ESC

}

destroyAllWindows();


avi 비디오 녹화하기

double fps = 15;

int fourcc = CV_FOURCC('X','V','I','D'); // codec

bool isColor = true;


VideoWriter *video = new VideoWriter;

if(!video->open("result.avi", fourcc, fps, Size(img_w, img_h), isColor)){

delete video;

return;

}


Mat img;

while(1){

// ...

*video << img;

// ...

}

delete video;


Mat <--> IplImage

Mat --> IplImage

Mat matimg;

IplImage* iplimh;

iplimg = &IplImage(matimg);


IplImage --> Mat

IplImage* iplimg;

Mat matimg;

matimg(iplimg);


픽셀 접근법

  Mat image;

  

  // 3 channel Image


for(int j=0; j < image.rows; j++)

{

        for(int i=0; i < image.cols; i++)

        {

                 image.at<Vec3b> (j,i)[0] += 30;

                 image.at<Vec3b> (j,i)[1] += 20;

                 image.at<Vec3b> (j,i)[2] += 20;

 

        }

}


이때 Vec3b 는 unsigned char 형이다 

b(unsigned char) 외에도 s(short), i(int), f(float), d(double) 형의 벡터가 존재한다.


* 추가사항 *

cv::Mat클래스의 at메소드를 사용한다면 가끔은 성가실 수 있다. 행렬 타입을 알고 있다면 cv::Mat의 템플릿 하위 클래스인 cv::Mat_ 클래스를 사용할 수 있다.

 

cv::Mat_<uchar> im2 = image;  //im2는 image를 참조

im2(50,100) = 0; // 50행 100열 화소에 접근


출처: http://jangjy.tistory.com/21 [살다보니..]

'Programming > openCV' 카테고리의 다른 글

polygon Detection  (0) 2017.05.03
사진 인식  (0) 2017.04.22
BGR별 히스토그램 구하기  (0) 2017.04.11
vector에 접근하는 두가지 방법  (0) 2017.04.11
13. Hough Circles  (0) 2017.04.04

코드

#include<iostream>

#include<opencv2\core.hpp>

#include<opencv\cv.h>

#include<opencv2\highgui.hpp>

#include<opencv2\imgproc.hpp>


using namespace cv;

using namespace std;


int main(){


Mat inputImg = imread("image/humming_bird.jpg", CV_LOAD_IMAGE_COLOR);


MatND histogramB, histogramG, histogramR;

int channel_B[] = { 0 };  // Blue

int channel_G[] = { 1 };  // Green

int channel_R[] = { 2 };  // Red

float channel_range[2] = {0.0 , 255.0};

const float* channel_ranges[1] = { channel_range };

int histSize[1] = { 256 };


// R, G, B별로 각각 히스토그램을 계산한다.

calcHist(&inputImg, 1, channel_B, Mat(), histogramB, 1, histSize, channel_ranges);

calcHist(&inputImg, 1, channel_G, Mat(), histogramG, 1, histSize, channel_ranges);

calcHist(&inputImg, 1, channel_R, Mat(), histogramR, 1, histSize, channel_ranges);


// Plot the histogram

int hist_w = 512; int hist_h = 400;

int bin_w = cvRound((double)hist_w / histSize[0]);


Mat histImageB(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0));

normalize(histogramB, histogramB, 0, histImageB.rows, NORM_MINMAX, -1, Mat());


Mat histImageG(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0));

normalize(histogramG, histogramG, 0, histImageG.rows, NORM_MINMAX, -1, Mat());


Mat histImageR(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0));

normalize(histogramR, histogramR, 0, histImageR.rows, NORM_MINMAX, -1, Mat());


for (int i = 1; i < histSize[0]; i++)

{


line(histImageB, Point(bin_w*(i - 1), hist_h - cvRound(histogramB.at<float>(i - 1))),

Point(bin_w*(i), hist_h - cvRound(histogramB.at<float>(i))),

Scalar(255, 0, 0), 2, 8, 0);


line(histImageG, Point(bin_w*(i - 1), hist_h - cvRound(histogramG.at<float>(i - 1))),

Point(bin_w*(i), hist_h - cvRound(histogramG.at<float>(i))),

Scalar(0, 255, 0), 2, 8, 0);


line(histImageR, Point(bin_w*(i - 1), hist_h - cvRound(histogramR.at<float>(i - 1))),

Point(bin_w*(i), hist_h - cvRound(histogramR.at<float>(i))),

Scalar(0, 0, 255), 2, 8, 0);


}



namedWindow("Original", CV_WINDOW_AUTOSIZE);

namedWindow("HistogramB", CV_WINDOW_AUTOSIZE);

namedWindow("HistogramG", CV_WINDOW_AUTOSIZE);

namedWindow("HistogramR", CV_WINDOW_AUTOSIZE);


moveWindow("Original", 100, 100);

moveWindow("HistogramB", 110, 110);

moveWindow("HistogramG", 120, 120);

moveWindow("HistogramR", 130, 130);


imshow("Original", inputImg);

imshow("HistogramB", histImageB);

imshow("HistogramG", histImageG);

imshow("HistogramR", histImageR);


waitKey(0);

return 0;

}


결과




'Programming > openCV' 카테고리의 다른 글

사진 인식  (0) 2017.04.22
open cv 요약  (0) 2017.04.18
vector에 접근하는 두가지 방법  (0) 2017.04.11
13. Hough Circles  (0) 2017.04.04
iterator의 개념  (0) 2017.04.04

vector<Vec3f> circles;

  Vec3f vec;


for (int i = 0; i < circles.size(); i++) {

vec = circles[i];

int cx = vec[0];

int cy = vec[1];

int radius = vec[2];

printf("Circles[%d]: (cx , cy)= (%d , %d), r = %d\n", k++, cx, cy, radius);

circle(image, Point(cx, cy), radius, Scalar(0, 0, 255), 2);

}




  vector<Vec3f> circles;

vector<Vec3f>::const_iterator itc = circles.begin();

while (itc != circles.end()) {

int cx = (*itc)[0];

int cy = (*itc)[1];

int radius = (*itc)[2];

printf("Circles[%d]: (cx , cy)= (%d , %d), r = %d\n", k++, cx, cy, radius);

circle(image, Point(cx, cy), radius, Scalar(0, 0, 255), 2);

++itc;

}




같은 결과 값을 가진다.

'Programming > openCV' 카테고리의 다른 글

open cv 요약  (0) 2017.04.18
BGR별 히스토그램 구하기  (0) 2017.04.11
13. Hough Circles  (0) 2017.04.04
iterator의 개념  (0) 2017.04.04
12. Templet Matching  (0) 2017.04.04

vector<Vec3f> circles;

HoughCircles( src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows/8, 200, 100, 0, 0 );

with the arguments:

  • src_gray : 입력 영상(Gray Scale)
  • circles : A vector that stores sets of 3 values: x_{c}, y_{c}, r for each detected circle.
  • CV_HOUGH_GRADIENT : 검출 함수 정의. Currently this is the only one available in OpenCV
  • dp = 1 : 누적기 해상도 (영상 크기 /2)
  • min_dist = src_gray.rows/8 : 검출된 원간의 최소거리
  • param_1 = 200 : 캐니 최대 경계값
  • param_2 = 100* : Threshold for center detection.
  • min_radius = 0 : Minimum radio to be detected. If unknown, put zero as default.
  • max_radius = 0 : Maximum radius to be detected. If unknown, put zero as default




코드


#include <iostream>

#include <opencv2/core/core.hpp>

#include <opencv2/highgui/highgui.hpp>

#include <opencv2/imgproc/imgproc.hpp>



using namespace cv;

using namespace std;


int main()

{

Mat image;

image = imread("image4/circle2.jpg", CV_LOAD_IMAGE_COLOR);


vector<Vec3f> circles;

HoughCircles(

image, // 원본이미지 

circles, 

CV_HOUGH_GRADIENT,

1,   // 누적기 해상도(영상크기/2)

100, // 두 원 간의 최소 거리

100, // 캐니 최대 경계값

50 // 투표 최소 개수

);


cout << "circles.size()= " << circles.size() << endl;

vector<Vec3f>::const_iterator itc = circles.begin();

int k = 0;


while (itc != circles.end()) {


int cx = (*itc)[0];

int cy = (*itc)[1];

int radius = (*itc)[2];


printf("Circles[%d]: (cx , cy)= (%d , %d), r = %d\n", k++, cx, cy, radius);

circle(image, Point(cx, cy), radius, Scalar(0, 0, 255), 2);

++itc;

}


namedWindow("Detected Circles");

imshow("Detected Circles", image);


waitKey(0);


return 0;

}


결과




'Programming > openCV' 카테고리의 다른 글

BGR별 히스토그램 구하기  (0) 2017.04.11
vector에 접근하는 두가지 방법  (0) 2017.04.11
iterator의 개념  (0) 2017.04.04
12. Templet Matching  (0) 2017.04.04
11. Emboss, sketch, 수채화  (0) 2017.04.04

Iterator란

Iterator는 컨테이너의 원소들을 순회 할 수 있는 객체


반복자는 컨테이너의 특정 위치를 가리킴

반복자는 Pointer와 같이 연산자를 사용할 수 있는데 pointer와 비슷

 

operator *         :     현재 가리키고 있는 위치 값

operator ++      :     다음 원소

operator --        :     이전 원소

operator != , == :      두 반복자가 같은 위치를 가리키고 있는지

operator =         :     반복자를 할당합니다.

 

가만히 보면 pointer와 비슷해 보인다.. 좀 다르다고 할 수 있는건 복잡한 컨테이너를 순회할 수 있는 스마트포인터라는 것입니다. 나중에 예제로 보겠지만 컨테이너::iterator 로 지정해주면 지정한 컨테이너 타입에 맞춰 움직이다가 iterator 알아서 메모리 관리가 됩니다. 지정한 자료의 삭제 같은 것이 필요 없다는 것이죠.

 

컨테이너에 보면 가지고 있는 원소를 순회하기 위해 공통 멤버 함수가 있습니다. 간단하게

begin() 과 end()을 보도록 하죠.


 


여기꽤 중요한 것이 있는데 end()는 마지막을 하나 지난 위치 입니다.  이걸 half-open range(반 개방 범위)라고 하는데요 

2가지 장점이 있습니다. 꼭 장점만 있지는 않습니다.. 잘못처리 하면 문제일으킬 소지를 다분히 가지고 있습니다.

 

  1.원소를 순회하는 루프를 간단히 할 수 있다. end()에 다다르지 않았다면 계속해서 루프를 돌면 된다.

  2.빈 범위에 대해서 특별한 처리를 할 필요가 없다. 빈 컨테이너에 대해서 begin()과 end()는 동일하다.

 

이런 특성 때문에 for 문을 작성할 때


for(vector<char>::iterator a = c.begin ; a != c.end() ; ++a)


와 같은 식으로!= 로 비교하고 ++a 를 사용합니다. end() 같지 않을 때 까지 계속 이동하면서 증가를 합니다.

증가 연산은 전위(prefix operator)를 사용합니다. 

이유는 class에서 증가연산자를 overloading 해 보셨다면 왜인지 아실것 같은데 후위(postfix)는 반복자의 이전값을 반환하기 때문에 임시로 객체가 생깁니다.

아무래도 전위 증가/감소가 성능이 좋겠죠. 후위를 써도 괜찮긴 하지만 사용하지 마세요.

 

그리고 iterator은 두 가지가 있는데

container::iterator   원소들을 읽기/쓰기 가능합니다.

container::const_iterator   읽기 전용으로 순회합니다


출처 : http://egloos.zum.com/ErinSyndrome/v/913685

'Programming > openCV' 카테고리의 다른 글

vector에 접근하는 두가지 방법  (0) 2017.04.11
13. Hough Circles  (0) 2017.04.04
12. Templet Matching  (0) 2017.04.04
11. Emboss, sketch, 수채화  (0) 2017.04.04
10. 마우스로 영역을 지정한 부분만 엣지 검출  (0) 2017.04.04

방법

1. 템플릿 매칭방법을 선택하고, 매칭을 시작한다.

2. 방법에따라 최대값을 찾을 것인지, 최소값을 찾을 것인지 정한다.

3. 그 부분에 사각형을 그린다.


코드

#include <opencv2/opencv.hpp>

#include <opencv2/highgui.hpp>


using namespace cv;

using namespace std;

int main()

{

Mat srcImage = imread("image4/alphabet.bmp", CV_LOAD_IMAGE_GRAYSCALE);

if (srcImage.empty())

return -1;


Mat tImage1 = imread("image4/A.bmp", CV_LOAD_IMAGE_GRAYSCALE);

Mat tImage2 = imread("image4/S.bmp", CV_LOAD_IMAGE_GRAYSCALE);

Mat tImage3 = imread("image4/b.bmp", CV_LOAD_IMAGE_GRAYSCALE);

Mat tImage4 = imread("image4/m.bmp", CV_LOAD_IMAGE_GRAYSCALE);


Mat dstImage;

cvtColor(srcImage, dstImage, COLOR_GRAY2BGR);


double minVal, maxVal;

Point minLoc, maxLoc;

Mat result;


// 제곱차 매칭 방법(TM_SQDIFF) 어두운곳이 매칭지점

matchTemplate(srcImage, tImage1, result, TM_SQDIFF);

imshow("TM_SQDIFF", result);

//비교한 MAT중에서 가장 큰 값을 찾는다.

minMaxLoc(result, &minVal, NULL, &minLoc, NULL);

rectangle(dstImage, minLoc,

Point(minLoc.x + tImage1.cols, minLoc.y + tImage1.rows), Scalar(255, 0, 0), 2); //blue


// 정규화된 제곱차 매칭 방법(TM_SQDIFF_NORMED) 어두운곳이 매칭지점

matchTemplate(srcImage, tImage2, result, TM_SQDIFF_NORMED);

imshow("TM_SQDIFF_NORMED", result);

minMaxLoc(result, &minVal, NULL, &minLoc, NULL);

rectangle(dstImage, minLoc,

Point(minLoc.x + tImage2.cols, minLoc.y + tImage2.rows), Scalar(0, 255, 0), 2); //green


// 정규화된 상관관계 방법(TM_CCORR_NORMED) 밝은곳이 매칭지점

matchTemplate(srcImage, tImage3, result, TM_CCORR_NORMED);

imshow("TM_CCORR_NORMED", result);


minMaxLoc(result, NULL, &maxVal, NULL, &maxLoc);

rectangle(dstImage, maxLoc,

Point(maxLoc.x + tImage3.cols, maxLoc.y + tImage3.rows), Scalar(0, 0, 255), 2); //red


// 정규화된 상관계수 방법(TM_CCOEFF_NORMED) 밝은곳이 매칭지점

matchTemplate(srcImage, tImage4, result, TM_CCOEFF_NORMED);

imshow("TM_CCOEFF_NORMED", result);

minMaxLoc(result, NULL, &maxVal, NULL, &maxLoc);

rectangle(dstImage, maxLoc,

Point(maxLoc.x + tImage4.cols, maxLoc.y + tImage4.rows), Scalar(255, 0, 255), 2);//puple


imshow("dstImage", dstImage);

waitKey();

return 0;

}



image안에서 x, y로 한칸씩 이동하면서 템플릿을 겹쳐 놓고 각 셀의 차이나 곱의 합을 계산해서 result배열을 만들어서 돌려 준다. 이때 image의 크기는 템플릿의 크기보다 커야 하고 계산 방식은 method로 정해진다.

  • CV_TM_SQDIFF -- 각 픽셀의 제곱의 차이
R(x,y)= \sum _{x',y'} (T(x',y')-I(x+x',y+y'))^2
  • CV_TM_SQDIFF_NORMED  -- CV_TM_SQDIFF / sqrt(각 픽셀의 제곱의 곱)

R(x,y)= \frac{\sum_{x',y'} (T(x',y')-I(x+x',y+y'))^2}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}

  • CV_TM_CCORR -- 각 픽셀의 곱의 합 (교차 상관)
R(x,y)= \sum _{x',y'} (T(x',y')  \cdot I(x+x',y+y'))
  • CV_TM_CCORR_NORMED -- CV_TM_CCORR / sqrt(각 픽셀의 제곱의 곱)
R(x,y)= \frac{\sum_{x',y'} (T(x',y') \cdot I(x+x',y+y'))}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}


  • CV_TM_CCOEFF -- 상관계수
R(x,y)= \sum _{x',y'} (T'(x',y')  \cdot I(x+x',y+y'))
  • CV_TM_CCOEFF_NORMED -- CV_TM_CCOEFF / sqrt(각 픽셀의 제곱의 곱)
NCC- 빠른 정상화 간 상관관계

R(x,y)= \frac{ \sum_{x',y'} (T'(x',y') \cdot I'(x+x',y+y')) }{ \sqrt{\sum_{x',y'}T'(x',y')^2 \cdot \sum_{x',y'} I'(x+x',y+y')^2} }


구현 결과



'Programming > openCV' 카테고리의 다른 글

13. Hough Circles  (0) 2017.04.04
iterator의 개념  (0) 2017.04.04
11. Emboss, sketch, 수채화  (0) 2017.04.04
10. 마우스로 영역을 지정한 부분만 엣지 검출  (0) 2017.04.04
9. sobel Filter / Canny Edge  (0) 2017.04.04

+ Recent posts