Écrivez un programme qui prend une image RVB en couleurs vraies I , le nombre maximal de lignes pour dessiner L , et la longueur minimale m et maximale M de chaque ligne. Une image de sortie O qui ressemble le plus possible comme I et est tiré à l' aide de L ou moins de lignes droites, qui ont toutes une longueur euclidienne entre m et M .
Chaque ligne doit être d'une couleur unie, avoir les deux extrémités dans les limites de O et être dessinée en utilisant l' algorithme de ligne de Bresenham (ce que la plupart des bibliothèques graphiques feront déjà pour vous). Les lignes individuelles ne peuvent avoir qu'une épaisseur de 1 pixel.
Toutes les lignes, même celles de longueur 0, doivent occuper au moins un pixel. Les lignes peuvent être tracées les unes sur les autres.
Avant de dessiner des lignes, vous pouvez initialiser l'arrière-plan de O à n'importe quelle couleur unie (qui peut dépendre de I ).
Détails
- O devrait avoir les mêmes dimensions que je .
- L sera toujours un entier non négatif. Il peut être supérieure à la surface de I .
- m et M sont des nombres à virgule flottante non négatifs avec M > = m . La distance entre deux pixels est la distance euclidienne entre leurs centres. Si cette distance est inférieure à m ou supérieure à M , une ligne entre ces pixels n'est pas autorisée.
- Les lignes ne doivent pas être anticrénelées.
- L'opacité et l'alpha ne doivent pas être utilisés.
- Votre programme ne devrait pas prendre plus d'une heure pour s'exécuter sur un ordinateur moderne décent sur des images avec moins d'un million de pixels et L moins de 10 000.
Images d'essai
Vous devez bien sûr nous montrer vos images de sortie les plus précises ou les plus intéressantes (ce qui, je pense, se produira lorsque L est compris entre 5% et 25% du nombre de pixels en I , et m et M sont environ un dixième de la taille diagonale).
Voici quelques images de test (cliquez pour les originaux). Vous pouvez également publier le vôtre.
Images plus simples:
C'est un concours de popularité. La soumission la plus votée gagne.
Remarques
- Il peut être utile de laisser L dériver d'un pourcentage du nombre total de pixels dans I ainsi que d'une valeur absolue. par exemple, ce
>>> imageliner I=img.png L=50% m=10 M=20
serait la même chose que>>> imageliner I=img.png L=32 m=10 M=20
s'ilimg.png
s'agissait d'une image de 8 x 8 pixels. Quelque chose de semblable pourrait être fait pour m et M . Ce n'est pas obligatoire. - Étant donné que les lignes ne peuvent pas sortir des limites, les lignes les plus longues possibles sera la longueur de la diagonale de I . Avoir M plus élevé que cela ne devrait cependant rien casser.
- Naturellement, si m est 0 et L est supérieur ou égal au nombre de pixels dans I , O pourrait être identique à I en ayant une longueur 0 "lignes" à chaque emplacement de pixel. Ce comportement n'est pas requis.
- On peut dire que la reproduction de la forme de I est plus importante que la reproduction de la couleur. Vous voudrez peut-être examiner la détection des contours .
la source
Réponses:
C ++ - des lignes quelque peu aléatoires, puis certaines
D'abord quelques lignes aléatoires
La première étape de l'algorithme génère aléatoirement des lignes, prend pour l'image cible une moyenne des pixels le long de celle-ci, puis calcule si le carré résumé des distances spatiales RVB de tous les pixels serait inférieur si nous peignions la nouvelle ligne (et peignez-le seulement, si c'est le cas). La nouvelle couleur des lignes est choisie comme la moyenne des valeurs RVB par canal, avec une addition aléatoire de -15 / + 15.
Choses que j'ai remarquées et influencé la mise en œuvre:
J'expérimentais avec quelques chiffres, et j'ai choisi
L=0.3*pixel_count(I)
et quittém=10
etM=50
. Il produira des résultats agréables à partir autour0.25
de0.26
pour le nombre de lignes, mais j'ai choisi 0,3 pour avoir plus de place pour plus de détails précis.Pour l'image de la porte dorée en taille réelle, cela a entraîné 235929 lignes à peindre (pour lesquelles il a fallu 13 secondes ici). Notez que toutes les images ici sont affichées en taille réduite et vous devez les ouvrir dans un nouvel onglet / les télécharger pour afficher la pleine résolution.
Effacez l'indigne
L'étape suivante est assez chère (pour les lignes de 235k, cela a pris environ une heure, mais cela devrait être bien dans le délai de "une heure pour 10k lignes sur 1 mégapixel"), mais c'est aussi un peu surprenant. Je passe en revue toutes les lignes précédemment peintes et je supprime celles qui ne rendent pas l'image meilleure. Cela me laisse dans cette course avec seulement 97347 lignes qui produisent l'image suivante:
Vous devrez probablement les télécharger et les comparer dans une visionneuse d'images appropriée pour repérer la plupart des différences.
et recommencer
Maintenant, j'ai beaucoup de lignes que je peux peindre à nouveau pour avoir à nouveau un total de 235929. Pas grand chose à dire, voici donc l'image:
brève analyse
L'ensemble de la procédure semble fonctionner comme un filtre flou sensible au contraste local et à la taille des objets. Mais il est également intéressant de voir où les lignes sont peintes, donc le programme les enregistre également (pour chaque ligne, la couleur des pixels sera rendue plus blanche, à la fin le contraste est maximisé). Voici les correspondants aux trois couleurs ci-dessus.
animations
Et puisque nous aimons tous les animations, voici quelques gifs animés de tout le processus pour la petite image du Golden Gate. Notez qu'il y a un tramage important en raison du format gif (et puisque les créateurs de formats de fichiers d'animation en vraies couleurs et les fabricants de navigateurs sont en guerre pour leurs ego, il n'y a pas de format standard pour les animations en vraies couleurs, sinon j'aurais pu ajouter un .mng ou similaire ).
Un peu plus
Comme demandé, voici quelques résultats des autres images (encore une fois, vous devrez peut-être les ouvrir dans un nouvel onglet pour ne pas les réduire)
Pensées futures
Jouer avec le code peut donner quelques variations intéressantes.
Le code
Ce ne sont que les deux principales fonctions utiles, le code entier ne tient pas ici et peut être trouvé à http://ideone.com/Z2P6Ls
Les
bmp
classesraw
et laraw_line
fonction accèdent respectivement aux pixels et aux lignes dans un objet qui peut être écrit au format bmp (c'était juste un hack qui traînait et je pensais que cela le rendait quelque peu indépendant de toute bibliothèque).Le format du fichier d'entrée est PPM
la source
Java - lignes aléatoires
Une solution très basique qui dessine des lignes aléatoires et calcule pour elles la couleur moyenne de l'image source. La couleur d'arrière-plan est définie sur la couleur moyenne source.
L = 5000, m = 10, M = 50
L = 10000, m = 10, M = 50
MODIFIER
J'ai ajouté un algorithme génétique qui gère une population de lignées. À chaque génération, nous ne conservons que les 50% des meilleures lignes, supprimons les autres et générons au hasard de nouvelles lignes. Les critères de maintien des lignes sont:
À ma grande déception, l'algorithme ne semble pas vraiment améliorer la qualité de l'image :-( seules les lignes deviennent plus parallèles.
Première génération (5000 lignes)
Dixième génération (5000 lignes)
Jouer avec les paramètres
la source
C - lignes droites
Une approche de base en C qui fonctionne sur des fichiers ppm. L'algorithme essaie de placer des lignes verticales avec une longueur de ligne optimale pour remplir tous les pixels. La couleur d'arrière-plan et les couleurs de ligne sont calculées comme une valeur moyenne de l'image d'origine (la médiane de chaque canal de couleur):
L = 5000, m = 10, M = 50
L = 5000, m = 10, M = 50
L = 100000, m = 10, M = 50
la source
Python 3 basé sur "des lignes quelque peu aléatoires, puis certaines", plus la détection des bords sobel.
le code peut théoriquement fonctionner indéfiniment (donc je peux l'exécuter du jour au lendemain pour le plaisir), mais il enregistre sa progression, donc toutes les images sont prises à partir de la marque 1-10 min.
Il lit d'abord l'image, puis utilise la détection des bords sobel pour trouver l'angle de tous les bords, afin de s'assurer que les lignes n'empiètent pas sur une autre couleur. Une fois qu'une ligne de la longueur aléatoire à l'intérieur (lengthmin, lengthmax) est définie, elle teste ensuite pour voir si elle contribue à l'image globale. Bien que les lignes plus petites soient meilleures, je règle la longueur de la ligne de 10 à 50.
la source