반응형
내 코드
//내 코드
//stop image 실습을 위한 파일
#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);
cv::Mat src_color_HSV1;
cvtColor(src_color, src_color_HSV1, COLOR_BGR2HSV);//BGR인 output, 즉 원본을 HSV로 변환한게 img_hsv
cv::Mat src_color_HSV;
cvtColor(src_color, src_color_HSV, COLOR_BGR2HSV);//BGR인 output, 즉 원본을 HSV로 변환한게 img_hsv
size_t width = src_color.cols;
size_t height = src_color.rows;
/*이진화*/
Scalar lower_red = Scalar(170, 190, 200); //빨강색 (HSV 범위)
Scalar upper_red = Scalar(185, 225, 255);
inRange(src_color_HSV, lower_red, upper_red, src_color_HSV);
/*이진화*/
RNG rng(12345);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(src_color_HSV/*1. 캐니엣지 영상 2. 이진영상 둘 중 하나 넣을 수 있음*/, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
Mat drawing = Mat::zeros(src_color_HSV.size(), CV_8UC3);
int object_contour_num=0;
int carea = 0;
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, object_contour_num/*int contourIdx*/, color, 2/*thickness*/, LINE_8/*lineType*/, hierarchy, 0);
/*
void drawContours( InputOutputArray image, InputArrayOfArrays contours,
int contourIdx, const Scalar& color,
int thickness = 1, int lineType = LINE_8,
InputArray hierarchy = noArray(),
int maxLevel = INT_MAX, Point offset = Point() );
*/
if (carea < cv::contourArea(contours[i])) { carea = cv::contourArea(contours[i]); object_contour_num = i; }//가장 넓은 면적을 가진 contours 요소를 찾아내는 함수 object_contour_num에 해당 인덱스가 저장됨
}
int CoGx, CoGy;//center of Gravity X,Y
CoGx = CoGy = 0;
int accX = 0, accY = 0;
int x_min = width, x_max = 0, y_min = height, y_max = 0;
int length = contours[object_contour_num].size();
for (size_t i = 0; i < length; i++)//size()는 요소의 갯수, capacity()는 할당된 메모리공간에서 몇개의 요소를 저장할 수 있는지를 나타냄
{
accX += contours[object_contour_num].at(i).x;
accY += contours[object_contour_num].at(i).y;
if (x_min > contours[object_contour_num].at(i).x)
x_min = contours[object_contour_num].at(i).x;
if (x_max < contours[object_contour_num].at(i).x)
x_max = contours[object_contour_num].at(i).x;
if (y_min > contours[object_contour_num].at(i).y)
y_min = contours[object_contour_num].at(i).y;
if (y_max < contours[object_contour_num].at(i).y)
y_max = contours[object_contour_num].at(i).y;
}
CoGx = accX / length;
CoGy = accY / length;
/*표지판 내 밝기 평균값 구하기*/
cv::Mat BGR_BIN_AND = Mat::zeros(cv::Size(width, height), CV_8UC3);
bitwise_and(src_color, src_color, BGR_BIN_AND, src_color_HSV);//output, 즉 원본에 white_mask값을 and 해준게 white_image
double b_mean_brightness = 0.0; //= cv::mean(BGR_BIN_AND)[0];
double g_mean_brightness = 0.0;
double r_mean_brightness = 0.0;
int b_count = 0, g_count = 0, r_count = 0;
for (size_t row = y_min; row < y_max; row++)
{
for (size_t col = x_min; col < x_max; col++)
{
int index = (row)*width + (col);//mono->각 배열에 접근 할 index를 만들어 주는거임.
int index_B = (row)*width * 3 + (col * 3 + 0);//RGB->B 배열에 접근 할 index를 만들어 주는거임.
int index_G = (row)*width * 3 + (col * 3 + 1);//RGB->G 배열에 접근 할 index를 만들어 주는거임.
int index_R = (row)*width * 3 + (col * 3 + 2);//RGB->R 배열에 접근 할 index를 만들어 주는거임.
if (BGR_BIN_AND.data[index_G] > 40 && BGR_BIN_AND.data[index_G] < 80) { g_mean_brightness += BGR_BIN_AND.data[index_G]; g_count++;}
if (BGR_BIN_AND.data[index_R] > 200 && BGR_BIN_AND.data[index_R] < 255) { r_mean_brightness += BGR_BIN_AND.data[index_R]; r_count++;}
if (BGR_BIN_AND.data[index_B] > 40 && BGR_BIN_AND.data[index_B] < 80) { b_mean_brightness += BGR_BIN_AND.data[index_B]; b_count++; }
}
}
g_mean_brightness /= g_count;
r_mean_brightness /= r_count;
b_mean_brightness /= b_count;
double area = contourArea(contours[object_contour_num]);
RotatedRect rrt = minAreaRect(contours[object_contour_num]);
double arcLen = arcLength(contours[object_contour_num], true);
double radius = CoGx - x_min;
/*string 화면 출력*/
Point ptTxt = Point(rrt.boundingRect().x, rrt.boundingRect().y);
string msg;
msg = std::format("area = {:.1f}", area);
putText(src_color, msg, Point(ptTxt.x+2*radius, ptTxt.y + 30 * 0), FONT_HERSHEY_SIMPLEX, 0.8, CV_RGB(10, 0, 10), 1, 3);
msg = std::format("length = {:.1f}", arcLen);
putText(src_color, msg, Point(ptTxt.x + 2 * radius, ptTxt.y + 30 * 1), FONT_HERSHEY_SIMPLEX, 0.8, CV_RGB(10, 0, 10), 1, 3);
msg = std::format("x,y = {:.1f}, {:.1f}", rrt.center.x, rrt.center.y);
putText(src_color, msg, Point(ptTxt.x + 2 * radius, ptTxt.y + 30 * 2), FONT_HERSHEY_SIMPLEX, 0.8, CV_RGB(10, 0, 10), 1, 3);
msg = std::format("Radius = {:.1f}",radius);
putText(src_color, msg, Point(ptTxt.x + 2 * radius, ptTxt.y + 30 * 3), FONT_HERSHEY_SIMPLEX, 0.8, CV_RGB(10, 0, 10), 1, 3);
msg = std::format("AvgBrightness =");
putText(src_color, msg, Point(ptTxt.x + 2 * radius, ptTxt.y + 30 * 4), FONT_HERSHEY_SIMPLEX, 0.8, CV_RGB(10, 0, 10), 1, 3);
msg = std::format("({:.1f},{:.1f},{:.1f})", b_mean_brightness, g_mean_brightness, r_mean_brightness);
putText(src_color, msg, Point(ptTxt.x + 2 * radius, ptTxt.y + 30 * 5), FONT_HERSHEY_SIMPLEX, 0.8, CV_RGB(10, 0, 10), 1, 3);
/*string 화면 출력*/
//cv::rectangle(src_color, rrt.boundingRect().tl(), rrt.boundingRect().br(), CV_RGB(0, 0, 255));//도형 주위 사각형 그리기
//cv::drawMarker(src_color, rrt.center, CV_RGB(255, 0, 0));//무게중심 그리기
const int ptSz = 4;
Point2f pt[ptSz];
cv::circle(src_color/*image src*/, rrt.center/*center Point*/, radius/*radius*/, CV_RGB(0, 0, 255));
return 1;
}
최적화된 코드
//교수님 코드
#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);
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;
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' 카테고리의 다른 글
[OPENCV-C++ ] 형태학 기반 영상처리 Dilation 팽창 (0) | 2023.11.26 |
---|---|
[OPENCV-C++ ] 형태학 기반 영상처리 Erosion 침식 (0) | 2023.11.26 |
[OPENCV-C++ ] findcontours(외곽 테두리 따주는 친구-segmentation 이어서) (0) | 2023.11.26 |
[OPENCV-C++ ] segmentation (0) | 2023.11.26 |
[OPENCV-C++ ] sigma를 활용한 gaussian filter (1) | 2023.11.26 |