반응형
윗 글에서 HSV변환 후 threshold를 줘서 따낸 2개를 합친 src_hsv_bin를 보면 노이즈가 상당히 많다.
open cv morphology_extension에서 지원해주는 open함수를 활용해서 노이즈를 제거하자
//최적화된 코드
#pragma once
#include "ISP.h"
int main()
{
std::string fileName = "../KCCImageNet/stop_img.png";
cv::Mat src_color = cv::imread(fileName, cv::ImreadModes::IMREAD_ANYCOLOR);
Mat src_hsv;
cvtColor(src_color, src_hsv, COLOR_BGR2HSV);
Mat src_hsv_bin, src_hsv_bin_Red_1, src_hsv_bin_Red_2;
inRange(src_hsv, Scalar(160, 180, 0), Scalar(180, 255, 255), src_hsv_bin_Red_1);//main 빨강색들을 추출
inRange(src_hsv, Scalar(0, 180, 0), Scalar(10, 255, 255), src_hsv_bin_Red_2);//짜투리 남은 빨강색들 추출
src_hsv_bin = src_hsv_bin_Red_1 + src_hsv_bin_Red_2;// main과 짜투리 합쳐줌
//morphology remove noise
int kernelSz = 2;
int shape = MorphShapes::MORPH_ELLIPSE; // MORPH_CROSS 나 MORPH_ELLIPSE 많이 씀
cv::Size sz = Size(2 * kernelSz + 1, 2 * kernelSz + 1);
Mat SE = cv::getStructuringElement(shape, sz);
Mat src_open, src_closing;
int type = MorphTypes::MORPH_OPEN;
cv::morphologyEx(src_hsv_bin, src_open, type, SE);
Mat diff_open = src_hsv_bin - src_open;
RNG rng(12345);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(src_hsv_bin, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
Mat drawing = src_color.clone();// Mat::zeros(src_color.size(), CV_8UC3);
for (size_t i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
drawContours(drawing, contours, (int)i, color, 2, LINE_8, hierarchy, 0);
//drawContours(drawing, contours, (int)i, color, CV_FILLED);
}
//find max area object
double max_area = 0;
size_t max_area_index = 0;
for (size_t i = 0; i < contours.size(); i++)
{
double area = contourArea(contours[i]);
if (max_area < area)
{
max_area = area;
max_area_index = i;
}
}
drawContours(drawing, contours, (int)max_area_index, CV_RGB(255, 0, 0), CV_FILLED);
const Point* pts = (const cv::Point*)Mat(contours[max_area_index]).data;
int npts = Mat(contours[max_area_index]).rows;
cv::polylines(drawing, &pts, &npts, 1, true, Scalar(200, 200, 200));
cv::fillConvexPoly(drawing, pts, npts, cv::Scalar(0, 255, 200));
//for (size_t i = 0; i < contours.size(); i++)
{
size_t i = max_area_index;
double area = contourArea(contours[i]);
RotatedRect rrt = minAreaRect(contours[i]);
double arcLen = arcLength(contours[i], true);
Point ptTxt = Point(rrt.boundingRect().br().x + 10, rrt.boundingRect().y);
string msg;
msg = std::format("area = {:.1f}", area);
putText(drawing, msg, Point(ptTxt.x, ptTxt.y + 30 * 0), FONT_HERSHEY_SIMPLEX, 0.8, CV_RGB(10, 0, 10), 1, 8);
msg = std::format("x,y = {:.1f}, {:.1f}", rrt.center.x, rrt.center.y);
putText(drawing, msg, Point(ptTxt.x, ptTxt.y + 30 * 1), FONT_HERSHEY_SIMPLEX, 0.8, CV_RGB(10, 0, 10), 1, 8);
msg = std::format("length = {:.1f}", arcLen);
putText(drawing, msg, Point(ptTxt.x, ptTxt.y + 30 * 2), FONT_HERSHEY_SIMPLEX, 0.8, CV_RGB(10, 0, 10), 1, 8);
cv::rectangle(drawing, rrt.boundingRect2f().tl(), rrt.boundingRect2f().br(), CV_RGB(0, 0, 255));
cv::drawMarker(drawing, rrt.center, CV_RGB(255, 0, 0));
cv::ellipse(drawing, rrt, CV_RGB(10, 255, 10));
int radius = std::min(rrt.boundingRect().width, rrt.boundingRect().height);
radius /= 2;
cv::circle(drawing, rrt.center, radius, CV_RGB(10, 50, 255));
msg = std::format("radius = {:d}", radius);
putText(drawing, msg, Point(ptTxt.x, ptTxt.y + 30 * 3), FONT_HERSHEY_SIMPLEX, 0.8, CV_RGB(10, 0, 10), 1, 8);
//avg_brightness - c code
uchar* pData = src_color.data;
uchar* pDataMask = src_hsv_bin.data;
//only red channel
int sum_red = 0;
int sum_red_count = 0;
for (size_t row = 0; row < src_color.rows; row++)
{
for (size_t col = 0; col < src_color.cols; col++)
{
int index = row * src_color.cols + col;
int index_bgr = index * 3;
int red = pData[index_bgr + 2];
int mask = pDataMask[index];
if (red > 0 && mask == 255)
{
sum_red += red;
sum_red_count++;
}
}
}
float avg_brightness_red = sum_red / sum_red_count;
msg = std::format("avg_red = {:.1f}", avg_brightness_red);
putText(drawing, msg, Point(ptTxt.x, ptTxt.y + 30 * 4), FONT_HERSHEY_SIMPLEX, 0.8, CV_RGB(10, 0, 10), 1, 8);
const int ptSz = 4;
Point2f pt[ptSz];
rrt.points(pt);
for (size_t i = 0; i < ptSz; i++)
{
cv::line(drawing, pt[i % ptSz], pt[(i + 1) % ptSz], CV_RGB(255, 0, 255), 1);
}
}
return 1;
}
반응형
'Open CV' 카테고리의 다른 글
[Ubuntu OpenCV] VM ware ubuntu에서 웹캠 연결 후 OpenCV 사용해서 Qt GUI 구성하기 (1) | 2024.03.08 |
---|---|
[OPENCV-C++ ] open cv 라이브러리 활용 erode, dilate (0) | 2023.11.26 |
[OPENCV-C++ ] 형태학 기반 영상처리 Dilation 팽창 (0) | 2023.11.26 |
[OPENCV-C++ ] 형태학 기반 영상처리 Erosion 침식 (0) | 2023.11.26 |
[OPENCV-C++ ] BGR→HSV→fndcontours→text로 사진에 데이터 표현 (1) | 2023.11.26 |