OpenCV_Segmentation,Labeling - chloe73/openCV GitHub Wiki
- ์ด๋ฏธ์ง๋ฅผ ๊ทธ๋ ์ด์ค์ผ์ผ๋ก ๋ณํํ๋ฉด ํฝ์ ์ ๊ฐ(0~255)์ ๋๊ณ ๋ฎ์์ ๊ตฌ๋ถํ ์ ์๋ค.
- ์ด๊ฒ์ ์งํ์ ๋๋ฎ์ด๋ก ๊ฐ์ ํ๊ณ ๋์ ๋ถ๋ถ์ ๋ด์ฐ๋ฆฌ , ๋ฎ์ ๋ถ๋ถ์ ๊ณ๊ณก์ด๋ผ๊ณ ํํํ๋ค.
- ๊ทธ๊ณณ์ ๋ฌผ์ ๋ถ๋๋ค๊ณ ์๊ฐํ๋ฉด ๋ฌผ์ด ์์ด๋ ๋ถ๋ถ์ด ์๊ธธ๊ฒ์ด๋ค.
- ๊ทธ ๋ถ๋ถ์ ๊ฒฝ๊ณ์ ์ ๋ง๋ค์ด ์๋ก ์์ด์ง ์๊ฒ ํด์ค๋ค.
- ๊ทธ ๊ฒฝ๊ณ์ ์ ์ด๋ฏธ์ง์ ๊ตฌ๋ถ์ง์ ์ผ๋ก ํ์ ํ์ฌ ์ด๋ฏธ์ง ๋ถํ ์ ํ๋ค.
- ๋์งํธ ์์์ ์ฌ๋ฌ๊ฐ์ ์์ญ์ผ๋ก ๋ถํ ํ๋ ๊ณผ์ ์ผ๋ก Object classification์ ํ์ฉ๋๋ค.
- ์์์ ๋ถํ ํ๋ ๋ฐฉ๋ฒ์๋ Thresholding์ด ์๋๋ฐ ์ด๋ฅผ ์ํํ๊ธฐ ์ํด์๋ ๋ค์๊ณผ ๊ฐ์ ๋๊ฐ์ง ๊ฐ์ ์ ํ๋ค.
- ๋ถํ ํ๊ณ ์ถ์ ๋ฌผ์ฒด์ ๋ฐฐ๊ฒฝ์ ๋ฐ๊ธฐ๊ฐ์ ๋ค๋ฅด๋ค.
- ๋ฐฐ๊ฒฝ ์์ญ ๋ด์์์ ๋ฌผ์ฒด ์์ญ ๋ด์์์ ๋ฐ๊ธฐ๊ฐ์ ์ฐจ์ด๊ฐ ๋ณ๋ก ์๋ค.
- ์ด์งํ ํ ์ด๋ฏธ์ง์์ ํ์ฒด๋ฅผ ์์๋ณด๊ธฐ ์ํด ๊ฐ์ ํฝ์ ๊ฐ๋ค๋ผ๋ฆฌ ๊ทธ๋ฃนํํ์ฌ ๋ฒํธ๋ฅผ ๋งค๊ธด ๊ฒ์ ๋ ์ด๋ธ๋ง์ด๋ผ๊ณ ํ๋ค.
- ๋ ์ด๋ธ๋ง์ ํฌ๊ฒ 4๋ฐฉํฅ๊ณผ 8๋ฐฉํฅ์ผ๋ก ๋๋์ด์ง๋ค.
- 4๋ฐฉํฅ์ ํ ํฝ์ ์ ์ค์ฌ์ผ๋ก ์ข์ฐ์ํ๋ก ์ธ์ ํ ํฝ์ ์ ๊ทธ๋ฃนํํ๊ณ , 8๋ฐฉํฅ์ ์ข์ฐ์ํ์ ๋๊ฐ์ 4๋ฐฉํฅ๊ณผ ์ธ์ ํ ํฝ์ ์ ๊ทธ๋ฃนํํ๋ค.
-
์์๋ก ํ๋์ threshold T๋ฅผ ์ ํ๋ค.
-
T๋ฅผ ์ด์ฉํด ํ๋์ ์์์ ๋๊ฐ์ ์์ญ์ผ๋ก ๋ถํ ํ๋ค.
-
๊ฐ๊ฐ์ ์์ญ์ ํด๋นํ๋ ํฝ์ ์ ํ๊ท m1, m2๋ฅผ ๊ตฌํ๋ค.
-
m1, m2์ ํ๊ท ์ผ๋ก ์๋ก์ด threshold T๋ฅผ ๊ตฌํ๋ค. T = 0.5X(m1+m2)
-
์ฒซ๋ฒ์งธ์ ๋๋ฒ์งธ threshold T์ ๊ฐ์ด ์ ์ฌํ๋ค๋ฉด ์ข ๋ฃํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด 2~4๋จ๊ณ๋ฅผ ๋ฐ๋ณตํ๋ค.
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <stdio.h>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat image, thresh;
int thresh_T, low_cnt, high_cnt, low_sum, high_sum, i, j, th;
thresh_T = 200; // ์ด๊ธฐ threshold ๊ฐ
th = 10; // ์ด๊ธฐ threshold์ ๋์ค threshold์ ๊ฐ์ ์ฐจ์ด์ ๊ธฐ์ค
low_cnt = high_cnt = low_sum = high_sum = 0;
image = imread("111.jpg", 0);
cout << "threshold value:" << thresh_T << endl;
while(1) {
for(j = 0; j < image.rows ; j++) {
for(i = 0; i < image.cols; i ++) {
if(image.at<uchar>(j, i) < thresh_T) {
low_sum += image.at<uchar>(j, i);
low_cnt++;
} else {
high_sum += image.at<uchar>(j, i);
high_cnt++;
}
}
} if(abs(thresh_T - (low_sum / low_cnt + high_sum / high_cnt) / 2.0f) < th)
{
break;
} else {
thresh_T = (low_sum / low_cnt + high_sum / high_cnt) / 2.0f;
cout << "threshold value:" << thresh_T << endl;
low_cnt = high_cnt = low_sum = high_sum = 0;
}
}
threshold(image, thresh, thresh_T , 255, THRESH_BINARY);
imshow("Input image", image);
imshow("thresholding", thresh);
waitKey(0);
}
//Otsu's method
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <stdio.h>
#include <iostream>
using namespace cv;
using namespace std;
int main() {
Mat image, result;
image = imread ("111.jpg", 0);
threshold(image, result, 0, 255, THRESH_BINARY | THRESH_OTSU); // 0๊ณผ 255๋ minimum & maximum
imshow("Input image", image);
imshow("result", result);
waitKey(0);
}
//Local (adaptive) thresholding
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <stdio.h>
#include <iostream>
using namespace cv;
using namespace std;
int main() {
Mat image, binary, adaptive_binary;
image = imread("111.jpg", 0);
threshold(image, binary, 150, 255, THRESH_BINARY);
adaptiveThreshold(image, adaptive_binary, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 85, 15); // 85 : 85X85, 15 : C
imshow("Input image", image);
imshow("binary", binary);
imshow("adaptive binary", adaptive_binary);
waitKey(0);
}
๐กLabeling
#include <iostream>
#include <opencv2/core/mat.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
using namespace std;
int main() {
Mat img_gray, img_color, img_binary;
img_gray = imread("111.jpg", IMREAD_GRAYSCALE);
threshold(img_gray, img_binary, 127, 255, THRESH_BINARY);
cvtColor(img_gray, img_color, COLOR_GRAY2BGR);
Mat img_labels, stats, centroids;
int numOfLables = connectedComponentsWithStats(img_binary, img_labels,
stats, centroids, 8, CV_32S);
//๋ผ๋ฒจ๋ง๋ ์ด๋ฏธ์ง์ค ํน์ ๋ผ๋ฒจ์ ์ปฌ๋ฌ๋ก ํํํด์ฃผ๊ธฐ
for (int y = 0; y < img_labels.rows; ++y) {
int* label = img_labels.ptr<int>(y);
Vec3b* pixel = img_color.ptr<Vec3b>(y);
for (int x = 0; x < img_labels.cols; ++x) {
if (label[x] == 3) {
pixel[x][2] = 0;
pixel[x][1] = 255;
pixel[x][0] = 0;
}
}
}
//๋ผ๋ฒจ๋ง ๋ ์ด๋ฏธ์ง์ ๊ฐ๊ฐ ์ง์ฌ๊ฐํ์ผ๋ก ๋๋ฌ์ธ๊ธฐ
for (int j = 1; j < numOfLables; j++) {
int area = stats.at<int>(j, CC_STAT_AREA);
int left = stats.at<int>(j, CC_STAT_LEFT);
int top = stats.at<int>(j, CC_STAT_TOP);
int width = stats.at<int>(j, CC_STAT_WIDTH);
int height = stats.at<int>(j, CC_STAT_HEIGHT);
rectangle(img_color, Point(left, top), Point(left + width, top + height),
Scalar(0, 0, 255), 1);
putText(img_color, to_string(j), Point(left + 20, top + 20),
FONT_HERSHEY_SIMPLEX, 1, Scalar(255, 0, 0), 2);
}
imshow("result", img_color);
waitKey(0);
}
https://yeoeun-ji.tistory.com/17
https://sss20-02.tistory.com/26
๋ผ๋ฒจ๋ง
https://webnautes.tistory.com/823
https://eehoeskrap.tistory.com/279
https://poorman.tistory.com/176
Watershed ์๊ณ ๋ฆฌ์ฆ์ ๋ ธ์ด์ฆ ๋ฑ์ผ๋ก ์ธํด์ ์์ ๋ถํ ์ด ํ์ ์ด์์ผ๋ก ๋ ์ ์๋ค.
๊ทธ๋์ OpenCV์์๋ ๋ง์ปค ๊ธฐ๋ฐ watershed ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํํ๋ค
๋ณํฉ์ด ๋ ๊ณ๊ณก์ ๊ณผ ๋ณํฉ์ด ๋์ง ์์ ๊ณ๊ณก์ ์ ์ง์ ํด์ฃผ๋ ๋ฐฉ๋ฒ์ด๋ค.
Watershed ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฉํ๊ธฐ ์ ์ ์์ญ์ ๋๋์ด ๋ผ๋ฒจ์ ๋ถ์ฌํด์ค๋ค.
์ค๋ธ์ ํธ๋ผ๊ณ ์๊ฐ๋๋ ์์ญ๊ณผ ๋ฐฐ๊ฒฝ์ด๋ผ๊ณ ์๊ฐ๋๋ ์์ญ์ ๋ผ๋ฒจ์ ๋ถ์ฌํ๋ค.
ํ์คํ์ง ์์ ์์ญ์ ๋ผ๋ฒจ์ 0์ผ๋ก ๋ถ์ฌํ๋ค.
โ ์ด๋ฐ์์ผ๋ก ์ด๋ฏธ์ง์ ๋ผ๋ฒจ์ ๋ถ์ฌํ๋ ๊ฒ์ ๋ง์ปค ๋ผ๊ณ ํ๋ค.
์ด์ ๋ถํฐ Watershed ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฉํ๋ค.
๋ง์ปค ์ง์ ๋ถํฐ ์์ํ์ฌ ๋ผ๋ฒจ๊ฐ์ด 0์ธ ์์ญ์ ๋ํ ๋ผ๋ฒจ๊ฐ์ ์ ๋ฐ์ดํธํ๋ค.
์ค๋ธ์ ํธ ์ฌ์ด์ ๊ฒฝ๊ณ์ ๋ผ๋ฒจ์ -1์ด ๋๋ค.
์ด ์ด๋ฏธ์ง๋ ๋์ ์ด ์๋ก ๋ถ์ด ์๋ค.
watershed ์๊ณ ๋ฆฌ์ฆ๊ณผ Distance Transform์ ์ฌ์ฉํ์ฌ ์๋ก ๋ถ์ด์๋ ๋์ ์ ๋ถ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค.
import numpy as np
import cv2 as cv
img = cv2.imread("C:/Users/ParkSangHoon/Desktop/OpenCV_ img_files/coins2.png")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)
cv.imshow("result", thresh)
cv.waitKey(0)
์ถ๋ ฅํ๋ฉด
์ด์ ์คํ๋์ ์ ์ฉํ์ฌ ๋ ธ์ด์ฆ๋ฅผ ์ ๊ฑฐํ๊ณ ํฝ์ฐฝ(dilate) ์ฐ์ฐ์ ์ ์ฉํ์ฌ ๋์ ์์ญ ๋ด์ ์์ ์ ์๋ ๊ณต๋ฐฑ์ ๋งค๊พผ๋ค.
๋์ ์ด ๊ฒ์ถ๋ ์ ์๋ ๋ฐฐ๊ฒฝ ์์ญ = sure_bg
kernel = np.ones((3,3),np.uint8)
opening = cv.morphologyEx(thresh,cv.MORPH_OPEN,kernel, iterations = 2)
sure_bg = cv.dilate(opening,kernel,iterations=3)
๋์ ์ค์ ๋ถ๋ถ์ ๊ฒ์ถํ๊ธฐ ์ํด์ distance transform๋ฅผ ์ ์ฉํ ํ ์ด์งํ๋ฅผ ํฉ๋๋ค
์ค๋ฅธ์ชฝ ์ด๋ฏธ์ง๊ฐ ๋์ ์์ญ์ด ํ์คํ ๋์ ์ค์ ์์ญ(sure_fg)์ ๋๋ค.
dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 5)
result_dist_transform = cv.normalize(dist_transform, None, 255, 0, cv.NORM_MINMAX, cv.CV_8UC1)
ret, sure_fg = cv.threshold(dist_transform, 0.7*dist_transform.max(),255, cv.THRESH_BINARY)
๋ฐฐ๊ฒฝ ์์ญ(sure_bg)์์ ๋์ ์ค์ ์์ญ(sure_fg)๋ฅผ ๋บ๋ค.
sure_fg = np.uint8(sure_fg)
unknown = cv.subtract(sure_bg,sure_fg)
์๋ ์ด๋ฏธ์ง์ฒ๋ผ ๋์ ์ธ์ง ๋ฐฐ๊ฒฝ์ธ์ง ์์ง์ ์ ์ ์๋ ์์ญ์ด ์กด์ฌํ๊ฒ ๋๋ค.
๋์ ์ค์ ์์ญ ์ด๋ฏธ์ง๋ฅผ ๋ผ๋ฒจ๋งํ ํ ์์ง ๋์ ์ธ์ง ๋ฐฐ๊ฒฝ์ธ์ง ์ ์ ์๋ ์์ญ์ ๋ผ๋ฒจ๊ฐ์ 0์ผ๋ก ์ง์ ํ๋ค.
๋ฐฐ๊ฒฝ์ด ํ์คํ ์์ญ์ 1์ด ๋๋ค.
# Marker labelling
ret, markers = cv.connectedComponents(sure_fg)
# Add one to all labels so that sure background is not 0, but 1
markers = markers+1
# Now, mark the region of unknown with zero
markers[unknown==255] = 0
watershed ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฉํ๋ฉด ๋์ ์ธ๊ณฝ์ ๋ผ๋ฒจ๊ฐ์ผ๋ก -1์ ๊ฐ์ง๋ฉฐ ๋ฐฐ๊ฒฝ์ ๋ผ๋ฒจ๊ฐ์ผ๋ก 1์ ๊ฐ๊ฒ๋ฉ๋๋ค.
markers = cv.watershed(img, markers)
img[markers == -1] = [255, 0, 0]
img[markers == 1] = [255, 255, 0]
์ ์ฒด์ฝ๋
import numpy as np
import cv2 as cv
img = cv.imread("C:/Users/ParkSangHoon/Desktop/OpenCV_ img_files/coins2.png")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)
# noise removal
kernel = np.ones((3,3),np.uint8)
opening = cv.morphologyEx(thresh,cv.MORPH_OPEN,kernel, iterations = 2)
# sure background area
sure_bg = cv.dilate(opening,kernel,iterations=3)
# Finding sure foreground area
dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 5)
result_dist_transform = cv.normalize(dist_transform, None, 255, 0, cv.NORM_MINMAX, cv.CV_8UC1)
ret, sure_fg = cv.threshold(dist_transform, 0.7*dist_transform.max(),255, cv.THRESH_BINARY)
# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv.subtract(sure_bg,sure_fg)
# Marker labelling
ret, markers = cv.connectedComponents(sure_fg)
# Add one to all labels so that sure background is not 0, but 1
markers = markers+1
# Now, mark the region of unknown with zero
markers[unknown==255] = 0
markers = cv.watershed(img, markers)
img[markers == -1] = [255, 0, 0]
img[markers == 1] = [255, 255, 0]
cv.imshow("dist_transform", result_dist_transform)
cv.imshow("unknown", unknown)
cv.imshow("sure_fg", sure_fg)
cv.imshow("sure_bg", sure_bg)
cv.imshow("result", img)
cv.waitKey(0)
https://leechamin.tistory.com/281
https://blog.naver.com/samsjang/220601488606
https://webnautes.tistory.com/1281
https://opencv-python.readthedocs.io/en/latest/doc/27.imageWaterShed/imageWaterShed.html
๋ผ๋ฒจ๋ง(labeling)์ด๋?
- ์ด์งํํ ์ด๋ฏธ์ง์์ ๊ฐ์ฒด๋ฅผ ๊ฐ๊ฐ ๋ถ๋ณํ๊ธฐ ์ํด ์ธ์ ํ ํฝ์ ๊ฐ๋ค๋ผ๋ฆฌ ๊ทธ๋ฃนํํ์ฌ ๋ฒํธ๋ฅผ ๋งค๊ธด ๊ฒ์ด๋ค.
- ๋ผ๋ฒจ๋ง์ ์ข์ธก ์๋จ๋ถํฐ ์ฐ์ธก ์๋จ ๋ฐฉํฅ์ผ๋ก ์ด๋ํ๋ฉด์ ๋ฒํธ๋ฅผ ๋ถ์ฌํ๋ค.
4๋ฐฉํฅ ๋ผ๋ฒจ๋ง์ ํ ํฝ์
์ ์ค์ฌ์ผ๋ก ์ญ์๊ฐ ๋ชจ์์ผ๋ก ์ธ์ ํ ํฝ์
์ ๊ทธ๋ฃนํํ๋ค.




