3 votes

Changer la couleur d'arrière-plan d'une image anti-crénelage en C# avec l'anti-crénelage

J'ai une image dont je dois changer la couleur d'arrière-plan (par exemple, changer l'arrière-plan de l'image d'exemple ci-dessous en bleu).

Cependant, l'image est anticrénelée et je ne peux donc pas simplement remplacer la couleur d'arrière-plan par une autre couleur.

J'ai essayé de créer une deuxième image qui n'est que l'arrière-plan, d'en changer la couleur et de fusionner les deux images en une seule, mais cela ne fonctionne pas car la bordure entre les deux images est floue.

Existe-t-il un moyen de faire cela, ou un autre moyen que je n'ai pas envisagé ?

Exemple d'image

8voto

LarsTech Points 43510

Utilisation de GDI+

Image image = Image.FromFile("cloud.png");

Bitmap bmp = new Bitmap(image.Width, image.Height);
using (Graphics g = Graphics.FromImage(bmp)) {
  g.Clear(Color.SkyBlue);
  g.InterpolationMode = InterpolationMode.NearestNeighbor;
  g.PixelOffsetMode = PixelOffsetMode.None;
  g.DrawImage(image, Point.Empty);
}

a donné lieu à :

enter image description here

4voto

Timothy Shields Points 17970

De manière abstraite

Chaque pixel de votre image est un vecteur (R, V, B), dont chaque composante est comprise dans l'intervalle [0, 1]. Vous voulez une transformation, T, qui convertira tous les pixels de votre image en un nouveau vecteur (R', G', B') sous les contraintes suivantes :

  • Les Noirs doivent rester Noirs
    • T(0, 0, 0) = (0, 0, 0)
  • le blanc doit devenir la couleur choisie C*
    • T(1, 1, 1) = C*

Une façon simple de procéder consiste à choisir la transformation T suivante :

T(c) = C* .* c  (where .* denotes element-wise multiplication)

Il s'agit d'une simple multiplication d'images.

Concrètement

Si vous n'êtes pas préoccupé par les performances, vous pouvez utiliser les méthodes (très lentes) suivantes GetPixel et SetPixel sur votre Bitmap pour appliquer cette transformation à chaque pixel de l'image. Si la manière de procéder n'est pas claire, dites-le dans un commentaire et j'ajouterai une explication détaillée pour cette partie.

Comparaison

Comparez cette méthode à celle présentée par LarsTech. La méthode présentée ici est en haut ; la méthode présentée par LarsTech est en bas. Remarquez les effets de bord indésirables sur l'icône du bas (voile blanc sur les bords).

Comparison

Et voici la différence d'image entre les deux :

Difference

Réflexion a posteriori

Si votre image source a un arrière-plan transparent (c'est-à-dire blanc transparent) et un premier plan noir (comme dans votre exemple), vous pouvez simplement créer votre transformée T(a, r, g, b) = (a, 0, 0, 0) puis dessiner votre image sur la couleur d'arrière-plan de votre choix, comme l'a suggéré LarsTech.

1voto

Paul Zahra Points 3034

Si vous souhaitez remplacer une couleur uniforme, vous pouvez la convertir en alpha. Je n'aimerais pas le coder moi-même !

Vous pouvez utiliser le code source Color To Alpha de GIMP (il est sous licence GPL). version de celui-ci

P.S. Je ne sais pas comment obtenir la dernière version.

1voto

Vinay Sharma Points 81

La suppression/le remplacement de l'arrière-plan, IMO, relève plus de l'art que de la science, vous ne trouverez pas d'algorithme unique pour résoudre ce problème MAIS, selon votre degré de désespoir ou d'intérêt pour la résolution de ce problème, vous voudrez peut-être considérer l'explication suivante :

Supposons que vous ayez une image en couleur.

Utilisez le mécanisme de décodage de votre choix et générez une image en niveaux de gris / luminosité de votre image couleur.

Tracez un graphique (métaphoriquement parlant) de la valeur numérique du pixel (x) par rapport au nombre de pixels de l'image pour cette valeur (y). Autrement dit, un histogramme de luminosité.

Maintenant, si votre arrière-plan est suffisamment grand (ou petit), vous verrez une partie du graphique représentant la distribution d'une gamme de pixels qui constituent votre arrière-plan. Vous pouvez sélectionner une plage légèrement plus large pour gérer l'anticrénelage (sur la base d'un décalage fixe que vous définissez si vous avez affaire à des images similaires) et l'appeler plage de luminosité pour votre arrière-plan.

Cela vous faciliterait la vie si vous connaissiez au moins un pixel (échantillon/valeur médiane d'un pixel) en dehors de la plage de pixels qui définit votre arrière-plan, de manière à pouvoir "rechercher" la partie du graphique qui définit votre arrière-plan.

Une fois que vous disposez de la gamme de pixels de luminosité pour l'arrière-plan, vous pouvez parcourir les pixels de l'image originale, comparer leurs valeurs de luminosité avec la gamme dont vous disposez et, si elle est comprise, remplacer le pixel de l'image originale par la couleur souhaitée, de préférence avec un décalage de luminosité basé sur le pixel original et le pixel échantillon, afin que l'arrière-plan remplacé ait également l'air anticrénelé.

Cette solution n'est pas parfaite et il existe de nombreux scénarios dans lesquels elle peut échouer ou échouer partiellement, mais elle fonctionnerait pour l'exemple d'image que vous avez joint à votre question.

Il existe également de nombreuses possibilités d'amélioration des performances, notamment grâce au GPGPU, etc.

Une autre solution possible consisterait à utiliser des bibliothèques de traitement d'images tierces préconstruites. Il en existe quelques-unes en open source, comme Camellia, mais je ne suis pas sûr des fonctionnalités fournies et de leur degré de sophistication.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X