Écrivez un programme qui prend une image truecolor standard et une seule couleur RVB 24 bits (trois chiffres de 0 à 255). Modifiez l'image d'entrée (ou sortez une nouvelle image avec les mêmes dimensions) de sorte que sa couleur moyenne soit exactement la couleur unique qui a été entrée. Vous pouvez modifier les pixels de l'image d'entrée de la manière que vous souhaitez pour y parvenir, mais l'objectif est de rendre les changements de couleur aussi visuellement imperceptibles que possible .
La couleur moyenne d'une image RVB est en réalité un ensemble de trois moyennes arithmétiques , une pour chaque canal de couleur. La valeur rouge moyenne est la somme des valeurs rouges sur tous les pixels de l'image divisée par le nombre total de pixels (la zone d'image), arrondie à l'entier le plus proche. Les moyennes verte et bleue sont calculées de la même manière.
Ce script Python 2 (avec PIL ) peut calculer la couleur moyenne de la plupart des formats de fichier image:
from PIL import Image
print 'Enter image file'
im = Image.open(raw_input()).convert('RGB')
pixels = im.load()
avg = [0, 0, 0]
for x in range(im.size[0]):
for y in range(im.size[1]):
for i in range(3):
avg[i] += pixels[x, y][i]
print 'The average color is', tuple(c // (im.size[0] * im.size[1]) for c in avg)
(Il existe ici des programmes de couleurs moyennes similaires , mais ils ne font pas nécessairement exactement le même calcul.)
La principale exigence de votre programme est que pour toute image d'entrée, la couleur moyenne de sa sortie correspondante doit correspondre exactement à la couleur qui a été entrée - comme jugé par l'extrait de code Python ou un code équivalent. L'image de sortie doit également avoir exactement les mêmes dimensions que l'image d'entrée.
Donc, vous pouvez techniquement soumettre un programme qui colore simplement l'entrée entière de la couleur moyenne spécifiée (parce que la moyenne serait toujours cette couleur), mais c'est un concours de popularité - la soumission avec le plus grand nombre de votes gagnera , et c'est si trivial la soumission ne vous apportera pas beaucoup de votes positifs. De nouvelles idées comme tirer parti des caprices de la vision humaine, ou réduire l'image et dessiner une bordure colorée autour d'elle (espérons-le) vous feront voter.
Notez que certaines combinaisons de couleurs et d'images moyennes nécessitent des changements de couleur extrêmement perceptibles. Par exemple, si la couleur moyenne à associer était noire (0, 0, 0), toute image d'entrée devrait être complètement noire, car si des pixels avaient des valeurs non nulles, ils rendraient également la moyenne non nulle ( sauf erreur d’arrondi). Gardez ces limites à l'esprit lors du vote.
Images de test
Certaines images et leurs couleurs moyennes par défaut pour jouer avec. Cliquez pour les tailles complètes.
A. moyenne (127, 127, 127)
Des images de fejesjoco avec toutes les couleurs répondent . Trouvé original sur son blog .
B. moyenne (62, 71, 73)
Yokohama . Fourni par Geobits .
C. moyenne (115, 112, 111)
D. moyenne (154, 151, 154)
E. moyenne (105, 103, 102)
Mont Shasta . Fourni par moi.
F. moyen (75, 91, 110)
Remarques
- Les formats d'entrée et de sortie exacts et les types de fichiers image utilisés par votre programme importent peu. Assurez-vous simplement qu'il est clair comment utiliser votre programme.
- C'est probablement une bonne idée (mais ce n'est pas une exigence technique) que si une image a déjà la couleur moyenne cible, elle doit être sortie telle quelle.
- Veuillez publier des images de test avec la couleur d'entrée moyenne (150, 100, 100) ou (75, 91, 110), afin que les votants puissent voir les mêmes entrées dans différentes solutions. (Publier plus d'exemples que cela est bien, même encouragé.)
la source
Réponses:
Python 2 + PIL, mise à l'échelle simple des couleurs
Voici une approche naïve qui devrait servir de bonne base de référence. À chaque itération, nous comparons notre moyenne actuelle avec la moyenne souhaitée et mettons à l'échelle le RVB de chaque pixel selon le rapport correspondant. Nous devons cependant être un peu prudents, pour deux raisons:
La mise à l'échelle de 0 donne toujours 0, donc avant de mettre à l'échelle, nous ajoutons quelque chose de petit (ici
0.01
)Les valeurs RVB sont comprises entre 0 et 255, nous devons donc ajuster le rapport en conséquence pour compenser le fait que la mise à l'échelle des pixels plafonnés ne fait rien.
Les images sont enregistrées au format PNG, car l'enregistrement au format JPG semble perturber les moyennes des couleurs.
Exemple de sortie
(40, 40, 40)
(150, 100, 100)
(75, 91, 110), palette Nuit étoilée
la source
C ++, correction gamma
Cela permet d'ajuster la luminosité de l'image à l'aide d'une simple correction gamma, la valeur gamma étant déterminée séparément pour chaque composant pour correspondre à la moyenne cible.
Les étapes de haut niveau sont les suivantes:
Toutes les entrées / sorties d'images utilisent des fichiers PPM en ASCII. Les images ont été converties de / vers PNG à l'aide de GIMP. Le code a été exécuté sur un Mac, les conversions d'images ont été effectuées sur Windows.
Code:
Le code lui-même est assez simple. Un détail subtil mais important est que, alors que les valeurs de couleur sont dans la plage [0, 255], je les mappe sur la courbe gamma comme si la plage était [-1, 256]. Cela permet à la moyenne d'être forcée à 0 ou 255. Sinon, 0 resterait toujours 0 et 255 resterait toujours 255, ce qui pourrait ne jamais permettre une moyenne de 0/255.
Utiliser:
.cpp
, par exempleforce.cpp
.c++ -o force -O2 force.cpp
../force input.ppm targetR targetG target >output.ppm
.Exemple de sortie pour 40, 40, 40
Notez que les images de tous les échantillons plus grands sont incluses en JPEG car elles dépassent la limite de taille SE en PNG. Étant donné que JPEG est un format de compression avec perte, ils peuvent ne pas correspondre exactement à la moyenne cible. J'ai la version PNG de tous les fichiers, qui correspond exactement.
Exemple de sortie pour 150, 100, 100:
Exemple de sortie pour 75, 91, 110:
la source
Python 2 + PIL
Cela parcourt chaque pixel dans un ordre aléatoire et réduit la distance entre chaque composante de la couleur du pixel et
255
ou0
(selon que la moyenne actuelle est inférieure ou supérieure à la moyenne souhaitée). La distance est réduite d'un facteur multiplicatif fixe. Ceci est répété jusqu'à ce que la moyenne souhaitée soit obtenue. La réduction est toujours au moins1
, sauf si la couleur est255
(ou0
), pour garantir que le traitement ne se bloque pas une fois que le pixel est proche du blanc ou du noir.Exemple de sortie
(40, 40, 40)
(150, 100, 100)
(75, 91, 110)
la source
Java
Une approche basée sur RNG. Un peu lent pour les grandes images d'entrée.
Tests:
(40,40,40)
(150 100 100)
(75,91 110)
la source