반응형
opencv만을 이용하여 사각형 이미지를 인식하기 위한 예제를 테스트 해보았으며, 이를 기록함.
# 환경
- Ubuntu 22.04
- opencv4.5.x
# 딥러닝 없이 사각형 인식 방법
1. 이미지의 전처리와 구조화
- 전처리:
노이즈를 제거(Blur)하고 밝기 변화가 심한 경계선(Canny Edge)만 남김 - 구조화:
흩어진 점들을 하나의 덩어리(Contour)로 묶고, 이를 다시 4개의 꼭짓점을 가진 다각형(ApproxPoly)으로 단순화함.
2. 정밀한 기하학적 연산
단순한 사각형 인식과 비스듬히 놓인 사각형의 각도를 파악함
- 회전 사각형(RotatedRect):
물체가 기울어져 있어도 이를 감싸는 최소 크기의 사각형을 찾아냄. - 좌표 및 각도 :
사각형의 중심점(x, y), 가로·세로 길이(w, h), 그리고 지면 대비 회전 각도(Angle)를 계산함.
3. 필터링(노이즈 제거)
- 면적 조건:
너무 작은 먼지나 노이즈를 무시함 (ex.Area > 100). - 형태 조건:
가로세로 비율(Aspect Ratio)을 계산하여 너무 길쭉한 사각형 등은 사각형에서 제외함.
4. 시각화
- 동적 텍스트 배치:
피타고라스 정리를 활용해 사각형의 회전 상태와 관계없이 텍스트가 물체 위쪽 적절한 위치에 표시되도록 연산 처리함. - 정보 표시:
화면에 실시간으로 "(중심 좌표) + 회전 각도"를 출력하여 사각형의 기초 데이터로 활용할 수 있게 함.
# 예시 코드
이미지 데이터에서 직사각형 인식하여, 직사각형의 좌표, 각도 정보를 출력함.
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include <cmath>
using namespace cv;
using namespace std;
int main() {
Mat src = imread("box.jpg");
if (src.empty()) return -1;
Mat gray, canned;
cvtColor(src, gray, COLOR_BGR2GRAY);
GaussianBlur(gray, gray, Size(3, 3), 0);
Canny(gray, canned, 50, 150); // 에지 추출
vector<vector<Point>> contours;
findContours(canned, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
for (const auto& contour : contours) {
double perl = arcLength(contour, true);
vector<Point> approx;
// 외곽선 근사화 (정밀도 조절: 0.02 * 둘레)
approxPolyDP(contour, approx, 0.02 * perl, true);
// 사각형 조건 체크
if (approx.size() == 4 && cv::isContourConvex(approx) && cv::contourArea(approx) > 100) {
// 1. 회전된 사각형 정보 추출
cv::RotatedRect rect = cv::minAreaRect(approx);
float w = rect.size.width;
float h = rect.size.height;
// 2. 가로세로 비율 계산 (항상 긴 쪽을 짧은 쪽으로 나눔)
float aspect_ratio = (w > h) ? (w / h) : (h / w);
// 3. 조건 설정 (예: 가로 5px 이상, 세로 5px 이상, 비율은 5:1 이하)
bool size_ok = (w > 5 && h > 5);
bool ratio_ok = (aspect_ratio < 5.0); // 직사각형
if (size_ok && ratio_ok) {
// 각도 측정
float angle = rect.angle;
if (w < h) angle += 90.0f;
// 직사각형 그리기
cv::polylines(src, approx, true, cv::Scalar(0, 255, 0), 2);
// 중심점 표시
cv::circle(src, rect.center, 3, cv::Scalar(255, 0, 0), -1);
std::string label = "(" + std::to_string((int)rect.center.x) + ", " + std::to_string((int)rect.center.y) + ") " + std::to_string((double)angle) + "'";
cv::putText(src, label, Point(rect.center.x - w/2, rect.center.y - sqrt(pow(w, 2)+pow(h, 2))/2 ),
cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 1);
}
}
}
imshow("Square Detection", src);
waitKey(0);
return 0;
}
*이는 테스트해본 코드이며 일부 수정해서 사용하면 됨.
반응형
'프로그래밍' 카테고리의 다른 글
| 유선 공유기(ipTime) 설정 방법 (0) | 2026.05.09 |
|---|---|
| apt update Warning/error 해결 방법 (0) | 2025.12.24 |