Image à la conversion de l'art ASCII - Stack Overflow

Comment convertir l'image bitmap à l'art ASCII en C ++?

  • images d'échelle de gris
  • en utilisant des polices espacées mono-
  • garder les choses simples (ne pas utiliser des trucs trop avancé pour les programmeurs de niveau débutant)

Il y a plus d'approches pour l'image à la conversion d'art ASCII qui sont pour la plupart basés sur l'utilisation des polices mono-espacées, pour simplifier, bâton seulement à l'essentiel:







intensité pixel / zone sur la base (ombrage)

Cette approche traite chaque pixel de la zone de pixels comme point unique. L'idée est de calculer l'intensité d'échelle de gris moyenne de ce point et remplacez-le par caractère avec une intensité assez proche de celle calculée. Pour cela nous avons besoin d'une liste de caractères utilisables chacun avec une intensité précalculé laissent appeler carte de caractère. Pour choisir plus rapidement le caractère qui est le meilleur pour quelle intensité il y a deux façons:

linéaire distribué carte de caractère d'intensité

Donc, nous utilisons uniquement des caractères qui ont une différence d'intensité avec la même étape. En d'autres termes lorsque classement ascendant puis:

De même, lorsque notre carte de caractère est trié alors nous pouvons calculer le caractère directement à partir de l'intensité (aucune recherche nécessaire)

carte arbitraire distribué caractère d'intensité

Nous avons donc tableau de caractères et de leurs intensités utilisables. Nous devons trouver l'intensité la plus proche du intensity_of (dot) à nouveau si la carte nous avons classé [], nous pouvons utiliser la recherche binaire par ailleurs nous avons besoin de O (n) boucle de recherche min à distance ou O (1) dictionnaire. Parfois, pour simplifier la carte de caractères [] peut être traité comme linéaire distribué provoquant une légère distorsion gamma généralement invisible dans le résultat à moins que vous savez ce qu'il faut chercher.

conversion sur la base de l'intensité est grande également pour les images de gris (non seulement en noir et blanc). Si vous sélectionnez le point comme un seul pixel le résultat devient grand (1 pixel -> caractère unique) donc pour des images plus grandes une zone (multiplication de la taille de la police) est sélectionnée au lieu de conserver le rapport d'aspect et ne grossit pas trop.

  1. de sorte uniformément diviser l'image en pixels (échelle de gris) ou de zones (rectangulaires) dot « s
  2. calculer l'intensité de chaque pixel / Espace
  3. le remplacer par le caractère de carte de caractère avec l'intensité la plus proche

Comme caractère carte, vous pouvez utiliser tous les caractères, mais le résultat est de mieux si le personnage a des pixels dispersés uniformément le long de la zone de caractère. Pour commencer, vous pouvez utiliser:

classement descendant et faire semblant d'être linéaire distribués.

Donc, si l'intensité du pixel / zone est i = <0-255> alors le caractère de remplacement sera

si i == 0, alors le pixel / région est noire, si i == 127 alors le pixel / région est gris et si i == 255 alors le pixel / surface est blanche. Vous pouvez expérimenter avec différents personnages à l'intérieur carte [].

exemple ici ancienne mine en C ++ et VCL:

vous devez remplacer / ignorer des choses VCL sauf si vous utilisez l'environnement Borland / Embarcadero

  • mm_log est mémo où le texte est émis
  • BMP est entrée bitmap
  • AnsiString est une chaîne de type VCL forme indexée 1 pas de 0 comme char *.

Sur la gauche est sortie de l'art ASCII (taille de la police 5px), et sur l'image d'entrée droite zoomées quelques fois. Comme vous pouvez le voir la sortie est plus grande pixel -> caractère. si vous utilisez des zones plus vastes au lieu de pixels alors le zoom est plus petit mais bien sûr, la sortie est moins agréable visuellement. Cette approche est très facile et rapide à code / processus.

Lorsque vous ajoutez des choses plus avancées comme:

  • calcul de la carte automatisés
  • sélection automatique de pixel / Taille de la zone
  • corrections de rapport d'aspect

Ensuite, vous pouvez traiter des images plus complexes avec de meilleurs résultats:

résultat ici en rapport 1: 1 (zoom pour voir les caractères):

Image à la conversion de l'art ASCII - Stack Overflow

Bien sûr, pour la zone que vous perdez l'échantillonnage des petits détails. Ceci est l'image de la même taille que le premier exemple échantillonné avec des zones:







Comme vous pouvez le voir est plus adapté pour des images plus grandes

raccord caractère (hybride entre Shading et ASCII Art solide)

Cette approche tente de remplacer la zone (pas plus de points de pixel unique) de caractère avec une intensité similaire et la forme. Cela a conduit à de meilleurs résultats, même avec de plus grandes polices utilisées par rapport à l'approche précédente d'autre part cette approche est un peu plus lent bien sûr. Il y a d'autres façons de le faire, mais l'idée principale est de calculer la différence (distance) entre la zone d'image (point) et le caractère rendu. Vous pouvez commencer par la somme naïve de la différence entre les pixels abs mais qui conduira à pas de très bons résultats parce que même un changement de 1 pixel fera la distance grande, au contraire, vous pouvez utiliser des paramètres de corrélation ou différents. L'algorithme global est presque le même que l'approche précédente:

  1. de sorte uniformément diviser l'image à (échelle de gris) des zones rectangulaires dot « s
    • idéalement avec le même format que les caractères de police rendus (il conservera l'aspect ratio, ne pas oublier que les caractères se chevauchent généralement un peu dans l'axe x)
  2. calculer l'intensité de chaque zone (dot)
  3. le remplacer par le caractère de carte de caractère avec l'intensité la plus proche / Forme

