├── .gitattributes ├── .ipynb_checkpoints └── Image_Processing-checkpoint.ipynb ├── Image_Processing.ipynb ├── VS └── Image_Processing │ ├── 1.png │ ├── Image_Processing.py │ ├── Image_Processing.pyproj │ ├── Image_Processing.sln │ ├── for_gray_world.png │ └── for_histogram_equalization.jpg ├── for_filter.png ├── for_gray_world.png ├── for_histogram_equalization_1.jpg └── for_histogram_equalization_2.jpg /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /VS/Image_Processing/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Houzich/Image-Processing/73c56212c66f1c81dcb5f118ed0e62d674264a80/VS/Image_Processing/1.png -------------------------------------------------------------------------------- /VS/Image_Processing/Image_Processing.py: -------------------------------------------------------------------------------- 1 | 2 | # coding: utf-8 3 | 4 | # In[1]: 5 | 6 | 7 | from PIL import Image 8 | import matplotlib.pyplot as plt 9 | import matplotlib.pylab as pylab 10 | import numpy as np 11 | 12 | #import skimage 13 | #from skimage import exposure 14 | #from skimage import io, color 15 | #from skimage import filters 16 | 17 | 18 | # In[2]: 19 | 20 | 21 | #get_ipython().run_line_magic('matplotlib', 'inline') 22 | #pylab.rcParams['figure.figsize'] = (20.0, 7.0) 23 | 24 | 25 | # # общие функции 26 | 27 | # In[3]: 28 | from PIL import ImageFilter 29 | ImageRGBArr = np.array( 30 | [ 31 | [[ 1 , 1 , 1 ], [ 1 , 1 , 1 ], [ 1 , 1 , 1 ]], 32 | [[ 1 , 1 , 1 ], [ 1 , 1 , 1 ], [ 1 , 1 , 1 ]], 33 | [[ 1 , 1 , 1 ], [ 1 , 1 , 1 ], [ 1 , 1 , 1 ]] 34 | ] 35 | ).astype(np.uint8) 36 | 37 | img_test = Image.fromarray(ImageRGBArr) 38 | im1 = img_test.filter(ImageFilter.MedianFilter) 39 | print(im1) 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | #import warnings 50 | 51 | ##переводит массив изображения из диапазона 0-255 в диапозон 0.0-1.0 52 | #def img_as_float(img): 53 | # warnings.filterwarnings("ignore") 54 | # result = skimage.img_as_float(img) 55 | # warnings.filterwarnings("default") 56 | # return result 57 | 58 | ##переводит массив изображения из диапазона 0.0-1.0 в диапозон 0-255 59 | #def img_as_ubyte(img): 60 | # warnings.filterwarnings("ignore") 61 | # result = skimage.img_as_ubyte(img) 62 | # warnings.filterwarnings("default") 63 | # return result 64 | 65 | ##возвращает карту разностей изображений 66 | #def difference_map(img1,img2): 67 | # result = np.abs(img1.astype(np.int) - img2.astype(np.int)).astype(np.uint8) 68 | # result = img_as_ubyte(color.rgb2gray(result)) 69 | # return result 70 | 71 | #def load_image(name): 72 | # try: 73 | # img = Image.open(name) 74 | # rgb = np.array(img.convert('RGB')) #загружаем изображение как RGB 75 | # gray = np.array(img.convert('L')) #загружаем изображение как Grayscale 76 | # print ('Image matrix size: ', rgb.shape) 77 | # except: 78 | # print("\nОшибка при открытии файла. Проверте имя или наличие файла в каталоге с проектом [EXIT]\n") 79 | # return rgb,gray 80 | 81 | 82 | ## # 2.1 83 | 84 | ## # Попробуем линейное растяжение яркости 85 | 86 | ## In[4]: 87 | 88 | 89 | #ImageRGBArr,ImageGrayArr = load_image("for_histogram_equalization_1.jpg") 90 | 91 | ##возвращает гистограмму в виде одномерных массивов x,y 92 | ##img - массив RGB 93 | #def histogram_from_rgb(img): 94 | # #цветовой режим Grayscale содержит только информацию о яркости изображения. 95 | # #следовательно для построении гистограммы предварительно нужно перевести изображение RGB в режим Grayscale 96 | # #создаем массив в соответствующих номеру ячейках которого хранится колличество пикселей значением равных номеру ячейки 97 | # #создаем одномерный массив от 0 до 255. он нужен для построения на гистограмме оси x 98 | # x = np.array(range(256)) 99 | # t = img_as_ubyte(color.rgb2gray(img)) 100 | # #подсчитываем сколько в массиве повторений каждого числа 101 | # y = np.bincount(t.ravel(),minlength=256) 102 | # return x,y 103 | 104 | ## Гистограмма – это график распределения яркостей на изображении. На горизонтальной оси - шкала яркостей 105 | ## тонов от белого до черного, на вертикальной оси - число пикселей заданной яркости 106 | ##выводим изображение а рядом гистограмму 107 | #def display_image_and_histogram(img, title): 108 | # x,y = histogram_from_rgb(img) 109 | # plt.subplot(121) 110 | # plt.imshow(img), plt.title(title) 111 | # ax = plt.subplot(122) 112 | # ax.hist(x, bins=np.arange(10, 256), weights=y) 113 | # ax.set_xlabel('яркость пикселей') 114 | # ax.set_ylabel('количество пикселей') 115 | # plt.show() 116 | 117 | 118 | 119 | #img_max = np.max(ImageRGBArr) 120 | #img_min = np.min(ImageRGBArr) 121 | #print ('максимум изображения: ',img_max) 122 | #print ('минимум изображения: ',img_min) 123 | #img_rescale = exposure.rescale_intensity(ImageRGBArr, in_range = (img_min,img_max)) 124 | 125 | #display_image_and_histogram(ImageRGBArr, 'исходное изображение') 126 | #display_image_and_histogram(img_rescale, 'обработанное линейным растяжением') 127 | 128 | 129 | 130 | 131 | ## # 5.0 132 | 133 | ## # Фильтр unsharp_mask взят из (source code) skimage 134 | 135 | ## In[21]: 136 | 137 | 138 | ## Фильтр Unsharp Mask (Контурная резкость) усиливает контраст только на участках с резким перепадом яркости цвета. 139 | ## Изображение визуально кажется более резким за счет ореолов в переходных зонах.Фильтр позволяет достаточно 140 | ## точно контролировать ореол.Толщина ореола должна быть такой, чтобы зритель ее не заметил. 141 | 142 | ## Эффект (Amount) — определяет, насколько сильно затемняются или осветляются участки изображения, находящиеся на границах 143 | ## контура. Выражается в процентах. Так, значение 100 процентов означает, что разница в тоне на границе более светлого и 144 | ## более тёмного участка усилится в два раза. На размер возникающего светлого или тёмного ореола данный параметр не влияет. 145 | 146 | ## Радиус (Radius) — влияет на степень размытия копии изображения. Этот параметр будет влиять на ширину зоны, в которой будет 147 | ## проявляться изменение тона. Меньший радиус используется для подчёркивания мелких деталей, так как большее его значение 148 | ## может приводить к их повреждению. 149 | 150 | ## Порог (Threshold) — определяет минимальную разницу тона, при которой осуществляется нерезкое маскирование. 151 | ## При шумном или зернистом оригинале его выставляют на более высокое значение, чтобы предотвратить подчёркивание этих 152 | ## нежелательных деталей. 153 | 154 | ##from __future__ import division 155 | ##import numpy as np 156 | #from scipy.ndimage.filters import gaussian_filter 157 | #from skimage import img_as_float 158 | 159 | 160 | #def _unsharp_mask_single_channel(image, radius, amount, vrange): 161 | # """Single channel implementation of the unsharp masking filter.""" 162 | 163 | # blurred = gaussian_filter(image, 164 | # sigma=radius, 165 | # mode='reflect') 166 | 167 | # result = image + (image - blurred) * amount 168 | # if vrange is not None: 169 | ## print("lalala") 170 | # return np.clip(result, vrange[0], vrange[1], out=result) 171 | # return result 172 | 173 | 174 | #def unsharp_mask(image, radius=1.0, amount=1.0, multichannel=False, 175 | # preserve_range=False): 176 | # vrange = None # Range for valid values; used for clipping. 177 | # if preserve_range: 178 | ## print("lalala") 179 | # fimg = image.astype(np.float) 180 | # else: 181 | # print("lalala") 182 | # fimg = img_as_float(image) 183 | # negative = np.any(fimg < 0) 184 | # if negative: 185 | # print("-1., 1.") 186 | # vrange = [-1., 1.] 187 | # else: 188 | # print("-1., 1.") 189 | # vrange = [0., 1.] 190 | 191 | # if multichannel: 192 | # result = np.empty_like(fimg, dtype=np.float) 193 | # for channel in range(image.shape[-1]): 194 | # result[..., channel] = _unsharp_mask_single_channel( 195 | # fimg[..., channel], radius, amount, vrange) 196 | # return result 197 | # else: 198 | # return _unsharp_mask_single_channel(fimg, radius, amount, vrange) 199 | 200 | 201 | ## In[22]: 202 | 203 | 204 | #pylab.rcParams.update({'font.size': 20}) 205 | ## функция повышения резкости с помощью гауссова фильтра. sigma - отклонение ядра фильтра, 206 | ## влияет на уровень размытия фильтром "gaussian" 207 | ## radius и amount - влияет на повышения резкости фильтром unsharp_mask (см.выше) 208 | #def gaussian_sharpened(image, sigma = 1, radius = 1, amount=10): 209 | # #Выводим исходное изображение---------------- 210 | # plt.figure(figsize=(30, 40)) 211 | # plt.subplot(131) 212 | # plt.imshow(image),plt.title('исходное изображение'),plt.axis('off') 213 | # #-------------------------------------------- 214 | # #размываем фильтром "gaussian". 215 | # #фильтр возвращает массив float диапозоном значений от 0. до 1. 216 | # img_blurred = img_as_ubyte(filters.gaussian(image, sigma, multichannel=True)) 217 | 218 | 219 | # #Выводим размытое изображение---------------- 220 | # plt.subplot(132) 221 | # plt.imshow(img_blurred),plt.title('фильтр "гауссов" sigma = ' + str(sigma)),plt.axis('off') 222 | # #-------------------------------------------- 223 | 224 | # #фильтр принимает массив только в диапозоне 0-1. поэтому переводим в диапазон 0-1.0 и результат обратно 225 | # img_sharpened = img_as_ubyte(unsharp_mask(img_as_float(img_blurred), radius = radius, amount = amount, multichannel = True)) 226 | 227 | # #Выводим финально изображение---------------- 228 | # plt.subplot(133) 229 | # plt.imshow(img_sharpened),plt.title('фильтр "unsharp mask" radius = ' + str(radius) + ' amount = ' + str(amount)),plt.axis('off') 230 | # plt.show() 231 | # #-------------------------------------------- 232 | # return img_sharpened 233 | 234 | ## img_sharpened_1 = gaussian_sharpened(ImageRGBArr, sigma = 1, radius = 1, amount=10) 235 | ## img_sharpened_2 = gaussian_sharpened(ImageRGBArr, sigma = 1, radius = 4, amount=4) 236 | ## img_sharpened_3 = gaussian_sharpened(ImageRGBArr, sigma = 2, radius = 1, amount=20) 237 | 238 | ##применяем стандартный фильтр для повышения резкости 239 | #img_scharrp = convolve(ImageRGBArr, KernelsList.get('повышение резкости'),'replicate') 240 | 241 | #img_unsharp_mask = img_as_ubyte(unsharp_mask(ImageRGBArr, radius = 2, amount = 1, multichannel = True)) 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | ## # Но линейное растяжение работает не всегда! 272 | 273 | ## In[5]: 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | #ImageRGBArr,ImageGrayArr = load_image("for_histogram_equalization_2.jpg") 308 | 309 | #img_max = np.max(ImageRGBArr) 310 | #img_min = np.min(ImageRGBArr) 311 | #print ('максимум для линейного растяжения: ',img_max) 312 | #print ('минимум для линейного растяжения: ',img_min) 313 | #img_rescale = exposure.rescale_intensity(ImageRGBArr, in_range = (img_min,img_max)) 314 | 315 | #display_image_and_histogram(ImageRGBArr, 'исходное изображение') 316 | #display_image_and_histogram(img_rescale, 'линейное растяжением') 317 | 318 | 319 | ## # Робастное линейное растяжение яркости 320 | 321 | ## In[6]: 322 | 323 | 324 | ## возьмем порог 8% 325 | ## Процентиль – это процент пикселей из массива, значением столько же или меньше чем конкретный пиксель. 326 | ## если мы возьмем порог 10% то функция percentile вернет пиксель из массива значенИе которого будет выше 10% 327 | ## от количества всех пикселей. к примеру, если у нас есть массив от 1 до 100 то np.percentile(array,10) вернет 328 | ## значение 10, что будет означать, что 10% значений массива меньше или равны 10. 329 | #img_min, img_max = np.percentile(ImageRGBArr, (0 + 8, 100 - 8)).astype(np.uint8) 330 | ## img_min - 8% пикселей в массиве меньше или равны pimg_min8 331 | ## img_max - 8% пикселей в массиве больше или равны img_max 332 | 333 | #print ('максимум для линейного растяжения: ',img_max) 334 | #print ('минимум для линейного растяжения: ',img_min) 335 | #img_rescale = exposure.rescale_intensity(ImageRGBArr, in_range = (img_min,img_max)) 336 | 337 | #display_image_and_histogram(ImageRGBArr, 'исходное изображение') 338 | #display_image_and_histogram(img_rescale, 'робастное линейное растяжение') 339 | 340 | 341 | ## # 2.2 342 | 343 | ## In[7]: 344 | 345 | 346 | ##для лучшего восприятия результатов операциы применим другое исходное изображение 347 | #ImageRGBArr,ImageGrayArr = load_image("for_gray_world.png") 348 | 349 | ## применим операцию «линейное растяжение по каналам». 350 | #rescale_arr = np.array(ImageRGBArr) 351 | ##мы применяем отдельно линейное растяжение для каждого канала. это приведет к изменению цветов, в отличии от 352 | ##"линейное растяжение яркости" где изменения цветов не значительное, меняются только яркости 353 | #for chann in range(3): 354 | # rescale_arr[:, :, chann] = exposure.rescale_intensity(ImageRGBArr[:, :, chann], in_range = (120,250)) 355 | 356 | 357 | ## Алгоритм модели "серый мир" 358 | ## 1. Сконвертируем изображение в вещественные числа. 359 | ## 2. Рассчитываем коэффициенты для каждого канала. 360 | ## 3. Делим каналы изображения на коэффициенты. 361 | ## 4. Обрезаем значения пикселей, чтобы они не выходили из допустимого диапазона [0; 255]. 362 | #def grey_world(rgb): 363 | # #конвентируем тип данных во float 364 | # rgb_f = rgb.astype(np.float32) 365 | # #подсчитаем среднии коэффициенты для каждого канала 366 | # avg_r = np.average(rgb_f[:, :, 0]) 367 | # avg_g = np.average(rgb_f[:, :, 1]) 368 | # avg_b = np.average(rgb_f[:, :, 2]) 369 | # x = (avg_r + avg_g + avg_b)/3 #среднее для всех каналов 370 | # avg = np.array([avg_r,avg_g,avg_b])/x #среднее каждого канала делиться на среднее всех каналов 371 | # #делим все каналы на коэффициенты 372 | # for chann in range(3): 373 | # if avg[chann]!=0: rgb_f[:, :, chann] = np.round(rgb_f[:, :, chann]/avg[chann]) 374 | # else: rgb_f[:, :, chann] = 0 375 | # #обрезаем значения пикселей, чтобы они не выходили из допустимого диапазона [0; 255] 376 | # rgb_f = np.clip(rgb_f,0,255) 377 | # out = np.array(rgb_f.astype(np.uint8)) #переводим в uint8 378 | # return out 379 | 380 | #grey_world_arr = grey_world(ImageRGBArr) 381 | #plt.subplot(131) 382 | #plt.imshow(ImageRGBArr), plt.title('исходное изображение'),plt.axis('off') 383 | #plt.subplot(132) 384 | #plt.imshow(grey_world_arr), plt.title('"серый мир"'),plt.axis('off') 385 | #plt.subplot(133) 386 | #plt.imshow(rescale_arr), plt.title('"линейное растяжение по каналам"'),plt.axis('off') 387 | #plt.show() 388 | 389 | 390 | ## # 2.3 391 | 392 | ## In[8]: 393 | 394 | 395 | #ImageRGBArr,ImageGrayArr = load_image("for_filter.png") 396 | #from skimage.morphology import disk 397 | ##функция добавления шума "соль и перец" 398 | #def salt_and_pepper(img, pad = 100): 399 | # #создаем массив случайных целых чисел от 0 до pad размером исходного изображения 400 | # noise = np.random.randint(pad, size = (img.shape[0], img.shape[1], 1)) 401 | # #в исходном изображении, меняем пиксели согласно минимальному и максимальному значению в массиве шума. 402 | # #там где в массиве шума у нас 0 меняем в массиве изображения на 255, и где pad-1 меняем в изображении на 0 403 | # img = np.where(noise == 0, 255, img) 404 | # img = np.where(noise == pad-1, 0, img) 405 | # return img 406 | 407 | ##зашумляем исходное изображение 408 | #SaltAndPepperArr = salt_and_pepper(ImageRGBArr, pad = 101) 409 | ##Median filter – резких границ не портит, убирает мелкие детали. изображение выглядит менее естественно 410 | #Median3x3Arr = np.zeros_like(ImageRGBArr) 411 | #Median5x5Arr = np.zeros_like(ImageRGBArr) 412 | #for chann in range(3): 413 | # Median3x3Arr[:,:,chann] = filters.median(SaltAndPepperArr[:,:,chann], disk(3)) 414 | # Median5x5Arr[:,:,chann] = filters.median(SaltAndPepperArr[:,:,chann], disk(5)) 415 | 416 | #plt.figure(figsize=(20, 10)) 417 | #plt.subplot(221) 418 | #plt.imshow(ImageRGBArr), plt.title('начальное изображение'),plt.axis('off') 419 | #plt.subplot(222) 420 | #plt.imshow(SaltAndPepperArr), plt.title('шум "соль и перец"'),plt.axis('off') 421 | #plt.subplot(223) 422 | #plt.imshow(Median3x3Arr), plt.title('медианный фильтр 3х3'),plt.axis('off') 423 | #plt.subplot(224) 424 | #plt.imshow(Median5x5Arr), plt.title('медианный фильтр 5х5'),plt.axis('off') 425 | #plt.show() 426 | 427 | ##карта разности между исходным изображением и зашумленным 428 | #MapScrNoiseArr = difference_map(ImageRGBArr, SaltAndPepperArr) 429 | ##карта разности между исходным изображением и скоректированным 430 | #MapScrFilter3x3Arr = difference_map(ImageRGBArr, Median3x3Arr) 431 | #MapScrFilter5x5Arr = difference_map(ImageRGBArr, Median5x5Arr) 432 | 433 | #plt.subplot(131) 434 | #plt.imshow(color.rgb2gray(MapScrNoiseArr), cmap='gray'), plt.title('карта разности - исходное и зашумленное'),plt.axis('off') 435 | #plt.subplot(132) 436 | #plt.imshow(color.rgb2gray(MapScrFilter3x3Arr), cmap='gray'), plt.title('исходное и скоректированным фильтром 3х3'),plt.axis('off') 437 | #plt.subplot(133) 438 | #plt.imshow(color.rgb2gray(MapScrFilter5x5Arr), cmap='gray'), plt.title('исходное и скоректированным фильтром 5х5'),plt.axis('off') 439 | #plt.show() 440 | 441 | 442 | ## # 4.0 443 | 444 | ## # Функции свертки 445 | 446 | ## In[9]: 447 | 448 | 449 | ##Эта функция принимает изображение и ядро и возвращает их свертку 450 | # # Args:image: массив numpy, kernel: массив numpy, mode = replicate (добавленные строки и столбцы 451 | # # заполняются крайними значениями массива) иначе нулями 452 | # # Returns: массив numpy 453 | ##Результат свертки изображения рассчитывается следующим образом: 454 | ##1. Переворачиваем ядро как по горизонтали, так и по вертикали. 455 | ##2. Помещаем первый элемент ядра на каждый пиксель изображения (элемент матрицы изображения). 456 | ##3. Умножаем каждый элемент ядра на соответствующий элемент матрицы изображения (тот, который перекрывается с ним). Суммируем, 457 | ## результаты, делим на коэффициент нормирования, и помещаем значение в том же положении в выходной матрице, что и центр ядра в матрице изображений. 458 | ##4. Для пикселей на границе матрицы изображения некоторые элементы ядра будут выходить за края матрицы изображения, 459 | ## следовательно, не имеют соответствующего элемента из матрицы изображения. 460 | ## Мы дополним матрицу изображения нулевыми элементами или крайними пиксилями 461 | #def convolve_2d(image, kernel, mode): 462 | # kernel = np.flipud(np.fliplr(kernel)) # переворачиваем массив ядра в направлении верх-низ, потом лево-право 463 | # result = np.zeros_like(image).astype(np.int) # создаем массив для результата свертки 464 | # #добавим нулевые строки и столбцы к входному изображжению 465 | # image_padded = np.zeros((image.shape[0] + 2, image.shape[1] + 2)) 466 | # image_padded[1:-1, 1:-1] = image 467 | # #заполняем дополнение крайними пикселями изображения 468 | # if mode == 'replicate': 469 | # image_padded[:,0] = np.copy(image_padded[:,1]) 470 | # image_padded[:,-1] = np.copy(image_padded[:,-2]) 471 | # image_padded[0,:] = np.copy(image_padded[1,:]) 472 | # image_padded[-1,:] = np.copy(image_padded[-2,:]) 473 | 474 | # for x in range(image.shape[1]): #Переберем все пиксели изображения 475 | # for y in range(image.shape[0]): 476 | # # перемножаем соответствующие элементы ядра изображения, суммируем и делим на коэффициент нормирования 477 | # result[y,x]=round((kernel*image_padded[y:y+3,x:x+3]).sum()) 478 | 479 | 480 | # result = np.clip(result, 0, 255) #обрезаем значения выходящие из диапозона 0-255 481 | # return result.astype(np.uint8) 482 | 483 | #def convolve(image, kernel, *mode): 484 | # result = np.zeros_like(image) 485 | # for chann in range(3): 486 | # result[:,:,chann] = convolve_2d(image[:,:,chann], kernel, *mode) 487 | # return result 488 | 489 | 490 | ## # Ядра фильтров 491 | 492 | ## In[10]: 493 | 494 | 495 | ## Ядра 496 | #KernelsList = { 497 | # 'усреднение': 1/9*np.array( [[ 1 , 1 , 1 ], [ 1 , 1 , 1 ], [ 1 , 1 , 1 ]] ), 498 | # 'сдвиг на 1': np.array( [[ 0 , 1 , 0 ], [ 0 , 0 , 0 ], [ 0 , 0 , 0 ]] ), 499 | # 'гауссов': 1/16*np.array( [[ 1 , 2 , 1 ], [ 2 , 4 , 2 ], [ 1 , 2 , 1 ]] ), 500 | # 'повышение резкости': 1/10*np.array( [[ -1 , -2 , -1 ], [ -2 , 22 , -2 ], [ -1 , -2 , -1 ]] ), 501 | # } 502 | 503 | 504 | ## # Применяем фильтры 505 | 506 | ## In[11]: 507 | 508 | 509 | ##обрежем изображение 510 | #img_test = ImageRGBArr[150:250,250:350,:] 511 | #plt.figure(figsize=(10, 20)) 512 | #test_convolve_img = convolve(img_test, KernelsList.get('усреднение'),'replicate') 513 | #plt.subplot(421), plt.imshow(img_test), plt.title('исходное изображение'),plt.axis('off') 514 | #plt.subplot(422), plt.imshow(test_convolve_img), plt.title('фильтр "усреднение"'),plt.axis('off') 515 | 516 | #test_convolve_img = convolve(img_test, KernelsList.get('сдвиг на 1'),'replicate') 517 | #plt.subplot(423), plt.imshow(img_test), plt.title('исходное изображение'),plt.axis('off') 518 | #plt.subplot(424), plt.imshow(test_convolve_img), plt.title('фильтр "сдвиг на 1"'),plt.axis('off') 519 | 520 | #test_convolve_img = convolve(img_test, KernelsList.get('гауссов'),'replicate') 521 | #plt.subplot(425), plt.imshow(img_test), plt.title('исходное изображение'),plt.axis('off') 522 | #plt.subplot(426), plt.imshow(test_convolve_img), plt.title('фильтр "гауссов"'),plt.axis('off') 523 | 524 | #test_convolve_img = convolve(img_test, KernelsList.get('повышение резкости'),'replicate') 525 | #plt.subplot(427), plt.imshow(img_test), plt.title('исходное изображение'),plt.axis('off') 526 | #plt.subplot(428), plt.imshow(test_convolve_img), plt.title('фильтр "повышение резкости"'),plt.axis('off') 527 | #plt.show() 528 | 529 | 530 | ## # Сравним результат работы собственного фильтра "гауссов" со встроенными функциями 531 | 532 | ## In[12]: 533 | 534 | 535 | #img_my_filter = convolve(img_test, KernelsList.get('гауссов'),'replicate') 536 | ##фильтр гаусса возвращает массив float со значениями от 0. до 1. 537 | #img_gaussian_filter1 = img_as_ubyte(filters.gaussian(img_test, sigma=1, multichannel=True)) 538 | #img_gaussian_filter2 = img_as_ubyte(filters.gaussian(img_test, sigma=2, multichannel=True)) 539 | 540 | ##карты разницы между собственным фильтром и встроенными 541 | #MapScrFilterArr1 = difference_map(img_my_filter, img_gaussian_filter1) 542 | #MapScrFilterArr2 = difference_map(img_my_filter, img_gaussian_filter2) 543 | 544 | #plt.figure(figsize=(10, 10)) 545 | #plt.subplot(321), plt.imshow(img_test), plt.title('исходное изображение'),plt.axis('off') 546 | #plt.subplot(322), plt.imshow(img_my_filter), plt.title('собственный фильтр "гауссов"'),plt.axis('off') 547 | #plt.subplot(323), plt.imshow(img_gaussian_filter1), plt.title('встроенный фильтр "гауссов" sigma=1'),plt.axis('off') 548 | #plt.subplot(324), plt.imshow(img_gaussian_filter2), plt.title('встроенный фильтр "гауссов" sigma=2'),plt.axis('off') 549 | #plt.subplot(325), plt.imshow(MapScrFilterArr1, cmap='gray'), plt.title('карта собственного и "гауссов" sigma=1'),plt.axis('off') 550 | #plt.subplot(326), plt.imshow(MapScrFilterArr2, cmap='gray'), plt.title('карта собственного и "гауссов" sigma=2'),plt.axis('off') 551 | #plt.show() 552 | 553 | 554 | ## # 5.0 555 | 556 | ## # Фильтр unsharp_mask взят из (source code) skimage 557 | 558 | ## In[21]: 559 | 560 | 561 | ## Фильтр Unsharp Mask (Контурная резкость) усиливает контраст только на участках с резким перепадом яркости цвета. 562 | ## Изображение визуально кажется более резким за счет ореолов в переходных зонах.Фильтр позволяет достаточно 563 | ## точно контролировать ореол.Толщина ореола должна быть такой, чтобы зритель ее не заметил. 564 | 565 | ## Эффект (Amount) — определяет, насколько сильно затемняются или осветляются участки изображения, находящиеся на границах 566 | ## контура. Выражается в процентах. Так, значение 100 процентов означает, что разница в тоне на границе более светлого и 567 | ## более тёмного участка усилится в два раза. На размер возникающего светлого или тёмного ореола данный параметр не влияет. 568 | 569 | ## Радиус (Radius) — влияет на степень размытия копии изображения. Этот параметр будет влиять на ширину зоны, в которой будет 570 | ## проявляться изменение тона. Меньший радиус используется для подчёркивания мелких деталей, так как большее его значение 571 | ## может приводить к их повреждению. 572 | 573 | ## Порог (Threshold) — определяет минимальную разницу тона, при которой осуществляется нерезкое маскирование. 574 | ## При шумном или зернистом оригинале его выставляют на более высокое значение, чтобы предотвратить подчёркивание этих 575 | ## нежелательных деталей. 576 | 577 | #from __future__ import division 578 | #import numpy as np 579 | #from scipy.ndimage.filters import gaussian_filter 580 | #from skimage import img_as_float 581 | 582 | 583 | #def _unsharp_mask_single_channel(image, radius, amount, vrange): 584 | # """Single channel implementation of the unsharp masking filter.""" 585 | 586 | # blurred = gaussian_filter(image, 587 | # sigma=radius, 588 | # mode='reflect') 589 | 590 | # result = image + (image - blurred) * amount 591 | # if vrange is not None: 592 | ## print("lalala") 593 | # return np.clip(result, vrange[0], vrange[1], out=result) 594 | # return result 595 | 596 | 597 | #def unsharp_mask(image, radius=1.0, amount=1.0, multichannel=False, 598 | # preserve_range=False): 599 | # vrange = None # Range for valid values; used for clipping. 600 | # if preserve_range: 601 | ## print("lalala") 602 | # fimg = image.astype(np.float) 603 | # else: 604 | # print("lalala") 605 | # fimg = img_as_float(image) 606 | # negative = np.any(fimg < 0) 607 | # if negative: 608 | # print("-1., 1.") 609 | # vrange = [-1., 1.] 610 | # else: 611 | # print("-1., 1.") 612 | # vrange = [0., 1.] 613 | 614 | # if multichannel: 615 | # result = np.empty_like(fimg, dtype=np.float) 616 | # for channel in range(image.shape[-1]): 617 | # result[..., channel] = _unsharp_mask_single_channel( 618 | # fimg[..., channel], radius, amount, vrange) 619 | # return result 620 | # else: 621 | # return _unsharp_mask_single_channel(fimg, radius, amount, vrange) 622 | 623 | 624 | ## In[22]: 625 | 626 | 627 | #pylab.rcParams.update({'font.size': 20}) 628 | ## функция повышения резкости с помощью гауссова фильтра. sigma - отклонение ядра фильтра, 629 | ## влияет на уровень размытия фильтром "gaussian" 630 | ## radius и amount - влияет на повышения резкости фильтром unsharp_mask (см.выше) 631 | #def gaussian_sharpened(image, sigma = 1, radius = 1, amount=10): 632 | # #Выводим исходное изображение---------------- 633 | # plt.figure(figsize=(30, 40)) 634 | # plt.subplot(131) 635 | # plt.imshow(image),plt.title('исходное изображение'),plt.axis('off') 636 | # #-------------------------------------------- 637 | # #размываем фильтром "gaussian". 638 | # #фильтр возвращает массив float диапозоном значений от 0. до 1. 639 | # img_blurred = img_as_ubyte(filters.gaussian(image, sigma, multichannel=True)) 640 | 641 | 642 | # #Выводим размытое изображение---------------- 643 | # plt.subplot(132) 644 | # plt.imshow(img_blurred),plt.title('фильтр "гауссов" sigma = ' + str(sigma)),plt.axis('off') 645 | # #-------------------------------------------- 646 | 647 | # #фильтр принимает массив только в диапозоне 0-1. поэтому переводим в диапазон 0-1.0 и результат обратно 648 | # img_sharpened = img_as_ubyte(unsharp_mask(img_as_float(img_blurred), radius = radius, amount = amount, multichannel = True)) 649 | 650 | # #Выводим финально изображение---------------- 651 | # plt.subplot(133) 652 | # plt.imshow(img_sharpened),plt.title('фильтр "unsharp mask" radius = ' + str(radius) + ' amount = ' + str(amount)),plt.axis('off') 653 | # plt.show() 654 | # #-------------------------------------------- 655 | # return img_sharpened 656 | 657 | ## img_sharpened_1 = gaussian_sharpened(ImageRGBArr, sigma = 1, radius = 1, amount=10) 658 | ## img_sharpened_2 = gaussian_sharpened(ImageRGBArr, sigma = 1, radius = 4, amount=4) 659 | ## img_sharpened_3 = gaussian_sharpened(ImageRGBArr, sigma = 2, radius = 1, amount=20) 660 | 661 | ##применяем стандартный фильтр для повышения резкости 662 | #img_scharrp = convolve(ImageRGBArr, KernelsList.get('повышение резкости'),'replicate') 663 | 664 | #img_unsharp_mask = img_as_ubyte(unsharp_mask(ImageRGBArr, radius = 2, amount = 1, multichannel = True)) 665 | 666 | ##Выводим изображения---------------- 667 | #plt.figure(figsize=(30, 40)) 668 | #plt.subplot(131) 669 | #plt.imshow(ImageRGBArr),plt.title('исходное изображение'),plt.axis('off') 670 | #plt.subplot(132) 671 | #plt.imshow(img_scharrp),plt.title('фильтр "повышение резкости"'),plt.axis('off') 672 | #plt.subplot(133) 673 | #plt.imshow(img_unsharp_mask),plt.title('фильтр "unsharp mask"'),plt.axis('off') 674 | #plt.show() 675 | ##-------------------------------------------- 676 | ## карта разности между фильтром "повышение резкости" и "unsharp mask" 677 | #diff_map = difference_map(img_scharrp, img_unsharp_mask) 678 | ##Выводим изображения---------------- 679 | #plt.figure(figsize=(10, 10)) 680 | #plt.imshow(diff_map, cmap='gray'),plt.title('Карта разности'),plt.axis('off') 681 | #plt.show() 682 | ##-------------------------------------------- 683 | 684 | -------------------------------------------------------------------------------- /VS/Image_Processing/Image_Processing.pyproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Debug 4 | 2.0 5 | cc0a99bc-5c56-4ce0-98ab-1124d732886c 6 | . 7 | Image_Processing.py 8 | 9 | 10 | . 11 | . 12 | Image_Processing 13 | Image_Processing 14 | 15 | 16 | true 17 | false 18 | 19 | 20 | true 21 | false 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /VS/Image_Processing/Image_Processing.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2026 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "Image_Processing", "Image_Processing.pyproj", "{CC0A99BC-5C56-4CE0-98AB-1124D732886C}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {CC0A99BC-5C56-4CE0-98AB-1124D732886C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {CC0A99BC-5C56-4CE0-98AB-1124D732886C}.Release|Any CPU.ActiveCfg = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | GlobalSection(ExtensibilityGlobals) = postSolution 21 | SolutionGuid = {753C1DD0-A30A-43D2-8AC0-E04245A649AF} 22 | EndGlobalSection 23 | EndGlobal 24 | -------------------------------------------------------------------------------- /VS/Image_Processing/for_gray_world.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Houzich/Image-Processing/73c56212c66f1c81dcb5f118ed0e62d674264a80/VS/Image_Processing/for_gray_world.png -------------------------------------------------------------------------------- /VS/Image_Processing/for_histogram_equalization.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Houzich/Image-Processing/73c56212c66f1c81dcb5f118ed0e62d674264a80/VS/Image_Processing/for_histogram_equalization.jpg -------------------------------------------------------------------------------- /for_filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Houzich/Image-Processing/73c56212c66f1c81dcb5f118ed0e62d674264a80/for_filter.png -------------------------------------------------------------------------------- /for_gray_world.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Houzich/Image-Processing/73c56212c66f1c81dcb5f118ed0e62d674264a80/for_gray_world.png -------------------------------------------------------------------------------- /for_histogram_equalization_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Houzich/Image-Processing/73c56212c66f1c81dcb5f118ed0e62d674264a80/for_histogram_equalization_1.jpg -------------------------------------------------------------------------------- /for_histogram_equalization_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Houzich/Image-Processing/73c56212c66f1c81dcb5f118ed0e62d674264a80/for_histogram_equalization_2.jpg --------------------------------------------------------------------------------