《图像处理实例》 之 二值图像分割
二值图像分割
以下的改进是http://www.imagepy.org/的作者原创,我只是对其理解之后改进和说明,欢迎大家使用这个小软件!
如有朋友需要源工程,请在评论处留邮箱!
原理:给定最大值处的种子点,然后进行涨水,各个种子点进行碰撞
1 void Binary_Division(InputArray& _src, Mat& mask, vector<Point> Edge_Point) 2 { 3 Mat src = _src.getMat();// , mask = _mask.getMat(); 4 5 mask = src.clone(); 6 distanceTransform(src, src, DIST_L2, DIST_MASK_3, 5); 7 normalize(src, src, 0, 255, NORM_MINMAX); 8 src.convertTo(src, CV_8UC1); 9 10 vector<vector<Point>> Edge_Data; 11 for (size_t i = 0; i < Edge_Point.size(); i++) 12 { 13 vector<Point> temp; 14 temp.push_back(Edge_Point[i]); 15 Edge_Data.push_back(temp); 16 mask.at<uchar>(Edge_Point[i]) = i + 1; 17 } 18 19 const int histSize = 255; 20 float range[] = { 0, 255 }; 21 const float* histRange = { range }; 22 Mat hist; 23 calcHist(&src, 1, 0, Mat(), hist, 1, &histSize, &histRange, true, false); 24 25 26 hist = hist.reshape(1, 1); 27 normalize(hist, hist, 0, 1000, NORM_MINMAX); 28 hist.convertTo(hist, CV_32FC1); 29 for (size_t level = 255; level > 0; level--) 30 { 31 if (!hist.at<float>(0, level)) continue; 32 FindRidge(src, mask, Edge_Data, level); 33 } 34 } 35 36 void FindRidge(InputArray& _src, Mat& mask, vector<vector<Point>>& Edge_Point,int level) 37 { 38 Mat src = _src.getMat(); 39 for (size_t i = 0; i < Edge_Point.size(); i++) 40 { 41 uchar pre_mark = i + 1; 42 for (int j = 0; j < Edge_Point[i].size(); j++) 43 { 44 vector<Point> temp_vector; 45 temp_vector.push_back(Point(Edge_Point[i][j].x, Edge_Point[i][j].y - 1)); 46 temp_vector.push_back(Point(Edge_Point[i][j].x, Edge_Point[i][j].y + 1)); 47 temp_vector.push_back(Point(Edge_Point[i][j].x - 1, Edge_Point[i][j].y)); 48 temp_vector.push_back(Point(Edge_Point[i][j].x + 1, Edge_Point[i][j].y)); 49 uchar* msk = mask.ptr(Edge_Point[i][j].y); 50 uchar* img = src.ptr(Edge_Point[i][j].y); 51 if (img[Edge_Point[i][j].x] < level) continue; 52 if (msk[j] == 254) 53 { 54 Edge_Point[i].erase(Edge_Point[i].begin() + j); 55 j--; 56 continue; 57 } 58 bool Flag = true; 59 for (size_t j = 0; j < temp_vector.size(); j++) 60 { 61 uchar* pre_data = mask.ptr(temp_vector[j].y); 62 if (pre_data[temp_vector[j].x] != pre_mark && pre_data[temp_vector[j].x] != 0 63 && pre_data[temp_vector[j].x] != 255 && pre_data[temp_vector[j].x] != (150+i+1) 64 && pre_data[temp_vector[j].x] != 254) 65 { 66 pre_data[temp_vector[j].x] = 254; 67 continue; 68 } 69 else if (pre_data[temp_vector[j].x] == 0 || pre_data[temp_vector[j].x] == pre_mark || pre_data[temp_vector[j].x] == 254) continue; 70 else if (pre_data[temp_vector[j].x] == 255) 71 { 72 if (src.at<uchar>(temp_vector[j]) <= level) 73 { 74 pre_data[temp_vector[j].x] = pre_mark; 75 Edge_Point[i].push_back(temp_vector[j]); 76 //Edge_Point[i].insert(Edge_Point[i].begin() + j + 1, temp_vector[j]); 77 } 78 else 79 { 80 FillBlock(src, Edge_Point[i], mask, level, Edge_Point[i][j], i); 81 Flag = false; 82 } 83 } 84 } 85 if (Flag) 86 { 87 mask.at<uchar>(Edge_Point[i][j]) = 150 + i + 1; 88 Edge_Point[i].erase(Edge_Point[i].begin() + j); 89 j--; 90 } 91 else 92 { 93 mask.at<uchar>(Edge_Point[i][j]) = i + 1; 94 } 95 } 96 } 97 } 98 99 void FillBlock(InputArray& _src, vector<Point>& Edge_Point, Mat& mask, int level, Point center,int seed_num) 100 { 101 Mat src = _src.getMat(); 102 mask.at<uchar>(center) = seed_num + 151; 103 vector<Point> fill_point; 104 int count = 0, count_mount = 1;//count; 105 fill_point.push_back(center); 106 while (count < count_mount) 107 { 108 vector<uchar*> img; 109 vector<uchar*> msk; 110 for (int i = -1; i < 2; i++) 111 { 112 img.push_back(src.ptr<uchar>(fill_point[count].y + i)); 113 msk.push_back(mask.ptr<uchar>(fill_point[count].y + i)); 114 } 115 for (size_t i = 0; i < 3; i++) 116 { 117 for (int j = -1; j < 2; j++) 118 { 119 if (img[i][fill_point[count].x + j] > level && !(j == 0 && i == 1) && msk[i][fill_point[count].x + j] == 255) 120 { 121 fill_point.push_back(Point(fill_point[count].x + j, fill_point[count].y + i - 1)); 122 msk[i][fill_point[count].x + j] = seed_num + 151; 123 } 124 else if (img[i][fill_point[count].x + j] <= level && msk[i][fill_point[count].x + j] == 255) 125 { 126 Edge_Point.push_back(Point(fill_point[count].x + j, fill_point[count].y + i - 1)); 127 msk[i][fill_point[count].x + j] = seed_num + 1; 128 } 129 } 130 } 131 //msk[1][fill_point[count].x] = 2; 132 count_mount = fill_point.size() - 1; 133 fill_point.erase(fill_point.begin()); 134 } 135 }
作者:影醉阏轩窗
-------------------------------------------
个性签名:衣带渐宽终不悔,为伊消得人憔悴!
如果觉得这篇文章对你有小小的帮助的话,记得关注再下的公众号,同时在右下角点个“推荐”哦,博主在此感谢!