Comment calculer la distance entre le caractère et le point? Telle est la partie la plus difficile de cette approche. En expérimentant ce que je développe compromis entre la vitesse, la qualité et la simplicité:

Diviser la zone de caractère aux zones

Image à la conversion de l'art ASCII - Stack Overflow

  • calculer l'intensité séparée pour gauche, à droite, en haut, vers le bas, et la zone centrale de chaque personnage de votre alphabet de conversion (carte)
  • normaliser les intensités de sorte qu'ils sont indépendants de la taille de la zone i = (i * 256) / (xs * YS)
  • image de source de processus dans les zones rectangulaires

    • (Avec le même rapport d'aspect que la police cible)
    • calculer pour chaque zone d'intensité de la même manière que dans le point 1
    • trouver la correspondance la plus proche de l'intensité dans l'alphabet de conversion
    • caractère ajusté de sortie
  • C'est le résultat pour la taille de police = 7px

    Image à la conversion de l'art ASCII - Stack Overflow

    Comme vous pouvez le voir la sortie est visuellement agréable même avec plus grande taille de la police utilisée (l'exemple précédent d'approche était avec la taille de la police 5px). La sortie est à peu près la même taille que l'image d'entrée (pas de zoom). Les meilleurs résultats sont obtenus parce que les personnages sont plus proches de l'image originale non seulement par l'intensité mais aussi par la forme globale et, par conséquent, vous pouvez utiliser des polices plus grandes et toujours en préservant les détails (jusqu'à un point de gros).

    code ici complet pour l'application de conversion basé VCL:

    Il est simple application de formulaire (Form1) avec un seul mm_txt TMemo en elle. Il charge l'image "pic.bmp". puis selon la résolution choix de l'approche à utiliser pour convertit en texte qui est enregistré dans « pic.txt » et envoyé au mémo pour visualiser. Pour ceux sans VCL ignorer les choses VCL et remplacer AnsiString avec tout type de chaîne que vous avez, et aussi les graphiques :: TBitmap avec une classe bitmap ou une image que vous avez à disposition avec une capacité d'accès de pixel.

    Note très importante est que celui-ci utilise les paramètres de mm_txt-> Font alors assurez-vous que vous définissez:

    • Font-> Pas = fpFixed
    • Font-> charset = OEM_CHARSET
    • Font-> Name = "Système"

    pour faire ce travail correctement sinon la police ne sera pas traitée comme mono-espacés. molette de la souris change juste la taille de police haut / bas pour voir les résultats sur différentes tailles de police

    • voir la visualisation Portraits de mots
    • utiliser un langage avec des capacités de sortie accès bitmap / fichier et texte
    • recommande fortement de commencer par la première approche car il est très facile détroit vers l'avant et simple, et ne puis passer à la seconde (qui peut être fait que la modification de la première si la plupart du code reste comme il est de toute façon)
    • Il est une bonne idée de calculer avec une intensité inversée (pixels noirs est la valeur maximale), car prévisualisation de texte standard est sur fond blanc conduisant donc à des résultats bien meilleurs.
    • vous pouvez expérimenter avec la taille, le nombre et la disposition des zones de lotissement ou d'utiliser une grille comme 3x3 à la place.

    Enfin voici une comparaison entre les deux approches sur la même entrée:

    Image à la conversion de l'art ASCII - Stack Overflow

    Lors de la lecture d'aujourd'hui de nouvelles questions que je suis une idée d'une application cool qui Grabs sélectionnée région de bureau et continue à alimenter asciiart convertisseur et voir le résultat. Après une heure de codage, il est fait et je suis très satisfait du résultat que je dois simplement avoir à ajouter ici.

    OK App consiste de seulement deux fenêtres. La première fenêtre principale est fondamentalement ma vieille fenêtre convertisseur sans sélection d'image et aperçu (tous les trucs ci-dessus est en elle). Il a juste l'aperçu ASCII et les paramètres de conversion. La seconde fenêtre est vide forme avec l'intérieur transparent pour la sélection de la zone saisissant (pas de fonctionnalité que ce soit).

    Maintenant, le minuteur, je prends juste la zone sélectionnée par la forme de sélection, passer à la conversion et l'aperçu du asciiart.

    Donc, vous entourez la zone que vous voulez convertir par la fenêtre de sélection et afficher le résultat dans la fenêtre principale. Il peut être un jeu, spectateur. Il ressemble à ceci:

    Image à la conversion de l'art ASCII - Stack Overflow

    Alors maintenant, je peux même regarder des vidéos en asciiart pour le plaisir. Certains sont vraiment sympa :).

    Si vous voulez essayer de mettre en œuvre ce en GLSL jeter un oeil à ceci:







    Articles Liés