- ๋ ์ด๋ธ๋ง(๋ผ๋ฒจ๋ง) ์๊ณ ๋ฆฌ์ฆ์์ 0์ ๋ฐฐ๊ฒฝ 1์ด์์ ๊ฐ์ฒด(Object)๋ก ํ๋จํ๋ค.
๋ ์ด๋ธ๋ง ํจ์ cv2.connectedComponents()
- ๋ ์ด๋ธ๋ง ํจ์๋ฅผ ์ด์ฉํ์ฌ ๋ ์ด๋ธ๋งต์ ์์ฑํ ์ ์๋ค.
retval, labels = cv2.connectedComponent(image, lable=None, connectivity=None, ltype=None)
- return
- retval: ๊ฐ์ฒด ๊ฐ์ +1(๋ฐฐ๊ฒฝ) ์ ๋ฐํ
- labels: ๋ ์ด๋ธ๋งต ํ๋ ฌ ๋ฐํ
- parameter
- image: 8๋นํธ 1์ฑ๋ ์์
- labels: ๋ ์ด๋ธ ๋งต ํ๋ ฌ(์ ๋ ฅ ์์๊ณผ ๊ฐ์ ํฌ๊ธฐ, numpy.ndarray)
- connectivity: 4 ๋๋ 8(default)
- type: label ํ์ . cv2.CV_32S(default) ๋๋ cv2.CV_16S
import cv2 as cv
#์ด๋ฏธ์ง๋ฅผ ํ๋ฐฑ์ผ๋ก ๋ถ๋ฌ์จ ํ ๋ฐ์ด๋๋ฆฌ๋ก ๋ณํ(์ด์งํ)
img = cv.imread("test.jpg", cv.IMREAD_GRAYSCALE)
ret, binar = cv.threshold(img, 0, 255, cv.THRESH_OTSU)
#๋ ์ด๋ธ๋ง
retval, labels = cv2.connectedComponent(binar)
๊ฐ์ฒด ์ ๋ณด๋ฅผ ํจ๊ป ๋ฐํํ๋ ๋ ์ด๋ธ๋ง ํจ์ cv2.connectedComponentsWithStats()
- object์ ์์น์ ํฌ๊ธฐ, ์ค์ฌ์์น, ํฝ์ ๋ฉด์ ์ ๋ฐํํ๋ค
retval, labels, stats, centroids = cv2.connectedComponentsWithStats(image, labels=None, stats=None, centroids=None, connectivity=None, ltype=None)
- return
- retval: ๊ฐ์ฒด ๊ฐ์ +1(๋ฐฐ๊ฒฝ) ์ ๋ฐํ
- labels: ๋ ์ด๋ธ๋งต ํ๋ ฌ ๋ฐํ
- stats: Nํ 5์ด, N์ retval ๊ฐ์ด๋ฉฐ, 5์ด์๋ x, y, width, height, area ์์ผ๋ก ์ ์ฅ๋จ
- centroids: Nํ 2์ด, 2์ด์๋ ๋ฌด๊ฒ์ค์ฌ ์ขํ์ธ x, y๊ฐ ์ ์ฅ๋จ
- parameter
- image: 8๋นํธ 1์ฑ๋ ์์
- labels: ๋ ์ด๋ธ ๋งต ํ๋ ฌ(์ ๋ ฅ ์์๊ณผ ๊ฐ์ ํฌ๊ธฐ, numpy.ndarray)
- stats: ๊ฐ Object์ ๋ฐ์ด๋ฉ ๋ฐ์ค, ํฝ์ ๋ฉด์ ์ ๋ด์ ํ๋ ฌ(numpy.ndaeeay.shape(N, 5), dtype=numpy.int32)
- centroids: ๊ฐ ๊ฐ์ฒด์ ๋ฌด๊ฒ ์ค์ฌ ์์น ์ ๋ณด๋ฅผ ๋ด์ ํ๋ ฌ numpy.ndarray. shape=(N, 2), dtype=numpy.float64.
- connectivity: 4 ๋๋ 8(default)
- ltype: label ํ์ . cv2.CV_32S(default) ๋๋ cv2.CV_16S
import cv2 as cv
#์ด๋ฏธ์ง๋ฅผ ํ๋ฐฑ์ผ๋ก ๋ถ๋ฌ์จ ํ ๋ฐ์ด๋๋ฆฌ๋ก ๋ณํ(์ด์งํ)
img = cv.imread("test.jpg", cv.IMREAD_GRAYSCALE)
ret, binar = cv.threshold(img, 0, 255, cv.THRESH_OTSU)
#๋ ์ด๋ธ๋ง
retval, labels, stats, centroids = cv2.connectedComponentWithStats(binar)
import cv2 as cv
import random
def setRandColor(min=0, max=255): #๋๋ค์์์ ๋ฐํํ๋ ํจ์
while True:
r = random.randrange(0, max)
g = random.randrange(0, max)
b = random.randrange(0, max)
if not(r < min and g < min and b < min):
return r, g, b
source = "source/test.jpeg"
origin = cv.imread(source, cv.IMREAD_COLOR)
origin = cv.resize(origin, (720, 720))
img = cv.cvtColor(origin, cv.COLOR_BGR2GRAY)
img = cv.GaussianBlur(img, (9, 9), 0)
ret, binar = cv.threshold(img, 0, 255, cv.THRESH_OTSU)
cv.imshow("binar", binar)
cnt, labels, stats, centroid = cv.connectedComponentsWithStats(binar)
count = 0
for i in range(0, cnt):
(x, y, w, h, area) = stats[i]
if area < 100:
continue
if area > 1500:
continue
if w > 700:
continue
if h > 700:
continue
cv.rectangle(origin, (x, y, w, h), (0, 255, 255))
count += 1
string = str(count)
cv.putText(origin, string, (x, y), cv.FONT_HERSHEY_PLAIN, 1.2, setRandColor(128, 255))
cv.imshow("Labeling", origin)
cv.waitKey(0)
cv.destroyAllWindows()


https://eehoeskrap.tistory.com/279
https://webnautes.tistory.com/823
https://poorman.tistory.com/176