Optimisation de combinaison peut également être utilisé pour résoudre des problèmes de 4 couleurs. Ici, lisons le problème automatiquement à partir de l'image. Le problème vient de Nikori-sama.
Il existe plusieurs zones et les zones adjacentes sont peintes de différentes couleurs.
$ \ mbox {variables} $ td> | $ v_ {ij} \ in \ {0, 1 \} ~ \ forall i, j $ td> | Zone i La couleur est-elle j? (1) td> tr> |
$ \ mbox {sujet à} $ td> | $ \ sum_j {v_ {ij}} = 1 ~ \ forall i $ td> | Choisissez une couleur ( 2) td> tr> |
td> | Les zones adjacentes doivent être de couleurs différentes (3) td> tr> |
Chargez le fichier image.
python
import networkx as nx
from urllib import request
from PIL import Image, ImageDraw
from collections import Counter
from itertools import product
from random import seed, shuffle
from pulp import *
#Lecture de fichiers image
with request.urlopen('https://dl.dropboxusercontent.com/u/35689878/tmp/4c.png') as fd:
im = Image.open(fd)
python
#Couleur représentative(Couleurs les plus fréquemment utilisées)Extrait
cc = sorted([(v, k) for k, v in Counter(im.getdata()).items()])[-1][1]
# RGB=(0,1,?)Élimine la couleur de
for y, x in product(range(im.height), range(im.width)):
R, G, B = im.getpixel((x, y))[:3]
if (R, G) == (0, 1):
im.putpixel(0, 0, B)
#Zone de couleur représentative RVB=(0,1,numéro de série)Remplir avec
n = 0
for y, x in product(range(im.height), range(im.width)):
if im.getpixel((x, y)) != cc:
continue
ImageDraw.floodfill(im, (x, y), (0, 1, n))
n += 1
#Élargissez un peu la frontière
seed(1)
dd = [(-1, 0), (0, -1), (0, 1), (1, 0)]
for h in range(1):
l = list(product(range(1, im.height-1), range(1, im.width-1)))
shuffle(l)
for y, x in l:
c = im.getpixel((x, y))
if c[:2] == (0, 1):
for i, j in dd:
if im.getpixel((x+i, y+j))[:2] != (0, 1):
im.putpixel((x+i, y+j), c)
Créez un graphique avec des zones sous forme de points et des pixels entre les zones adjacentes sous forme d'arêtes.
python
#Montrer graphiquement s'ils sont côte à côte
g = nx.Graph()
for y, x in product(range(im.height-1), range(im.width-1)):
c1 = im.getpixel((x, y))
if c1[:2] != (0, 1):
continue
c2 = im.getpixel((x+1, y))
c3 = im.getpixel((x, y+1))
if c2[:2] == (0, 1) and c1[2] != c2[2]:
g.add_edge(c1[2], c2[2])
if c3[:2] == (0, 1) and c1[2] != c3[2]:
g.add_edge(c1[2], c3[2])
Formulez et résolvez.
python
#Résolvez le problème des 4 couleurs
r4 = range(4)
m = LpProblem() #Modèle mathématique
#Faire ou non la zone i couleur j(1)
v = [[LpVariable('v%d_%d'%(i, j), cat=LpBinary) for j in r4] for i in g.nodes()]
for i in g.nodes():
m += lpSum(v[i]) == 1 # (2)
for i, j in g.edges():
for k in r4:
m += v[i][k] + v[j][k] <= 1 # (3)
m.solve()
co = [(97, 132, 219), (228, 128, 109), (255, 241, 164), (121, 201, 164)] #4 couleurs
rr = [int(value(lpDot(r4, i))) for i in v] #résultat
for y, x in product(range(im.height-1), range(im.width-1)):
c = im.getpixel((x, y))
if c[:2] == (0, 1): #S'il s'agit d'une zone, peignez avec le résultat
ImageDraw.floodfill(im, (x, y), co[rr[c[2]]])
im.save('result.png')
Quand je l'ai essayé, ça allait.
c'est tout
Recommended Posts