영상 분할 기법 중 하나
가정
1. 분할, 추출하고 싶은 물체와 배경의 밝기값 다름
2. 배경영역과 물체 영역 내의 밝기값이 단조로움(차이가 별로 없음)
적절한 threshold를 찾는 것이 중요
유의점
종류
global thresholding: 각 픽셀마다 같은 threshold 사용
기본 방식
othu's method
개념
좋은 threshold를 가지고 하나의 영상을 두개의 그룹으로 분할 하였다면 --> 두 그룹의 밝기 차이는 큼, 하나의 그룹에 속한 픽셀들의 값은 유사
즉, 다양한 t를 적용해보았을 때 픽셀값의 차이가 크다면 이 t는 좋은 t임 --> T를 사용하겠다는 의미
이미지 히스토그램으로 판단
방식
local thresgholding: 각 픽셀마다 다른 threshold 사용
코드
Threshold operation -->
double threshold (Mat src, Mat dst, double thresh, double maxval, int type)
• Apply fixed level thresh to each array element
• Typically used to get binary image from grayscale input image
• maxval : dst(I) = maxval if src(I) > thresh, 0 otherwise, when type is THRESH_BINARY
• Type : THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV
int main() {
Mat image = imread("lena.png");
cvtColor(image, image, CV_BGR2GRAY);
Mat dst;
threshold(image, dst, 100, 255, THRESH_BINARY);
imshow("dst", dst);
imshow("image", image);
waitKey(0);
return 0;
}
void adaptiveThreshold(Mat src, Mat dst, double maxval, int adaptiveMethod, int thresholdType, int blockSize, double C)
• adaptiveMethod:ADAPTIVETHRESH_MEAN_C, ADAPTIVETHRESH_GAUSSIAN_C
• thresholdType:THRESH_BINARY,THRESH_BINARY_INV
• blockSIze : size of neighborhood used to calculate threshold (3,5,7)
• C : constant subtracted from mean or weighted mean
• dst(x, y) is computed as MEAN(blockSize x blockSize)-C or GAUSSIAN(blockSize x blockSize) –C around (x,y)
int main() {
Mat image = imread("lena.png");
cvtColor(image, image, CV_BGR2GRAY);
Mat dst;
adaptiveThreshold(image, dst, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 7, 10);
imshow("dst", dst);
imshow("image", image);
waitKey(0);
return 0;
}
Void inRange(cv::InputArray src, cv::InputArray lowerb, cv::InputArray upperb, cv::OutputArray dst)
• src – first input array.
• lowerb – inclusive lower boundary array or a scalar
• upperb – inclusive upper boundary array or a scalar
• dst – output array of the same size as src and CV_8U type
int main() {
Mat image = imread("hand.png");
cvtColor(image, image, CV_BGR2YCrCb);
inRange(image, Scalar(0, 133, 77), Scalar(255, 173, 127), image);
imshow("inRange", image); // 사이의 값들 --> white, 사이 값x --> black
waitKey(0);
return 0;
}
--> Global Thresholding
- basic method
int main() {
Mat image, thresh;
int thresh_T, low_cnt, high_cnt, low_sum, high_sum, i, j, th;
thresh_T = 200;
th = 10;
low_cnt = high_cnt = low_sum = high_sum = 0;
image = imread("lena.png", 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 algorithm
W:weigt(가중치-전체 중)와 M:mean(평균)은 다름
int main() {
Mat image, result;
image = imread("lena.png", 0);
threshold(image, result, 0, 255, THRESH_BINARY | THRESH_OTSU);
imshow("Input image", image);
imshow("result", result);
waitKey(0);
}
Local(Adaptive) Thresholding
int main() {
Mat image, binary, adaptive_binary;
image = imread("opencv.jpg", 0);
threshold(image, binary, 150, 255, THRESH_BINARY); // globla thresholding
adaptiveThreshold(image, adaptive_binary, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 85, 15); // local thresholding
imshow("Input image", image);
imshow("binary", binary);
imshow("adaptive binary", adaptive_binary);
waitKey(0);
}
void grabCut(cv::InputArray img, cv::InputOutputArray mask, cv::Rect rect, cv::InputOutputArray bdgModel, cv::InputOutputArray fgdModel, int iterCount, int mode)
• img - Input image
• mask - mask image specifying background, foreground
• rect - Coordinates of squares with foreground
• bdgModel, fgdModel - Array used internally by algorithm
• iterCount - Number of iterations the algorithm must run
• mode - There are two types, GC_INIT_WITH_RECT and GC_INIT_WITH_MASK, each using a rectangle or mask to perform this algorithm
int main() {
Mat result, bgdModel, fgdModel, image, foreground;
image = imread("dog.png");
//inner rectangle which includes foreground
Rect rectangle(15, 0, 155, 240); // rectangle 크기
grabCut(image, result, rectangle, bgdModel, fgdModel, 10, GC_INIT_WITH_RECT); compare(result, GC_PR_FGD, result, CMP_EQ);
foreground = Mat(image.size(), CV_8UC3, Scalar(255, 255, 255)); image.copyTo(foreground, result);
imshow("original", image);
imshow("Result", result);
imshow("Foreground", foreground);
waitKey(0);
}