1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
| #include <opencv2/opencv.hpp> using namespace cv;
void getHistogram(Mat &img, double *histogram){ int H[256] = {0}; for (int nrow = 0; nrow < img.rows; nrow++) { for (int ncol = 0; ncol < img.cols; ncol++) { int h = img.ptr<uchar>(nrow)[ncol]; H[h] ++; } } int N = img.rows * img.cols; for (int i = 0; i <= 255; i++) { histogram[i] = double(H[i]) / double(N); } }
void Otsu(double *histogram, double &threshold){ double w1 = 0.0, w2 = 1.0; double u1, u2; double max = 0.0; double sum = 0.0; for (int i = 0; i <= 255; i++) { sum += i * histogram[i]; } double sum1 = 0.0, sum2 = sum; double threshold1 = 0.0, threshold2 = 0.0;
for (int t = 1; t <= 255; t++) { w1 += histogram[t]; w2 = 1 - w1; if (w1 == 0) { continue; }else if (w2 == 0){ break; } sum1 += t * histogram[t]; sum2 = sum - sum1; u1 = sum1 / w1; u2 = sum2 / w2; double v = w1 * w2 * (u1 - u2) * (u1 - u2); if (v >= max) { threshold1 = t; if (v > max) { threshold2 = t; } max = v; } } threshold = (threshold1 + threshold2) / 2; }
void getOtsuImg(Mat img, Mat &result, double threshold){ for (int nrow = 0; nrow <= img.rows; nrow++) { for (int ncol = 0; ncol <= img.cols; ncol++) { if (img.ptr<uchar>(nrow)[ncol] <= threshold) { result.ptr<uchar>(nrow)[ncol] = 0; }else{ result.ptr<uchar>(nrow)[ncol] = 255; } } } }
int main() { Mat img,result; img = imread("Otsu.png", IMREAD_GRAYSCALE); if (img.empty()) { printf("读取图像文件失败"); system("pause"); return -1; }
double histogram[256] = {0}; getHistogram(img, histogram);
double threshold = 0; Otsu(histogram, threshold);
result = img.clone(); getOtsuImg(img, result, threshold); imshow("img", img); imshow("Otsu", result); waitKey(); imwrite("result.jpg", result); return 0; }
|