approxPolyDP를 활용해 꼭지점을 찾고, 꼭지점을 통해 나온 꼭지점의 start점과 end점 을 통해 기울어진 각도 파악.
증명은 Image J로
버그: main문에서 화면 출력시 각도 부분만 글자가 겹침. 함수들이 2번씩 돌음.
//https://poorman.tistory.com/193
#include"opencv2\opencv.hpp"
#include<iostream>
#include<math.h>
#include<string>
#define M_PI 3.141592653 /*PI*/
using namespace std;
using namespace cv;
const float getAngle(const Point start, const Point end); //식별자 오류.https://blog.danggun.net/839 함수 선언 해주기.
//Contour 영역 내에 텍스트 쓰기
//https://github.com/bsdnoobz/opencv-code/blob/master/shape-detect.cpp
void setLabel(Mat& image, string str, vector<Point> contour, vector<Point2f> approx)
{
int fontface = FONT_HERSHEY_SIMPLEX;
double scale = 0.5;
int thickness = 1;
int baseline = 0;
Size text = getTextSize(str, fontface, scale, thickness, &baseline);
//문자열은 사각형 공간으로 나타낼수 있습니다. 문자열의 올바른 출력을 위하여, 이 문자열 공간의 크기를 가져올수 있는 함수인 getTextSize
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 a[4]; // 4개 꼭지점 x좌표값 int로 저장.
int b[4]; // y좌표값 int로저장.
string s[4]; // 4개 x 좌표값을 string으로 변환.
string s2[4]; // y좌표값 string 변환
for (int i = 0; i < approx.size(); i++)
{
a[i] = approx[i].x;
b[i] = approx[i].y;
s[i] = to_string(a[i]);
s2[i] = to_string(b[i]);
putText(image, "(" + s[i] + ", " + s2[i] + ")", Point(approx[i].x, approx[i].y), FONT_HERSHEY_SIMPLEX, 1, 255);
imshow("dbug", image);
waitKey(0);
}
//각도
float angle = getAngle(approx[0], approx[3]); // approx[0]~approx[3]. 꼭지점의 start점과 end점.
string angle_s = to_string(angle);
putText(image, "angle: " + angle_s, Point(20, 20), FONT_HERSHEY_DUPLEX, 1, 255);
//중심점. https://mathbang.net/442 참고.
int sum_x = 0;
int sum_y = 0;
for (int i = 0; i < approx.size(); i++)
{
sum_x += approx[i].x;
sum_y += approx[i].y;
}
int centerX = sum_x / 4;
int centerY = sum_y / 4;
string centerX_str = to_string(centerX);
string centerY_str = to_string(centerY);
putText(image, "(" + centerX_str + "," + centerY_str + ")", Point(centerX, centerY), FONT_HERSHEY_DUPLEX, 1, 255, 1);
}
Mat contour(Mat dst)
{
vector < vector<Point>> contours;
vector<Vec4i> hierarchy; // 벡터궁금.
RNG rng(12345); // 난수 발생기.
findContours(dst, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); //cv.CHAIN_APPROX_SIMPLE 시작점과 끝점에만 포인터를 그린다.
//참고:cv.CHAIN_APPROX_NONE 모든 경계선에 포인터를 그린다.
Mat drawing = Mat::zeros(dst.size(), CV_8UC3);
for (int i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
}
//contours를 근사화하기. 꼭지점 좌표값.
vector<Point2f> approx;
Mat img_result = drawing.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))) > 100) // fabs: math.h에 있는 절댓값함수.
{
int size = approx.size(); //4
//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), 15); //approx[k]의 사이즈 4. 0~3 즉 4개의 꼭지점 좌표 확인가능. approx[0~4] , img_result는 그림임.
}
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));
}
if (size == 4 && isContourConvex(Mat(approx))) //isContourConvex:인자로 입력된 Contour가 Convex Hull 인지 체크.
{ //만약 Convex Hull이라면 True를 리턴, 그렇지 않으면 False 리턴
setLabel(img_result, "rectangle", contours[i], approx); //사각형
}// setLabel은, 영상에 바운딩 박스를 그려놓고, 그 위에 해당 도형의 이름 문자열을 표시하는 용도입니다.
}
}
return img_result;
}
//각도 알고리즘.
const float getAngle(const Point start, const Point end) {
float dy = end.y - start.y;
float dx = end.x - start.x;
float rad = atan2(dy, dx);
return rad * (180.0 / M_PI);
} // 단 이미지를 원본 사이즈로 해야 image J를 통해서 정확히 확인가능.
//이미지 프로세싱.
Mat imgProcessing(Mat src, Mat dst)
{
cvtColor(src, dst, COLOR_BGR2GRAY, 0);
GaussianBlur(dst, dst, Size(3, 3), 0);//필터링, 캐니엣지 적용이전 잡음제거
GaussianBlur(dst, dst, Size(3, 3), 0);
GaussianBlur(dst, dst, Size(3, 3), 0);
//edge - > contour -> start와 end점 이용해서 기울기 및 기울어진 각도 구해보기.
Canny(dst, dst, 220, 255, 3);
return dst;
}
int main(void)
{
Mat src = imread("O:/인수인계/[SDC]motherAFG/test.bmp");
//resize(src, src, Size(1000, 1000), 0, 0, CV_INTER_LINEAR); //원사이즈에서 사이즈를 작게하니 문자가 겹쳐지는 버그생김.
Mat dst = src.clone();
dst = imgProcessing(src, dst);
dst = contour(dst);
imshow("dst", dst); //왜 각도가 겹치나?
imshow("src", src);
waitKey(0);
}
알고리즘.
블러링->캐니엣지->contour-> approxpolyDP(꼭지점)-> 각도 알고리즘 -> setLabel함수에 도형의 이름과 꼭지점 그리고 각도를 puttext 로 뿌림.
참조
https://poorman.tistory.com/193
[OpenCV 3.2] Shape Detection (다각형 검출)
[OpenCV 3.2] Shape Detection (다각형 검출) 사각형 검출에서 다각형의 꼭지점 개수로 사각형을 구분하였는데 4개의 선분 이상의 다각형에서는 화살표, 블록, 별 모양 등의 도형을 구분할 수 없다. 그래
poorman.tistory.com
알고리즘 참조.
Horizontal Grays :: OpenCV 사각형 검출 및 기울어진 각도 계산 (tistory.com)
OpenCV 사각형 검출 및 기울어진 각도 계산
이번에 할 것은 영상내의 사각형을 찾아내고 그 사각형의 기울기를 계산하는 것 아래 OpenCV에서 친절히 샘플 소스를 줬는데... 뭔 소린지 잘 모르겠어서 참고하고 기존에 쓰던 알고리즘을 이용해
zeal74.tistory.com
각도(아래 2개 참조 글, 동일 내용)
핵심.
라디안 -> 각도.
rad* (180/pi) = degree
각도 -> 라디안
degree * (pi/180) = rad
Embedded blog: 두 점 사이의 각도 계산 (alprogs.blogspot.com)
두 점 사이의 각도 계산
OpenCV 를 이용, 빨강, 검정 두 점을 인식하고 두 점 사이의 각도와 그 중심을 계산하여 출력하는 화면과 소스. 오브젝트의 방향성과 위치를 인식할 수 있게 되었다. #include #include #inc
alprogs.blogspot.com
[OpenCV] 두점을 인식하여 사이의 각 구하기 : 네이버 블로그 (naver.com)
[OpenCV] 두점을 인식하여 사이의 각 구하기
OpenCV 를 이용, 빨강, 검정 두 점을 인식하고 두 점 사이의 각도와 그 중심을 계산하여 출력하는 화면...
blog.naver.com
삼각형의 무게중심의 좌표, 무게중심 공식 – 수학방 (mathbang.net)
삼각형의 무게중심의 좌표, 무게중심 공식
삼각형의 무게중심은 중학교 때 공부했어요. 삼각형의 무게중심과 삼각형의 중선 이번에는 앞서 공부한 내분점과 외분점의 좌표 공식을 이용해서 삼각형의 무게중심의 좌표를 구하는 방법을
mathbang.net
'Vision' 카테고리의 다른 글
각도,라디안 (0) | 2021.07.21 |
---|---|
각도구하기 방법2 (RotatedRect 이용) (0) | 2021.07.20 |
Angle&Gradient&Distance (0) | 2021.07.19 |
c++ 연산시간측정 (0) | 2021.07.16 |
용어 정리 (0) | 2021.07.15 |