#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat img_original, img_gray, img_edge;
//이미지파일 로드
img_original = imread("test2.jpg", IMREAD_COLOR);
//img_original = imread("test2.png", IMREAD_COLOR);
//img_original = imread("test.jpg", IMREAD_COLOR);
if (img_original.empty())
{
cout << "Could not open or find the image" << std::endl;
return -1;
}
//그레이스케일 이미지로 변환
cvtColor(img_original, img_gray, COLOR_BGR2GRAY);
//에지 검출
GaussianBlur(img_gray, img_edge, cvSize(5, 5),0,0);
Canny(img_edge, img_edge, 50, 150, 3);
int height = img_edge.rows;
int width = img_edge.cols;
double hough_height = ((sqrt(2.0) * (double)(height>width ? height:width)) / 2.0);
int centerX = width / 2.0;
int centerY = height / 2.0;
int accumulator_width = 180;
int accumulator_height = hough_height * 2;
int accumulator_size = accumulator_height * accumulator_width;
int *accumulator = (int*)malloc(sizeof(int)*accumulator_size);
memset(accumulator, 0, sizeof(int)*accumulator_size);
double table_sin[180], table_cos[180];
double DEG2RAD = CV_PI / 180;
for (int angle = 0; angle < 180; angle++)
{
table_sin[angle] = sin(angle*DEG2RAD);
table_cos[angle] = cos(angle*DEG2RAD);
}
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if ( img_edge.at<uchar>(y,x) > 0 )
for (int angle = 0; angle < 180; angle++)
{
int r = (x-centerX)*table_cos[angle] + (y-centerY)*table_sin[angle];
r = r + hough_height;//r이 음수인 경우 때문 -r ~ r 범위를 0 ~ 2r 범위로 변경
accumulator[r*accumulator_width + angle] += 1;
}
}
}
//accumulator에서 MAX값 찾기
int max = -1;
for (int y = 0; y < accumulator_height; y++)
for (int x = 0; x < accumulator_width; x++)
{
if (accumulator[y*accumulator_width + x] > max)
max = accumulator[y*accumulator_width + x];
}
//accumulator를 이미지화
Mat img_accumulator = Mat(accumulator_height, accumulator_width, CV_8UC3);
for (int y = 0; y < accumulator_height; y++)
for (int x = 0; x < accumulator_width; x++)
{
int value = 255 * ((double)accumulator[y*accumulator_width + x]) / max;
img_accumulator.at<Vec3b>(y, x)[0] = 255-value;
img_accumulator.at<Vec3b>(y, x)[1] = 255-value;
img_accumulator.at<Vec3b>(y, x)[2] = 255-value;
}
int count = 0;
for (int r = 0; r < accumulator_height; r++)
for (int angle = 0; angle < 180; angle++)
{
if (accumulator[r * accumulator_width + angle] > 50)
{
// 11 x 11 영역내에서 현재 위치가 local maxima 인지 검사
int max = accumulator[r * accumulator_width + angle];
for (int y = -5; y <= 5; y++)
{
for (int x = -5; x <= 5; x++)
{
int new_r = r + y;
int new_angle = angle + x;
if ( new_angle < 0 )
{
new_angle = 180 + new_angle;
}
else if (new_angle >= 180) {
new_angle = new_angle - 180;
}
if ( new_r >= 0 && new_r < accumulator_height)
{
if (accumulator[ new_r * accumulator_width + new_angle] > max)
{
max = accumulator[ new_r * accumulator_width + new_angle];
x = y = 6;//loop 종료
}
}
}
}
if (max > accumulator[r * accumulator_width + angle])
{
continue; //현재 위치는 local maxima가 아님
}
// r = x*cos(theta) + y*sin(theta)
// y = (r- x*cos(theta))/ sin(theta) 수평선인 경우
// x = (r- y*sin(theta))/ cos(theta) 수직선인 경우
int x1, x2, y1, y2;
if (angle >= 45 && angle <= 135) //수평선
{
x1 = 0;
x2 = width;
y1 = ((r - hough_height) - (x1 - centerX)*table_cos[angle]) / table_sin[angle] + centerY;
y2 = ((r - hough_height) - (x2 - centerX)*table_cos[angle]) / table_sin[angle] + centerY;
}
else //수직선
{
y1 = 0;
y2 = height;
x1 = ((r - hough_height) - (y1 - centerY)*table_sin[angle]) / table_cos[angle] + centerX;
x2 = ((r - hough_height) - (y2 - centerY)*table_sin[angle]) / table_cos[angle] + centerX;
}
circle(img_accumulator, cvPoint(angle, r), 3, Scalar(255, 0, 0));
line(img_original, cvPoint(x1, y1), cvPoint(x2, y2), Scalar(255, 0, 0), 1);
count++;
cout << count << " (" << x1 << "," << y1 << ") (" << x2 << "," << y2 << ") angle=" << angle<<" r="<<r<< " accumulator값="<< accumulator[r * accumulator_width + angle]<<endl;
}
}
imshow("img_result", img_original);
imshow("img_gray", img_gray);
imshow("img_edge", img_edge);
imshow("img_accumulator", img_accumulator);
imwrite("img_gray.jpg", img_gray);
imwrite("img_edge.jpg", img_edge);
imwrite("img_accumulator.jpg", img_accumulator);
imwrite("img_result.jpg", img_original);
//키보드 입력이 될때까지 대기
waitKey(0);
return 0;
}
댓글 0
| 번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
|---|---|---|---|---|
| 51 | [아두이노] 장애물 감지 자율주행 자동차 | proin | 2018.05.14 | 1 |
| 50 | [아두이노] DC 모터의 제어(모터드라이버 L298N) 1편 | proin | 2018.05.14 | 3 |
| 49 | 아두이노 탱크 연결 사진 | proin | 2018.05.14 | 2 |
| 48 | 오픈소스 + 알고리즘 | proin | 2018.05.14 | 1 |
| 47 | OpenCV #7-2 Example (허프 변환으로 영상 내 선 감지) | proin | 2018.05.14 | 0 |
| 46 | 롤 모델 | proin | 2018.05.14 | 2 |
| » | 사진에서 엣지 따오는 소스 | proin | 2018.05.14 | 1 |
| 44 | 카메라 여는 소스 | proin | 2018.05.14 | 1 |
| 43 | Visual Studio 2017에서 OpenCV 3.4를 사용하는 방법 | proin | 2018.05.14 | 0 |
| 42 | 모터 돌리는 소스 | proin | 2018.05.14 | 2 |
| 41 | project | proin | 2018.05.14 | 1 |
| 40 | [25호]DIY 프로젝트 공모전- 차선 인식을 통한 차량의 능동적 안전시스템 개발 | proin | 2018.05.14 | 1 |
| 39 | [Web] PHP 로그인/로그아웃/회원가입 {원본} | proin | 2018.05.14 | 1 |
| 38 | html 출력 {원본} | proin | 2018.05.14 | 1 |
| 37 | 세션을 사용한 PHP 로그인/로그아웃 소스 {원본} | proin | 2018.05.14 | 1 |
| 36 | 세션을 사용한 PHP 로그인/로그아웃 소스 | proin | 2018.05.03 | 2 |
| 35 | html 출력 | proin | 2018.05.02 | 1 |
| 34 | 옥션 로그인 부분 소스 | proin | 2018.05.02 | 0 |
| 33 | XML과 DB | project2018 | 2018.05.02 | 3 |
| 32 | 컨버터 | proin | 2018.05.02 | 0 |