图像增强

假装没事ソ 提交于 2019-12-05 09:07:54
  1 Mat ImageAHE(Mat img, int block)
  2 {
  3     Mat AHE_GO = img.clone();
  4     
  5     int width = img.cols;
  6     int height = img.rows;
  7     int width_block = width / block; //每个小格子的长和宽
  8     int height_block = height / block;
  9     //存储各个直方图  
 10     
 11     
 12     int tmp2[16 * 16][256] = { 0 };//10要和block保持一致
 13     float C2[16 * 16][256] = { 0.0 };
 14     //分块
 15     int total = width_block * height_block;//分割的总的块儿数
 16     for (int i = 0; i < block; i++)
 17     {
 18         for (int j = 0; j < block; j++)
 19         {
 20             int start_x = i * width_block;
 21             int end_x = start_x + width_block;
 22             int start_y = j * height_block;
 23             int end_y = start_y + height_block;
 24 
 25             int num = i + block * j;
 26             //遍历小块,计算直方图
 27             for (int ii = start_x; ii < end_x; ii++)
 28             {
 29                 for (int jj = start_y; jj < end_y; jj++)
 30                 {
 31                     int index = img.at<uchar>(jj, ii);
 32                     tmp2[num][index]++;
 33                 }
 34             }
 35             //计算累积分布直方图  
 36             for (int k = 0; k < 256; k++)
 37             {
 38                 if (k == 0)
 39                     C2[num][k] = 1.0f * tmp2[num][k] / total;
 40                 else
 41                     C2[num][k] = C2[num][k - 1] + 1.0f * tmp2[num][k] / total;
 42             }
 43         }
 44     }
 45     //将统计结果写入
 46     for (int i = 0; i < block; i++)
 47     {
 48         for (int j = 0; j < block; j++)
 49         {
 50             int start_x = i * width_block;
 51             int end_x = start_x + width_block;
 52             int start_y = j * height_block;
 53             int end_y = start_y + height_block;
 54             int num = i + block * j;
 55             //遍历小块,计算直方图
 56             for (int ii = start_x; ii < end_x; ii++)
 57             {
 58                 for (int jj = start_y; jj < end_y; jj++)
 59                 {
 60                     int index = img.at<uchar>(jj, ii);
 61                     //结果直接写入AHE_GO中去
 62                     AHE_GO.at<uchar>(jj, ii) = C2[num][index] * 255;
 63                 }
 64             }
 65         }
 66     }
 67     return AHE_GO;
 68 }
 69 
 70 Mat ImageEqaualize(Mat img)
 71 {
 72     int width = img.cols;
 73     int height = img.rows;
 74     Mat HT_GO = img.clone();
 75     int tmp[256] = { 0 };
 76     float C[256] = { 0.0 };
 77     int total = width * height;
 78     for (int i = 0; i < img.rows; i++)
 79     {
 80         for (int j = 0; j < img.cols; j++)
 81         {
 82             int index = img.at<uchar>(i, j);
 83             tmp[index] ++;
 84         }
 85     }
 86     //计算累积函数  
 87     for (int i = 0; i < 256; i++) {
 88         if (i == 0)
 89             C[i] = 1.0f * tmp[i] / total;
 90         else
 91             C[i] = C[i - 1] + 1.0f * tmp[i] / total;
 92     }
 93     //这里的累积函数分配的方法非常直观高效
 94     for (int i = 0; i < img.rows; i++) {
 95         for (int j = 0; j < img.cols; j++) {
 96             int index = img.at<uchar>(i, j);
 97             HT_GO.at<uchar>(i, j) = C[index] * 255;
 98         }
 99     }
100     return HT_GO;
101 }
102 
103 Mat ImageClHe(Mat img, int block)
104 {
105     int width = img.cols/ block;
106     int height = img.rows/ block;
107     Mat CLHE_GO = img.clone();
108     int tmp[256] = { 0 };
109     float C[256] = { 0.0 };
110     int total = width * height;
111     for (int i = 0; i < img.rows; i++)
112     {
113         for (int j = 0; j < img.cols; j++)
114         {
115             int index = img.at<uchar>(i, j);
116             tmp[index] ++;
117         }
118     }
119     /////////////////////////限制对比度计算部分,注意这个地方average的计算不一定科学
120     int average = width * height / 255 /64;
121     int LIMIT = 4 * average;
122     int steal = 0;
123     for (int k = 0; k < 256; k++)
124     {
125         if (tmp[k] > LIMIT) {
126             steal += tmp[k] - LIMIT;
127             tmp[k] = LIMIT;
128         }
129     }
130     int bonus = steal / 256;
131     //hand out the steals averagely  
132     for (int k = 0; k < 256; k++)
133     {
134         tmp[k] += bonus;
135     }
136     ///////////////////////////////////////////
137     //计算累积函数  
138     for (int i = 0; i < 256; i++) {
139         if (i == 0)
140             C[i] = 1.0f * tmp[i] / total;
141         else
142             C[i] = C[i - 1] + 1.0f * tmp[i] / total;
143     }
144     //这里的累积函数分配的方法非常直观高效
145     for (int i = 0; i < img.rows; i++) {
146         for (int j = 0; j < img.cols; j++) {
147             int index = img.at<uchar>(i, j);
148             CLHE_GO.at<uchar>(i, j) = C[index] * 255;
149         }
150     }
151     return CLHE_GO;
152 }
153 
154 Mat ImageClHeNoInter(Mat img, int block)
155 {
156     Mat CLAHE_GO = img.clone();
157 
158     int width = img.cols;
159     int height = img.rows;
160     int width_block = width / block; //每个小格子的长和宽
161     int height_block = height / block;
162     //存储各个直方图  
163     int tmp2[8 * 8][256] = { 0 };
164     float C2[8 * 8][256] = { 0.0 };
165     //分块
166     int total = width_block * height_block;
167     for (int i = 0; i < block; i++)
168     {
169         for (int j = 0; j < block; j++)
170         {
171             int start_x = i * width_block;
172             int end_x = start_x + width_block;
173             int start_y = j * height_block;
174             int end_y = start_y + height_block;
175             int num = i + block * j;
176             //遍历小块,计算直方图
177             for (int ii = start_x; ii < end_x; ii++)
178             {
179                 for (int jj = start_y; jj < end_y; jj++)
180                 {
181                     int index = img.at<uchar>(jj, ii);
182                     tmp2[num][index]++;
183                 }
184             }
185             //裁剪和增加操作,也就是clahe中的cl部分
186             //这里的参数 对应《Gem》上面 fCliplimit  = 4  , uiNrBins  = 255
187             int average = width_block * height_block / 255;
188             int LIMIT = 4 * average;
189             int steal = 0;
190             for (int k = 0; k < 256; k++)
191             {
192                 if (tmp2[num][k] > LIMIT) {
193                     steal += tmp2[num][k] - LIMIT;
194                     tmp2[num][k] = LIMIT;
195                 }
196             }
197             int bonus = steal / 256;
198             //hand out the steals averagely  
199             for (int k = 0; k < 256; k++)
200             {
201                 tmp2[num][k] += bonus;
202             }
203             //计算累积分布直方图  
204             for (int k = 0; k < 256; k++)
205             {
206                 if (k == 0)
207                     C2[num][k] = 1.0f * tmp2[num][k] / total;
208                 else
209                     C2[num][k] = C2[num][k - 1] + 1.0f * tmp2[num][k] / total;
210             }
211         }
212     }
213     //计算变换后的像素值  
214     //将统计结果写入
215     for (int i = 0; i < block; i++)
216     {
217         for (int j = 0; j < block; j++)
218         {
219             int start_x = i * width_block;
220             int end_x = start_x + width_block;
221             int start_y = j * height_block;
222             int end_y = start_y + height_block;
223             int num = i + block * j;
224             //遍历小块,计算直方图
225             for (int ii = start_x; ii < end_x; ii++)
226             {
227                 for (int jj = start_y; jj < end_y; jj++)
228                 {
229                     int index = img.at<uchar>(jj, ii);
230                     //结果直接写入AHE_GO中去
231                     CLAHE_GO.at<uchar>(jj, ii) = C2[num][index] * 255;
232                 }
233             }
234         }
235 
236     }
237     return CLAHE_GO;
238 }
239 
240 Mat ImageClahe(Mat img, int block)
241 {
242     Mat CLAHE_GO = img.clone();
243     //int block = _step;//pblock
244     int width = img.cols;
245     int height = img.rows;
246     int width_block = width / block; //每个小格子的长和宽
247     int height_block = height / block;
248     //存储各个直方图 
249     int tmp2[8 * 8][256] = { 0 };
250     float C2[8 * 8][256] = { 0.0 };
251     //分块
252     int total = width_block * height_block;
253     for (int i = 0; i < block; i++)
254     {
255         for (int j = 0; j < block; j++)
256         {
257             int start_x = i * width_block;
258             int end_x = start_x + width_block;
259             int start_y = j * height_block;
260             int end_y = start_y + height_block;
261             int num = i + block * j;
262             //遍历小块,计算直方图
263             for (int ii = start_x; ii < end_x; ii++)
264             {
265                 for (int jj = start_y; jj < end_y; jj++)
266                 {
267                     int index = img.at<uchar>(jj, ii);
268                     tmp2[num][index]++;
269                 }
270             }
271             //裁剪和增加操作,也就是clahe中的cl部分
272             //这里的参数 对应《Gem》上面 fCliplimit = 4 , uiNrBins = 255
273             int average = width_block * height_block / 255;
274             //关于参数如何选择,需要进行讨论。不同的结果进行讨论
275             //关于全局的时候,这里的这个cl如何算,需要进行讨论 
276             int LIMIT = 40 * average;
277             int steal = 0;
278             for (int k = 0; k < 256; k++)
279             {
280                 if (tmp2[num][k] > LIMIT) {
281                     steal += tmp2[num][k] - LIMIT;
282                     tmp2[num][k] = LIMIT;
283                 }
284             }
285             int bonus = steal / 256;
286             //hand out the steals averagely 
287             for (int k = 0; k < 256; k++)
288             {
289                 tmp2[num][k] += bonus;
290             }
291             //计算累积分布直方图 
292             for (int k = 0; k < 256; k++)
293             {
294                 if (k == 0)
295                     C2[num][k] = 1.0f * tmp2[num][k] / total;
296                 else
297                     C2[num][k] = C2[num][k - 1] + 1.0f * tmp2[num][k] / total;
298             }
299         }
300     }
301     //计算变换后的像素值 
302     //根据像素点的位置,选择不同的计算方法 
303     for (int i = 0; i < width; i++)
304     {
305         for (int j = 0; j < height; j++)
306         {
307             //four coners 
308             if (i <= width_block / 2 && j <= height_block / 2)
309             {
310                 int num = 0;
311                 CLAHE_GO.at<uchar>(j, i) = (int)(C2[num][CLAHE_GO.at<uchar>(j, i)] * 255);
312             }
313             else if (i <= width_block / 2 && j >= ((block - 1)*height_block + height_block / 2)) {
314                 int num = block * (block - 1);
315                 CLAHE_GO.at<uchar>(j, i) = (int)(C2[num][CLAHE_GO.at<uchar>(j, i)] * 255);
316             }
317             else if (i >= ((block - 1)*width_block + width_block / 2) && j <= height_block / 2) {
318                 int num = block - 1;
319                 CLAHE_GO.at<uchar>(j, i) = (int)(C2[num][CLAHE_GO.at<uchar>(j, i)] * 255);
320             }
321             else if (i >= ((block - 1)*width_block + width_block / 2) && j >= ((block - 1)*height_block + height_block / 2)) {
322                 int num = block * block - 1;
323                 CLAHE_GO.at<uchar>(j, i) = (int)(C2[num][CLAHE_GO.at<uchar>(j, i)] * 255);
324             }
325             //four edges except coners 
326             else if (i <= width_block / 2)
327             {
328                 //线性插值 
329                 int num_i = 0;
330                 int num_j = (j - height_block / 2) / height_block;
331                 int num1 = num_j * block + num_i;
332                 int num2 = num1 + block;
333                 float p = (j - (num_j*height_block + height_block / 2)) / (1.0f*height_block);
334                 float q = 1 - p;
335                 CLAHE_GO.at<uchar>(j, i) = (int)((q*C2[num1][CLAHE_GO.at<uchar>(j, i)] + p * C2[num2][CLAHE_GO.at<uchar>(j, i)]) * 255);
336             }
337             else if (i >= ((block - 1)*width_block + width_block / 2)) {
338                 //线性插值 
339                 int num_i = block - 1;
340                 int num_j = (j - height_block / 2) / height_block;
341                 int num1 = num_j * block + num_i;
342                 int num2 = num1 + block;
343                 float p = (j - (num_j*height_block + height_block / 2)) / (1.0f*height_block);
344                 float q = 1 - p;
345                 CLAHE_GO.at<uchar>(j, i) = (int)((q*C2[num1][CLAHE_GO.at<uchar>(j, i)] + p * C2[num2][CLAHE_GO.at<uchar>(j, i)]) * 255);
346             }
347             else if (j <= height_block / 2) {
348                 //线性插值  
349                 int num_i = (i - width_block / 2) / width_block;
350                 int num_j = 0;
351                 int num1 = num_j * block + num_i;
352                 int num2 = num1 + 1;
353                 float p = (i - (num_i*width_block + width_block / 2)) / (1.0f*width_block);
354                 float q = 1 - p;
355                 CLAHE_GO.at<uchar>(j, i) = (int)((q*C2[num1][CLAHE_GO.at<uchar>(j, i)] + p * C2[num2][CLAHE_GO.at<uchar>(j, i)]) * 255);
356             }
357             else if (j >= ((block - 1)*height_block + height_block / 2)) {
358                 //线性插值  
359                 int num_i = (i - width_block / 2) / width_block;
360                 int num_j = block - 1;
361                 int num1 = num_j * block + num_i;
362                 int num2 = num1 + 1;
363                 float p = (i - (num_i*width_block + width_block / 2)) / (1.0f*width_block);
364                 float q = 1 - p;
365                 CLAHE_GO.at<uchar>(j, i) = (int)((q*C2[num1][CLAHE_GO.at<uchar>(j, i)] + p * C2[num2][CLAHE_GO.at<uchar>(j, i)]) * 255);
366             }
367             //双线性插值
368             else {
369                 int num_i = (i - width_block / 2) / width_block;
370                 int num_j = (j - height_block / 2) / height_block;
371                 int num1 = num_j * block + num_i;
372                 int num2 = num1 + 1;
373                 int num3 = num1 + block;
374                 int num4 = num2 + block;
375                 float u = (i - (num_i*width_block + width_block / 2)) / (1.0f*width_block);
376                 float v = (j - (num_j*height_block + height_block / 2)) / (1.0f*height_block);
377                 CLAHE_GO.at<uchar>(j, i) = (int)((u*v*C2[num4][CLAHE_GO.at<uchar>(j, i)] +
378                     (1 - v)*(1 - u)*C2[num1][CLAHE_GO.at<uchar>(j, i)] +
379                     u * (1 - v)*C2[num2][CLAHE_GO.at<uchar>(j, i)] +
380                     v * (1 - u)*C2[num3][CLAHE_GO.at<uchar>(j, i)]) * 255);
381             }
382             //最后这步,类似高斯平滑
383             CLAHE_GO.at<uchar>(j, i) = CLAHE_GO.at<uchar>(j, i) + (CLAHE_GO.at<uchar>(j, i) << 8) + (CLAHE_GO.at<uchar>(j, i) << 16);
384         }
385     }
386     return CLAHE_GO;
387 }

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!