Advertisement
999ms

K-means filter

May 9th, 2020
1,722
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.41 KB | None | 0 0
  1. from PIL import Image, ImageFilter
  2. from collections import deque
  3. from time import time
  4. from random import randrange as rnd
  5.  
  6. white = (255, 255, 255)
  7. black = (0, 0, 0)
  8. def GetPathToImage(index):
  9.     return 'C:\\Users\\User\\Desktop\\university\\educational_and_research_work\\Filters\\for_Andrew\\  (%d).png' % index
  10.  
  11. def GetKMeanColors(listOfPixels, k):    
  12.     def GetRandColor():
  13.         return (rnd(256), rnd(256), rnd(256))
  14.    
  15.     def GetColorDist(a, b):
  16.         return sum([(a[i] - b[i]) ** 2 for i in range(3)])
  17.  
  18.     arr = [GetRandColor() for i in range(k)]
  19.  
  20.     def GetClass(color):
  21.         dist = 10 ** 10 #inf
  22.         index = -1
  23.         for i in range(k):
  24.             currentDist = GetColorDist(color, arr[i])
  25.             if currentDist < dist:
  26.                 dist = currentDist
  27.                 index = i
  28.         return index
  29.    
  30.     n = len(listOfPixels)
  31.    
  32.     def GetTotalError():
  33.         result = 0
  34.         for i in range(n):
  35.             result += GetColorDist(arr[currentClass[i]], listOfPixels[i][0]) * listOfPixels[i][1]
  36.         return result
  37.    
  38.     currentClass = [0 for i in range(n)]
  39.    
  40.     def GetDirections():
  41.         result = [[0, 0, 0] for i in range(k)]
  42.         cnt = [0 for i in range(k)]
  43.         for i in range(n):
  44.             r, g, b = listOfPixels[i][0]
  45.             thisCount = listOfPixels[i][1]
  46.             thisClass = currentClass[i]
  47.             result[thisClass][0] += r * thisCount
  48.             result[thisClass][1] += g * thisCount
  49.             result[thisClass][2] += b * thisCount
  50.             cnt[thisClass] += thisCount
  51.        
  52.         for i in range(k):
  53.             if cnt[i] != 0:
  54.                 for j in range(3):
  55.                     result[i][j] //= cnt[i]
  56.         return result
  57.        
  58.     ITR = 50
  59.     for itr in range(ITR):
  60.         currentClass = [GetClass(listOfPixels[i][0]) for i in range(n)]
  61.         dirs = GetDirections()
  62.         for i in range(k):
  63.             r, g, b = arr[i]
  64.             mr, mg, mb = dirs[i]
  65.             arr[i] = ((r + mr) // 2, (g + mg) // 2, (b + mb) // 2)
  66.        
  67.     colorToColor = {}
  68.     for i in range(n):
  69.         colorToColor[listOfPixels[i][0]] = arr[currentClass[i]]
  70.        
  71.     return arr, GetTotalError(), colorToColor
  72.  
  73. def Filter(number):
  74.     name = GetPathToImage(number)
  75.     try:  
  76.         img = Image.open(name).convert('RGB')
  77.     except FileNotFoundError:  
  78.         return (0, 0, 0, 0)
  79.     pixel_map = img.load()
  80.     w, h = img.size
  81.    
  82.     countMapOfColors = {}
  83.     for i in range(w):
  84.         for j in range(h):
  85.             cur = pixel_map[i, j]
  86.             if cur not in countMapOfColors:
  87.                 countMapOfColors[cur] = 0
  88.             countMapOfColors[cur] += 1
  89.    
  90.    
  91.     listOfPixels = []
  92.     for color in countMapOfColors:
  93.         listOfPixels.append((color, countMapOfColors[color]))
  94.    
  95.     k = 5
  96.     currentColors, currentError, currentMapOfColors = GetKMeanColors(listOfPixels, k)        
  97.     for i in range(w):
  98.         for j in range(h):
  99.             pixel_map[i, j] = currentMapOfColors[pixel_map[i, j]]
  100.    
  101.     countMapOfColors = {}
  102.     for i in range(w):
  103.         for j in range(h):
  104.             cur = pixel_map[i, j]
  105.             if cur not in countMapOfColors:
  106.                 countMapOfColors[cur] = 0
  107.             countMapOfColors[cur] += 1
  108.    
  109.     precents = 10 # если больше precents процентов на картинке данного цвета, то будем считать, что это фон
  110.     totalSize = w * h
  111.     backgroundColors = set()
  112.    
  113.     backgroundColors.add(white) # чтобы сразу убрать белые точки
  114.    
  115.    
  116.     for color in countMapOfColors:
  117.         if countMapOfColors[color] / totalSize * 100 >= precents:
  118.             backgroundColors.add(color)
  119.    
  120.     for x in range(w):
  121.         for y in range(h):
  122.             if pixel_map[x, y] in backgroundColors:
  123.                 pixel_map[x, y] = white
  124.                
  125.     steps = [(dx, dy) for dy in range(-1, 2) for dx in range(-1, 2)]
  126.     def BlurImage():
  127.         arr = [[0 for y in range(h)] for x in range(w)]
  128.         result = [[0 for y in range(h)] for x in range(w)]
  129.         matrix = [
  130.             [-1, -1, -1],
  131.             [-1, 9, -1],
  132.             [-1, -1, -1]]
  133.        
  134.         def Get(i, j):
  135.             ans = [0, 0, 0]
  136.             for (dx, dy) in steps:
  137.                 x = min(w - 1, max(i + dx, 0))
  138.                 y = min(h - 1, max(j + dy, 0))
  139.                 for ind in range(3):
  140.                     ans[ind] += pixel_map[x, y][ind] * matrix[dx + 1][dy + 1]
  141.  
  142.             return (ans[0], ans[1], ans[2])
  143.                    
  144.         for x in range(w):
  145.             for y in range(h):
  146.                 arr[x][y] = Get(x, y)
  147.        
  148.         for x in range(w):
  149.             for y in range(h):
  150.                 pixel_map[x, y] = arr[x][y]
  151.                
  152.     first = [[pixel_map[x, y] for y in range(h)] for x in range(w)]
  153.     BlurImage()
  154.     second = [[pixel_map[x, y] for y in range(h)] for x in range(w)]
  155.     print('done')
  156.     return first, second
  157.  
  158. arr = []
  159. for number in range(1, 10):
  160.     arr.append(Filter(number))
  161.    
  162. w = len(arr[0][0])
  163. h = len(arr[0][0][0])
  164.  
  165.  
  166. img = Image.new('RGB', (w * 2, h * len(arr)))
  167. mp = img.load()
  168.  
  169. for i in range(len(arr)):
  170.     for j in range(2):
  171.         for x in range(w):
  172.             for y in range(h):
  173.                 mp[x + j * w, i * h + y] = arr[i][j][x][y]
  174.  
  175. img.show()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement