23.11.16 (목) 41일차
첫 번째 도형 날개 부분이 줄어든 걸 확인할 수 있다.
침식할 때는 데이터가 사라질 수 있음을 유의하고 사용해야 한다.
마스크 크기를 늘려주면 더 많이 침식된다
#pragma once
#include "ISP.h"
int main()
{
std::string fileName = "../KCCImageNet/images/circle_plate.png";
cv::Mat src_gray = cv::imread(fileName, cv::ImreadModes::IMREAD_GRAYSCALE);
Mat src_bin;
threshold(src_gray, src_bin, 150, 255, ThresholdTypes::THRESH_BINARY);
uchar* pData = src_bin.data;
size_t width = src_gray.cols;
size_t height = src_gray.rows;
Mat src_erosion = Mat::zeros(height, width, CV_8UC1);
// 침식 (erosion)
const int SE_sz = 3;
int SE_half_sz = SE_sz / 2;
int SE_Cross[SE_sz * SE_sz] =
{
0, 255, 0,
255, 255, 255,
0, 255, 0,
};
int SE_Rect[SE_sz * SE_sz] =
{
255, 255, 255,
255, 255, 255,
255, 255, 255,
};
// full image searching
uchar* pDst = src_erosion.data;
for (size_t row = SE_half_sz; row < height - SE_half_sz; row++) {
for (size_t col = SE_half_sz; col < width - SE_half_sz; col++) {
//struct element
bool allone = true;
for (int h = -SE_half_sz; h <= SE_half_sz; h++) {
for (int w = -SE_half_sz; w <= SE_half_sz; w++) {
int index = (row + h) * width + (col + w);
int index_SE = (h + SE_half_sz) * SE_sz + (w + SE_half_sz);
uchar input = pData[index];
//input == 0 : background
bool condition = (input == 0 && SE_Cross[index_SE] == 255);
if (condition == true)
{
allone = false;
break;
}
}
if (!allone) break;
}
if (allone)
pDst[row * width + col] = 255;
else
pDst[row * width + col] = 0;
}
}
uchar* pErosion = pDst;
for (size_t row = SE_half_sz; row < height - SE_half_sz; row++) {
for (size_t col = SE_half_sz; col < width - SE_half_sz; col++) {
bool condition = false;
for (int h = -SE_half_sz; h <= SE_half_sz; h++) {
for (int w = -SE_half_sz; w <= SE_half_sz; w++) {
int index = (row + h) * width + (col + w);
int index_SE = (h + SE_half_sz) * SE_sz + (w + SE_half_sz);
uchar input = pErosion[index];
//input == 0 : background
condition = (input == 255 && SE_Cross[index_SE] == 255);
if (condition == true)
{
break;
}
}
if (condition == true)
{
break;
}
}
}
}
return 1;
}
#pragma once
#include "ISP.h"
int main()
{
std::string fileName = "../KCCImageNet/images/circle_plate.png";
cv::Mat src_gray = cv::imread(fileName, cv::ImreadModes::IMREAD_GRAYSCALE);
Mat src_bin;
threshold(src_gray, src_bin, 150, 255, ThresholdTypes::THRESH_BINARY);
uchar* pData = src_bin.data;
size_t width = src_gray.cols;
size_t height = src_gray.rows;
Mat src_dilation = Mat::zeros(height, width, CV_8UC1);
const int SE_sz = 3;
int SE_half_sz = SE_sz / 2;
int SE_Cross[SE_sz * SE_sz] =
{
0, 255, 0,
255, 255, 255,
0, 255, 0,
};
int SE_Rect[SE_sz * SE_sz] =
{
255, 255, 255,
255, 255, 255,
255, 255, 255,
};
// full image searching
uchar* pDst = src_dilation.data;
for (size_t row = SE_half_sz; row < height - SE_half_sz; row++) {
for (size_t col = SE_half_sz; col < width - SE_half_sz; col++) {
//struct element
bool allone = true;
for (int h = -SE_half_sz; h <= SE_half_sz; h++) {
for (int w = -SE_half_sz; w <= SE_half_sz; w++) {
int index = (row + h) * width + (col + w);
int index_SE = (h + SE_half_sz) * SE_sz + (w + SE_half_sz);
uchar input = pData[index];
//input == 0 : background
bool condition = (input == 0 && SE_Cross[index_SE] == 255);
if (condition == true)
{
allone = false;
break;
}
}
if (!allone) break;
}
if (allone)
pDst[row * width + col] = 255;
else
pDst[row * width + col] = 0;
}
}
// dilation
uchar* pDilation = src_dilation.data;
for (size_t row = SE_half_sz; row < height - SE_half_sz; row++) {
for (size_t col = SE_half_sz; col < width - SE_half_sz; col++) {
bool condition = false;
if (condition == true)
{
for (int h = -SE_half_sz; h <= SE_half_sz; h++) {
for (int w = -SE_half_sz; w <= SE_half_sz; w++) {
int index = (row + h) * width + (col + w);
int index_SE = (h + SE_half_sz) * SE_sz + (w + SE_half_sz);
if (SE_Cross[index_SE] == 255)
pDilation[index] = 255;
}
}
}
}
}
return 1;
}
shape 모양원본 이미지
축소 이미지
팽창 이미지
int kernelSz = 1;
int shape = MorphShapes::MORPH_CROSS;
Size sz = Size(2 * kernelSz + 1, 2 * kernelSz + 1);
Mat SE = getStructuringElement(shape, sz);
// 침식 erode
// src :: src_bin
Mat src_erode;
erode(src_bin, src_erode, SE);
Mat diff_erode = src_bin - src_erode;
Mat src_dilate;
dilate(src_bin, src_dilate, SE);
Mat diff_dilate = src_dilate - src_bin;
첫 번째 도형의 날개가 사라진 걸 볼 수 있다
세 번째 도형이 붙었다
int kernelSz = 3;
int shape = MorphShapes::MORPH_CROSS;
Size sz = Size(2 * kernelSz + 1, 2 * kernelSz + 1);
Mat SE = getStructuringElement(shape, sz);
// 침식 erode
// src :: src_bin
Mat src_erode;
erode(src_bin, src_erode, SE);
Mat diff_erode = src_bin - src_erode;
Mat src_dilate;
dilate(src_bin, src_dilate, SE);
Mat diff_dilate = src_dilate - src_bin;
// extension
Mat src_open, src_closing;
int type = MorphTypes::MORPH_OPEN;
morphologyEx(src_bin, src_open, type, SE);
type = MorphTypes::MORPH_CLOSE;
morphologyEx(src_bin, src_closing, type, SE);
원본 영상
이진화 처리
Opening으로 노이즈 제거하고 다시 사이즈 유지시키기하는 이유: contour가 15개가 출력되는데, 우리 눈에 보이는 건 6개 뿐이다. 자잘한 것들이 잡힌다는 뜻이기 때문에 침식하고 팽창시킨다
(침식만 시키면 원 사이즈가 줄어든다)
drawing
Result Image
#pragma once
#include "ISP.h"
int main()
{
std::string fileName = "../KCCImageNet/images/brake_disk/brake_disk_part_01.png";
cv::Mat src_gray = cv::imread(fileName, cv::ImreadModes::IMREAD_GRAYSCALE);
Mat src_result;
cvtColor(src_gray, src_result, cv::COLOR_GRAY2BGR);
uchar* pData = src_gray.data;
size_t width = src_gray.cols;
size_t height = src_gray.rows;
Mat src_bin = Mat::zeros(Size(width, height), CV_8UC1);
uchar* pDataBin = src_bin.data;
int threshold = 245;
// 이진화, Binary
for (size_t i = 0; i < width * height; i++)
{
int value = pData[i];
(value > threshold) ? pDataBin[i] = 255 : pDataBin[i] = 0;
}
int kernelSz = 2;
int shape = MorphShapes::MORPH_CROSS;
cv::Size sz = Size(2 * kernelSz + 1, 2 * kernelSz + 1);
Mat SE = getStructuringElement(shape, sz);
Mat src_open;
int type = MorphTypes::MORPH_OPEN;
morphologyEx(src_bin, src_open, type, SE);
RNG rng(12345);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(src_open, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
Mat drawing = Mat::zeros(src_open.size(), CV_8UC3);
for (size_t i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(drawing, contours, (int)i, color, -2, LINE_8, hierarchy, 0);
int CoGx, CoGy;
CoGx, CoGy = 0, 0;
int rad;
int accX = 0, accY = 0;
int length = contours[i].size();
int x_min = width, x_max = 0, y_min = height, y_max = 0;
for (size_t n = 0; n < length; n++)
{
accX += contours[i].at(n).x;
accY += contours[i].at(n).y;
if (x_min > contours[i].at(n).x)
x_min = contours[i].at(n).x;
if (x_max < contours[i].at(n).x)
x_max = contours[i].at(n).x;
if (y_min > contours[i].at(n).y)
y_min = contours[i].at(n).y;
if (y_max < contours[i].at(n).y)
y_max = contours[i].at(n).y;
}
CoGx = accX / length;
CoGy = accY / length;
rad = (x_max - x_min) / 2;
drawContours(src_result, contours, (int)i, CV_RGB(255, 255, 0), -2, LINE_8, hierarchy, 0);
line(src_result, Point(CoGx, CoGy - rad), Point(CoGx, CoGy + rad), CV_RGB(255, 0, 0), 5);
double area = contourArea(contours[i]);
double arcLen = arcLength(contours[i], true);
string msg;
msg = format("area = %.1f", area);
putText(src_result, msg, Point(CoGx, CoGy + 30 * 0), FONT_HERSHEY_SIMPLEX, 1, CV_RGB(0, 0, 255), 2, 8);
msg = format("x,y = %d, %d", CoGx, CoGy);
putText(src_result, msg, Point(CoGx, CoGy + 30 * 1), FONT_HERSHEY_SIMPLEX, 1, CV_RGB(0, 0, 255), 2, 8);
msg = format("length = %.1f", arcLen);
putText(src_result, msg, Point(CoGx, CoGy + 30 * 2), FONT_HERSHEY_SIMPLEX, 1, CV_RGB(0, 0, 255), 2, 8);
}
return 1;
}