《图像处理实例》 之 疏密程度统计
疏密程度统计
以下的改进是http://www.imagepy.org/的作者原创,我只是对其理解之后改进和说明,欢迎大家使用这个小软件!
如有朋友需要源工程,请在评论处留邮箱!
说明:
此方法是大佬给别的公司做的一个项目,本博文只对其进行方法说明!
目标:
假设给定一个标准,圆与圆之间的密度为Value,当大于这个密度的时候就是不符合要求!
方法:
1.填充每个圆形目标
2.背景和前景做变换(把圆作为背景)
3.对前景进行距离变换
4.求局部最大值
5.结合最大值位置和距离图对图像进行评估
运行步骤:
下面的红色圆代表物体之间的间隙,同时也代表疏密程度值!
核心程序:
1 //---fill black value 2 int FillBlock(Mat src, Mat &mask, Point center) 3 { 4 uchar back = src.at<uchar>(center.y, center.x); 5 vector<Point> fill_point; 6 int count = 0, count_mount = 1; 7 fill_point.push_back(center); 8 while (count < count_mount) 9 { 10 vector<uchar*> img; 11 vector<uchar*> msk; 12 for (int i = -1; i < 2; i++) 13 { 14 img.push_back(src.ptr<uchar>(fill_point[count].y + i)); 15 msk.push_back(mask.ptr<uchar>(fill_point[count].y + i)); 16 } 17 for (size_t i = 0; i < 3; i++) 18 { 19 for (int j = -1; j < 2; j++) 20 { 21 if (img[i][fill_point[count].x + j] == back && !(j == 0 && i == 1) && msk[i][fill_point[count].x + j] == 255) 22 { 23 fill_point.push_back(Point(fill_point[count].x + j, fill_point[count].y + i - 1)); 24 msk[i][fill_point[count].x + j] = 1; 25 } 26 } 27 } 28 msk[1][fill_point[count].x] = 1; 29 count_mount = fill_point.size() - 1; 30 fill_point.erase(fill_point.begin()); 31 } 32 return 0; 33 } 34 //---cal mask 35 //---@_src 36 //---@mask 37 void MaskImage(InputArray _src, Mat &mask) 38 { 39 Mat src = _src.getMat(),mask_tmp = Mat::zeros(src.size(), CV_8UC1); 40 mask_tmp.setTo(255); 41 Mat rows = Mat::zeros(Size(src.cols, 1), CV_8UC1), cols = Mat::zeros(Size(1, src.rows), CV_8UC1); 42 Mat src_rows_beg = mask_tmp.row(0); 43 Mat src_rows_end = mask_tmp.row(src.rows - 1); 44 Mat src_cols_beg = mask_tmp.col(0); 45 Mat src_cols_end = mask_tmp.col(src.cols - 1); 46 rows.copyTo(src_rows_beg); rows.copyTo(src_rows_end); 47 cols.copyTo(src_cols_beg); cols.copyTo(src_cols_end); 48 for (size_t i = 1; i < src.rows-1; i++) 49 { 50 uchar *img0 = src.ptr<uchar>(i - 1); 51 uchar *img = src.ptr<uchar>(i); 52 uchar *img1 = src.ptr<uchar>(i + 1); 53 uchar *msk = mask_tmp.ptr<uchar>(i); 54 for (size_t j = 1; j < src.cols-1; j++) 55 { 56 bool flag = false; 57 //msk[j] = img[j] == 0 ? 0 : msk[j]; 58 if (msk[j] != 255) continue; 59 flag = (img[j] < img[j - 1] || img[j] < img[j + 1] 60 || img[j] < img0[j] || img[j] < img0[j - 1] 61 || img[j] < img0[j + 1] || img[j] < img1[j] 62 || img[j] < img1[j - 1] || img[j] < img1[j + 1]) 63 ? true : false; 64 int tmp = flag == true ? FillBlock(src, mask_tmp, Point(j, i)) : 0; 65 } 66 } 67 mask = mask_tmp.clone(); 68 } 69 //---filter parts max value 70 //---@ 71 //---@ 72 //---@gap 73 //---@radius 74 75 vector<Point> Find_Max(InputArray _src, Mat&mask,int gap,int radius) 76 { 77 Mat src = _src.getMat(); 78 79 typedef struct MyStruct 80 { 81 Point position; 82 float data; 83 }MyStruct; 84 85 MaskImage(src, mask); 86 vector<MyStruct> max_point; 87 for (size_t i = 0; i < src.rows; i++) 88 { 89 uchar *img = src.ptr<uchar>(i); 90 uchar *msk = mask.ptr<uchar>(i); 91 for (size_t j = 0; j < src.cols; j++) 92 { 93 if (msk[j] != 255) continue; 94 MyStruct my_struct; 95 my_struct.data = img[j]; 96 my_struct.position = Point(j, i); 97 max_point.push_back(my_struct); 98 } 99 } 100 for (size_t i = 0; i < max_point.size(); i++) 101 { 102 for (size_t j = i; j < max_point.size(); j++) 103 { 104 MyStruct temp; 105 if (max_point[i].data <= max_point[j].data) 106 { 107 if (max_point[j].data == 0) continue; 108 temp = max_point[j]; 109 max_point[j] = max_point[i]; 110 max_point[i] = temp; 111 } 112 } 113 } 114 //---find max 115 for (size_t k = 0; k < max_point.size(); k++)//--- 116 { 117 uchar back = src.at<uchar>(max_point[k].position.y, max_point[k].position.x); 118 vector<Point> fill_point; 119 int count = 0, count_mount = 1; 120 fill_point.push_back(max_point[k].position); 121 122 while (count < count_mount && max_point[k].data != 1) 123 { 124 vector<uchar*> img; 125 vector<uchar*> msk; 126 for (int i = -1; i < 2; i++) 127 { 128 img.push_back(src.ptr<uchar>(fill_point[count].y + i)); 129 msk.push_back(mask.ptr<uchar>(fill_point[count].y + i)); 130 } 131 for (int i = 0; i < 3; i++) 132 { 133 for (int j = -1; j < 2; j++) 134 { 135 //--- 136 uchar x = pow((max_point[k].position.x - fill_point[count].x + j), 2); //(max_point[k].position.x - img[i][fill_point[count].x + j])*(max_point[k].position.x - img[i][fill_point[count].x + j]); 137 uchar y = pow((max_point[k].position.y - (fill_point[count].y + i - 1)) , 2); // (max_point[k].position.y - img[i][fill_point[count].y + j])*(max_point[k].position.y - img[i][fill_point[count].x + j]); 138 uchar distance = sqrt(x + y); 139 if (img[i][fill_point[count].x + j] <= img[1][fill_point[count].x] - gap 140 || msk[i][fill_point[count].x + j] == 3 141 || msk[i][fill_point[count].x + j] == 0 142 || (j == 0 && i == 1) 143 || distance >= radius) continue; 144 if (img[i][fill_point[count].x + j] == 2) max_point[k].data = 1; 145 msk[i][fill_point[count].x + j] = 3; 146 fill_point.push_back(Point(fill_point[count].x + j, fill_point[count].y + i - 1)); 147 count_mount++; 148 } 149 } 150 count++; 151 } 152 if (max_point[k].data == 1) 153 { 154 for (size_t i = 0; i < fill_point.size(); i++) 155 { 156 mask.at<uchar>(fill_point[i]) = 1; 157 } 158 } 159 else 160 { 161 for (size_t i = 0; i < fill_point.size(); i++) 162 { 163 mask.at<uchar>(fill_point[i]) = 2; 164 } 165 max_point[k].data = 255; 166 mask.at<uchar>(max_point[k].position) = 255; 167 } 168 } 169 }
作者:影醉阏轩窗
-------------------------------------------
个性签名:衣带渐宽终不悔,为伊消得人憔悴!
如果觉得这篇文章对你有小小的帮助的话,记得关注再下的公众号,同时在右下角点个“推荐”哦,博主在此感谢!