# ASCII ART edge detection

As the title says, I was thinking to contest in which one must detect edges of an ASCII art.

The code should accept a B/W ASCII art as input. A B/W ASCII art is defined as (by me) an ASCII art with only one kind of non-white-spaces character (in our case: an asteriks *). And as output produce a standard ASCII art (all ASCII characters are accepted) which should remember the contourn of the first.

The purpose of using more than one character in the output is to make some edges ssmoother. For instance, one could let this input

     ***
****
******
******
******
******
****
***


could became:

      ___
_/   )
_/    /
/      |
|      /
|      \
\      |
\     |
\___)


The input \n separated string as input. Each line has a maximum of 80 characters. The number of rows is not specified.

This is my sample Python3 program:

import fileinput as f
import re as r
import copy as c
a,s,p='*',' ','+'
s=[list(' '*n)]
for l in f.input():
if(len(l)>n):l=l[:n]
k=list(r.sub('[^ ^\%c]'%a,'',' '+l+' '))
s.append(k+[' ']*(n-len(k)))
s.append([' ']*n)
return s
def np(s):
s=c.deepcopy(s)
for l in s[1:-1]:
for w in l[1:-1]: print(w,end='')
print()
def grow(i):
o=c.deepcopy(i)
for x in range(1,len(o)-1):
for y in range(1,len(o[x])-1):
if(i[x][y]==a): o[x-1][y-1]=o[x-1][y+1]=o[x-1][y]=o[x+1][y]=o[x+1][y-1]=o[x+1][y+1]=o[x][y+1]=o[x][y-1]=a

return o
def diff(i,o):
c=[]
for x in range(0,len(i)):
l=[]
for y in range(0,len(i[x])):
if(i[x][y]==a and o[x][y]==s): l.append(p)
else: l.append(s)
c.append(l)
return c
np(diff(grow(I),I))


### Input:

Here below I put both input of the programs. It is an 80x70 ASCII ART. It means it has 70 lines of 80 characters, each separated by \n.

This input file contains only spaces and the asterisk *, it has a maximum of 80 columns as every ASCII art.

If you find a nicer art let me know!

                                              *************
*****          *****
******                  ***
***                         ****
*********                             **
***********                               **
******   *******                                **
*****       *******      ***                         **
****          ********     *****                          *
**            *********     *****                    *****  *
***            *********     *******                  ******  **
**             **********     *******                  ******   **
**              **********    *******                  ********   *
*               ***********   ******                    ********   *
**              ************   *****                     ********    *
*               ************    ***                       ********   *
*               *************                               ******    *
*                *************                                 ***     *
**                *************                                         *
*                **************                                         *
**                *************                                         **
*                 *************                                         **
**                *************                                          ***
***                *************                                          ****
**                 ************                                           ****
**                *************                                           ****
**                *************           *****                           ****
**                *************          **   **          **              ****
**                 ************          *     *         ** **            ****
*                  ************          **   **        **   **           ****
*                  *************        *******         **   ***          ****
*                  ************          *****           *******          ****
*                   ************         ***               *****          ****
**     *             *************                          ****          *****
**    ***            **************                                      *****
*    *****            *************                                     ******
** *******             **************                                  *******
**********             ***************              *                *********
**********              *****************          ***             ***********
***********              *******************                    **************
***********               **********************            ******************
************              *****************     **     ***********************
*************             ******************      ****     *******************
**************            ******************              ********************
****************           ******************              *******************
***************           *******************              *******************
****************           ******************              ******************
******************         ******************             *******************
*******************         *****************             *******************
*********************      ******************           ********************
*********************************************          *********************
**********************************************       ***********************
************************     *****************      ************************
**********************       ******************* **************************
*********************        *********************************************
*********************        ****************************  ***************
********************         **************************    ***************
********************         *********************         ***************
*******************          ********************         ****************
******************           *****************            ****************
*****************             ****************            ***************
*****************             ****************            ***************
*****************             *****************           ***************
****************             *****************           ***************
**************              ******************          ***************
****************          ****************
**************            ***************
**************
************


### Possible output:

A possible output could be:

                                         +++++             ++++
++++++     ++++++++++     +++
++      +++++        +++++   +++++
++++++++   +++++                ++++    ++
++++         ++                       ++++  ++
++++++           ++                           ++  ++
+++++      +++       +   +++++                     ++  ++
++++     +++++++       ++  ++   ++                     ++  ++
++    +++++   ++        +   +     +                  +++++++ ++
+++  ++++      ++         +  ++     ++                ++     ++ ++
++   ++        ++         ++  +       +                +      ++  ++
++  +++         +          +  ++       +               ++      +++  +
++  ++          ++          + ++       ++               +        +++ +
++ +++          ++           + +      +++                +        + + ++
+  +            +            + +     ++                  +        ++++ +
++ ++           ++            + ++   ++                   ++        + + +
++ ++            +             +  +++++                     ++      ++ + +
++ ++             +             +                             +++   ++  + +
+  +             ++             +                               +++++   + +
++ ++             +              +                                      ++ +
+  +              +             ++                                      +  +
++ ++             ++             +                                       +  ++
++  +              +             ++                                       +   ++
+   +              +             +                                        +    +
+  ++             ++            ++                                        +    +
+  +              +             +         +++++++                         +    +
+  +              +             +        ++     ++        ++++            +    +
+  +              +             +        +  +++  +       ++  +++          +    +
+  +              ++            +        + ++ ++ +      ++  +  ++         +    +
+ ++               +            ++      ++  +++  +      +  +++  ++        +    +
+ +                +             +      +       ++      +  +++   +        +    +
+ +                +            ++      ++     ++       ++       +        +    +
+ +   +++          ++            ++      +   +++         +++     +       ++    +
+  ++ ++          +             ++     +++++             +    ++      ++     +
+ ++   ++         +              +                       ++++++      ++     ++
++++     +         ++             +++                                ++      +
+       +          ++              ++            +++              +++       +
+           +               ++++        ++ ++           +++         +
++          ++                 ++++     +   +        ++++           +
+           ++                   +++++ +++++    +++++              +
++           ++                      +++   ++++++                  +
++           +                 +++++  +++++                       +
++          +                  +  +++    +++++                   +
+++        +                  ++   ++++++  +                    +
+        ++                  +           ++                   +
++        +                   +            +                   +
+++      ++                  +           ++                  ++
++      +                  +           +                   +
+++    ++                 +         +++                   +
++++++                  +        ++                    ++
++     +++                     +
+    ++                       +
+++++                 ++++++                        +
+                      ++   ++                   +                          +
+                     ++     +                                             ++
+                     +      +                            ++               +
+                    ++      +                          ++++               +
+                    +       +                     ++++++ ++               +
+                   ++       +                    ++      +                +
+                  ++        +                 ++++       +                +
+                 ++         ++                +          +               ++
+                 +           +                ++         +               +
+                 +           +                 +         +               +
++                +           +                 ++        +               +
++              ++           +                  +        +               ++
++++++++++++++++            +++                +        +                +
++              ++        ++               +
++++++++++++++++          ++              +
++            ++
++++++++++++++


This is also the output produced by the script above. Of course it is not the best output and I'm sure one can easily produce a smoother one.

It is a popularity-contest since, I hope votes will be proportional to elegance and quality of outputs! (Also I guess good results acan be obtained combinig aplay and gimp-cli) There are no strict rules on how the output should be..just use your fantasy!

• Please define the input that will be used in all the answers to compare them. The panda is too large IMHO. – A.L Apr 21 '14 at 22:37
• Does the length of each line of the input need to be constant? The first line of the panda is shorter than the other lines (spaces are missing at the end). – A.L Apr 21 '14 at 22:59
• Does the input file contains only one character and spaces? – A.L Apr 21 '14 at 23:06
• Thanks for your questions, I don't think the panda is too large: it has 80 column as every ASCII art. I didn't said it, but the max of columns should be 80. Yes the input file contains only the asterisks and the space. Thanks again, I added these info in the question. – Antonio Ragagnin Apr 22 '14 at 7:20
• That's a panda? I thought it was snoopy.... – Justin Apr 23 '14 at 6:51

### GolfScript

I thought golfing is popular on this site, so a GolfScript submission always fits for a popularity contest.

n%.0=,' '[*]\1$++{0\0++{42=}%[{.}*]);2/}%{.}*]);2/{zip{~+2base' /\-\|/ /\| - '=}%n+}%  You can try the code with your own ascii art here. Note that it is required that all lines have the same length. Example:  /------------\ /--- --------- --\ /---- ---/ \--- -\ / ---/ \--\---\ /------ / \-- \ /-- / \ \ /---- -- | \ \ /--- ----/ / / /--\ \ \ /-- ---/ / | / \ \-\\ / --/ / | | | /----\\\\ /- / / / / \ / | | \ / -/ / | | | | | \ \ / / | | / / / \ \ | //-/ / | / -/ | | || / | / | | / | | \\\ | / | | \ / \ \ || /// / | \--/ \ / || /// | | \- / || / | | | \--/ || | / / | || / | | / / | | / | | | | / | / / | \ / | | | | \ | / | / | | | | / | | | | | | | /----\ | | | | | | / -- \ /-\ | | | | \ | | / \ | / \-\ | | | / | | | \ / | / /\ \ | | || | \ / -- / | | | \ | | || | / \ / \ -- | | | || \ \ | -/ \- | | | / | /\ | \ \--/ | / / | | | / \ | \ \---/ / / | / / \ \ | / | | \/- | \ -\ / | | | | \ /\ /- | | | \ --\ / \ /- | | \ \ --\ \--/ /-- | | | \ ---\ /--- | | \ | ----\-\ /---- | | \ | \ \-\---\\--- | | \ | | \---/ / | | -\ \ \ \ | | / / | | | | \ \ | | / | -\ | | / | | \ \ | | | | -\ / | /- / | ----- | / | | \ /- | | ---- | / | \ / \ --\/- | | / | / | | | - | | / | -/ | | | | | ----/ | | | / | / / | | / | --/ | | | / \ | | / | | | | | | | | | \ | | \ | | | | | \ / | \ | | \-------------/ \- | | \ \ / \ | \-------------/ \ | \ / \-----------/  • Golfscript is always relevant. – Nit Apr 22 '14 at 23:09 • Ha it makes the panda look enraged +1 for using more than 1 character. – Magic Octopus Urn Aug 3 '17 at 20:08 The Python code, primarily relies on regex to do the task. def edge_detect(st): width = len(max(st.split('\n'), key=len)) #Pad the image with extra blank lines above and below st = '{{0: <{0}}}\n{{1}}\n{{0: <{0}}}'.format(width).format('', st.rstrip('\n')) return re.sub(r""" #Match a non space character (?<=\s.{{{0}}})[^\s]|#When the char above is a space [^\s](?=.{{{0}}}\s) |#When the char below is a space (?<=\s)[^\s]| #When the previous char is a space [^\s](?=\s) #When the following char is a space """.format(width), '+', #Replace it with edge character '+' st, flags=re.X|re.S).replace('*',' ') # And finally replace all # non-space character with spaces  *Output >>> print edge_detect(st) +++++++++++++ +++++ +++++ ++++++ +++ +++ ++++ +++++++++ ++ ++++ + ++ ++++++ + ++ ++ +++++ ++ + +++ ++ ++++ ++ + ++ + + ++ ++ ++ + + +++++ + +++ ++ + ++ + ++ + ++ ++ ++ + + ++ + + ++ ++ + + ++ +++ ++ + + + ++ + ++ ++ + + + ++ ++ + + ++ + + + + + + +++ + ++ + + ++ + + ++ + + + + +++ + ++ + + + + ++ ++ + ++ + + ++ + + ++ ++ ++ ++ + + + +++ + ++ + + ++ + + + + ++ ++ + + + ++ + + +++++ + + ++ + + ++ ++ ++ + + ++ + + + + ++ ++ + + + + + ++ ++ ++ ++ + + + + ++ ++ +++ ++ + + + + + + + + +++ + +++ + + + + + + +++ + ++ + + ++ + + + ++++ ++ ++ ++ +++ + + ++ + + ++ + + + ++ + ++ +++ + + + ++ + + + + + + + +++ + + + + ++ +++ +++ + + + + ++ ++++ + + + + ++++++ +++++ + + + + + ++ ++++++ + + + + + ++++ + + + + + + ++ + + ++ + + + + + + ++ + + ++ + + + + + + + + + + ++ + + + + + + ++ + + ++ + +++ + + ++++++ + ++ + + +++++ + +++ + + ++ + + ++ + + ++ + ++ +++ ++ + + + + ++ + + ++ + +++ + + + + + ++++++ + + + ++ + ++ + + + ++ + ++++ ++ + + ++ + + + ++ + + + + + + + + + + + + + + + + + + + ++ + + + + ++++++++++++++ + + + + + ++ + + ++++++++++++++ + + + ++ ++++++++++++  Another one print edge_detect(st) +++ ++ + ++ + + + + + ++ + ++ + +++  # Python Using gradient operation to identify edges: from numpy import gradient, zeros import matplotlib.pylab as plt b = open("file").readlines() bi = zeros((len(b),len(b[0]))) e = enumerate for i,l in e(b): for j,c in e(l): if(c=="*"): bi[i][j]=1 g = gradient(bi,.5,.5) g = (abs(g[0])+abs(g[1]))>=1. plt.subplot(2,1,1) plt.imshow(bi,cmap='Greys'), plt.show() plt.subplot(2,1,2) plt.imshow(g*1,cmap='Greys'), plt.show()  Output for the banana and panda: To make an ASCII Output, the part of the plots should be replaced with: r = range s = "" for i in r(len(b)): for j in r(len(b[0])): if(g[i][j]!=0): s+="*" else: s+=" " s +="\n" print s  ASCII Output: Banana:  *** ** **** ** *** ** * ** * ** *** ** **** ** *** **  Panda:  *************** **** ****** ************* *** *** ***** ***** ***** ******** ***** **** ** ********** ** ****** ****** * ** **** ***** ***** ** *** **** **** ****** ** ** ***** **** ** ***** ** ** ** ** **** * * ******* ** ** ** ** ********** ** ** ** ** ** ** ** ****** ***** ** ** ** ** ** ** **** **** ** ** ** *** ** ** * * **** ** ** ** *** ** ** *** **** ** ** ** ** ** ** *** *** ** ** ***** ** ** * * * * ** ** *** *** ** * * *** ** ** ****** * * **** ** ** *** * * * * ** ** * * **** ** ** **** * * ** ** **** **** ** ** ** ** ** ** ** ** ** ** **** ** ** ** ** **** ** ** ***** ** ** **** ** ** ** ** ** ** ** **** ** ** ********* ***** ** ** **** ** ** * * * * ******* ** ** * * ** ** ********* **** **** ** ** * * ** ** ** ***** ******* ** ** ** * * ** ** ** *** ** ** ** ** ** * * * ** ** ****** *** ** ** ** *** *** ** ** *** ****** ** ** ** ** ** ** ** **** ** ** ** *** ** ** *** ** ** **** ** ** *** * *** ** * ** ** **** *** **** ** ** ** ****** ***** ***** ** ** ** ******* *** ******* ** ** ** * *** ********* ** ** ** ************** * ** ** ** ** *** ******* ** *** ** ** **** ** ** *** ** ** ** ** ** ** ** ** ** *** ** ** ** ** *** ** ** ** ** *** ** ** *** ** ********* ** *** ** ****** ** *** ** ***** ** *** ** * ******* **** *** ** ** ** ** ****** ** ** ** ** * ** ** ** ** ** ***** ** ** ** ** ******* ** ** ** ** ** ****** ** ** ** ** ** **** ** ** ** ** ** **** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **************** *** ** ** ** ************** *** ** ** ** **************** ** ** ************** ** ** ** **  • A banana? It's a boomerang for me. :) – A.L Apr 23 '14 at 17:07 # Mathematica Assuming that panda contains the original string, the following obtains the pixels of the contour edges and replaces them with "+". t = (Most /@ Partition[Take[Characters@panda, {61, 5636}], 82]) /. {"*" -> 1, " " -> 0}; Grid[ImageData[EdgeDetect[Image[t]]] /. {1 -> "+", 0 -> " "}, Spacings -> 0]  ## How it works Partition[Take[Characters@panda, {61, 5636}], 82] breaks the string up into lines of characters. Most removes the new line characters. Image[t]]] converts the matrix of 0's and 1's into an image. EdgeDetect finds the edges of the image. ImageData obtains the binary matrix of the image. /. {1 -> "+", 0 -> " "} replaces each 0 and 1 with the appropriate character. Grid displays the Ascii art. Java This checks lines and rows if there's anything on top, left, right or bottom and based on that picks a value from array holding symbol that's used to generate new art using edges! Example output:  /^^^^^^^^^^^\ /^^^/ \_^^\ /^^^^/ \^\ / / /^^\ /^^^^^^ / \\ /^^_ | \\ /^^^^/ | / \\ /^^^/ / | /^\ \\ /^^/ / | / \ / // / / | | /^^^\ / /^/ / | / \ / | \\ // / | | / | | \\ // | | / _/ / \ | / / | / / | | \ // / | \ / \ | / \ | | \_/ \ \ | / / | \_ / | / | | \_/ | // | | | | / / | // | | /| | | / || /| / | | \ / / | / | \ || | | | | || / | | | || | | /^^^\ | | || \ | // \\ /\ | | |/ | | | | // /\ | | | | | |\ // /| |\ | | | | \ / ^^^/ \| | \ | | | \ | | _/ \^^^ | | | | | \ \_/ | / | | /| / | \ \__/ / / |/ / \ \ \ / | | / \ \ | / | |\ /^ | | ^\ / | | ^ | \ \ / /^ | | | \ ^^\ /_\ /^ | | \ \ ^^\ /^^ | | | | _^^^\ /^^^ | | \ | | /\ /^^^^ | | \ | \ /^^\ | | | \ \ | / | | ^\ | \ | | | | / | | / | \ | | | | | ^\ \ | / | | \ | | | / | ^\ / | /^ | | ^^^^^^ | / | | _____ \ /^ | \ / \ | / | | / | ^^\ /^ / | | | ^ __ | | / | _/ | | | | | ____/ | | | / | / | | | / | __/ / | | / \ | | / | | | | | | | | | | | | \ | | \ | | \ / | | | | \____________/ \_ \ | | \ / \ \ \____________/ \ | \ / \__________/ /^\ /^ | /^ / / | \ | \_ \ \_ | \_\  Code: package com.ruuhkis.asciiedge; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; public class ASCIIEdge { public static void main(String[] args) { try { if (args.length > 0) { for (String arg : args) { new ASCIIEdge().detach(new FileInputStream(new File(arg))); } } else { new ASCIIEdge().detach(new FileInputStream(new File("art.txt"))); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private void detach(InputStream is) throws IOException { BufferedReader bw = new BufferedReader(new InputStreamReader(is)); StringBuilder artBuilder = new StringBuilder(100); int longestLineLength = 0; int numLines = 0; String line = null; while ((line = bw.readLine()) != null) { artBuilder.append(line + System.getProperty("line.separator")); if (line.length() > longestLineLength) { longestLineLength = line.length(); } numLines++; } bw.close(); char[][] artBuffer = new char[numLines][longestLineLength]; String[] lines = artBuilder.toString().split( System.getProperty("line.separator")); for (int i = 0; i < lines.length; i++) { lines[i].getChars(0, lines[i].length(), artBuffer[i], 0); for (int j = lines[i].length(); j < longestLineLength; j++) { artBuffer[i][j] = ' '; } } detach(artBuffer, longestLineLength, numLines); } private void detach(char[][] artBuffer, int longestLineLength, int numLines) { char[][] outputBuffer = new char[numLines][longestLineLength]; for (int i = 0; i < numLines; i++) { for (int j = 0; j < longestLineLength; j++) { ; int horizontalEdge = isHorizontalEdge(artBuffer[i], j, longestLineLength); int verticalEdge = isVerticalEdge(artBuffer, i, j, numLines); char[][] result = { { '/', '^', '\\' }, { '|', ' ', '|' }, { '\\', '_', '/' } }; outputBuffer[i][j] = result[verticalEdge + 1][horizontalEdge + 1]; ; } System.out.println(outputBuffer[i]); } } private int isVerticalEdge(char[][] chars, int row, int col, int numLines) { boolean canBeEdge = chars[row][col] != ' '; boolean upperEdge = row - 1 < 0 || chars[row - 1][col] == ' '; boolean lowerEdge = row + 1 >= numLines || chars[row + 1][col] == ' '; return (canBeEdge && (upperEdge || lowerEdge)) ? upperEdge ? -1 : 1 : 0; } private int isHorizontalEdge(char[] chars, int index, int length) { boolean canBeEdge = chars[index] != ' '; boolean leftEdge = index - 1 < 0 || chars[index - 1] == ' '; boolean rightEdge = index + 1 > length - 1 || chars[index + 1] == ' '; return (canBeEdge && (leftEdge || rightEdge)) ? leftEdge ? -1 : 1 : 0; } }  Ps. first timer here, don't be rough :D Pps. that Panda looks like its sad :( • I assure you no pandas were harmed during the making of this ASCII art – Antonio Ragagnin Apr 23 '14 at 18:08 Python (ascii -> image -> edge filter -> ascii) I kind of cheated, I converted the ascii text to an image and ran PIL edge detect filter on it. Then, I inverted the image and converted back to ascii text: from PIL import Image, ImageFilter, ImageOps import random from bisect import bisect greyscale = [" "," ",".,-","_ivc=!/|\\~","gjez2]/(YL)t[+T7Vf","mdK4ZGbNDXY5P*Q","W8KMA","#%$"]
zonebounds=[36,72,108,144,180,216,252]

f=open('input.txt', 'r')
f.close()

width=82
height=len(lines)

im = Image.new("RGB", (width,height), "white")

y=0
for line in lines:
x=0
for px in line:
if px != ' ' and x < width:
pixels[x,y] = (0,0,0)
x+=1
y+=1

im=im.resize((width, height),Image.BILINEAR)
im=im.convert("L")
im=im.filter(ImageFilter.FIND_EDGES)
im=ImageOps.invert(im)

str=""
for y in range(0,im.size[1]):
for x in range(0,im.size[0]):
lum=255-im.getpixel((x,y))
row=bisect(zonebounds,lum)
possibles=greyscale[row]
str=str+possibles[random.randint(0,len(possibles)-1)]
str=str+"\n"
print str


Here is the result:

$#$$#%$$%%$$%$$$$%###%%#%%%##$$$%%#$#%#$%%%%$$%###$$%%%##%##
%                                   $%%$$%#%$$$#$$%# # % %% %#$$$$% %#%#% # % %#%%$$   #%$$% %%%% % #  #$$$%$                       $### #%$
%                   #%$#$#           $% %# #$        #
#               #%$%#$##       %%$% $$% # % %#% ##%% ## % %#$$ %$      $% %$    %$%$$%# # # ##$$$ $$% % %# ##% ## # #% % # #% %% % % # # % % # %$$  $$# # % %# % # ## # % %#%  # % #% #% %# #$$       $%$        $$#  % % #%$$%          %%           % %#                #        % $##$
%     $% # # % %% % #$#$# # %$% $% #% % %$   #%                   %%        # $% %$   $$% % # %#%% ##$$ # $% #$% #             $#$$% % % % % #% # %#%# % #$$ #%$              #                                      ## #  %
$% #$             #$#$  %
%$$## %# %$$ #
$$% # % # #%   % % % #  %# #% % # # % % #  #%##% % %#   #  % # %#%% # %% # % # # % % % %% %%# % # % # #% # # ## # # %# % %  #  % % % %$$$%$  #$# %# % #$
# %                      #       $%$  #$% %$    $$% %  % %# ##$$       $# ## % # ### %# #%$   %%$#$%     #       %#    %%
#  %% $# # ## ##%$#             #    %#      $$%# % %%$$         %              %                       ##$%$#      %%     #%%
#%$% # #$             ##%                                %#      % %
%       %          %%              $# %#%$% %
$# $$% # % %## # #% % %#% % %%# # % ## #%## ##$$ %#%%% % %$%           $%$##   %##$$% # % %# % #### ### % # % # % %#$$#%#                   # %
#%%        %                  ##   %$##$%  #                    # $% %$                  $%$                   % %
%%        #                   $%$ #
%%#      #%                  #           ##                  $$%  % # % % %## #%  %# # # %###%  #% %$$     #%   #
#    ##                       #   $#%%$%                 $%#%$%                        %   $#$%   %$# %$
#                     %#     #                                             $# % % # %$#               
%                    %#      #                          #$#%$    %
       #                     %%%$#$ #$% #$                   $%$                    %%          %
#                  #$% #%#% %$    %
%                 $% ## # % #$    $% # # %$         %               #     #
$#$                 #         #               %     %
%$#$                 %$%$     #
##%              #%           %                  #        $%$    %
# ##%#%$$#%#%$$#%#            #%$# % # % # ## ##$#               $# %$##$#%$#$$#$$%%          $$# % #%##$$#$##$%#$%#%#$#%%#$%#$$#%%%%%%%#%##%%#$$##%#$%            #$%$


Sources cited (for greyscale image to ascii conversion): http://stevendkay.wordpress.com/2009/09/08/generating-ascii-art-from-photographs-in-python/

• I like it! I once tried to do it only using commands: convert (to convert ASCII art to image); GIMP-command-line (to perform edge detection); and aplay (to render the image in ASCII art). but failed:p (and welcome to Codegolf) – Antonio Ragagnin Apr 25 '14 at 20:05
• Thanks! I thought to myself, how can I leverage all the work that has already been conducted on image convolution with minimum rework. I also wanted to output more than one type of character to "blend" the text lines, this gives it a more retro feel. Ascii artists used to draw with text paint programs and use different symbols to make patterns like this. On a related note, there was also a version of Quake that redrew the pixels in ascii. It was very surreal. – blakesteel Apr 25 '14 at 20:32

## k4

this is a lazy version that just finds the edges, it doesn't try to find the prevailing shape and pick an appropriate character

the "algo" is just to find all cells that differ from the one to the left or above, then use array-language magic to turn the boolean matrix back into ASCII art

there's a minor hack to pad the beginning of everything with an extra space, or it would consider the left and top to be "edges" -- this way it still does, but i can just drop that off later

$cat o.k f:{(1_~~':" ",)'x} g:{(f x)|+f@+x} h:{-1" +"g@0:$,/$x;} h@*.z.x \\$


more or less the same output as the sample in the spec

here it is on the boomerang/banana:

$cat b.txt *** **** ****** ****** ****** ****** **** ***$ q o.k -q b.txt
+++
++  +
++    +
+     +
+     +
++    ++
+++   +
+++ +
\$


# Python

This is very simple Python version of "highpass" filter :). It checks whether a pixel is at least surrounded by its 4 sides. This is one of my first Python codes ever so please be subtle...

import sys
def px(x,y):
try:
v = s[x][y]
except IndexError:
v = ' '
return v
def r(x,y):
return '{:<3}'.format(s[x][y-1:y+2])
def v(x,y):
return (px(x,y)==' ' or r(x,y)=='***' and px(x-1,y)=='*' and px(x+1,y)=='*') and ' ' or '*'
for row in range(len(s)):
for cell in range(len(s[row])):
sys.stdout.write(v(row,cell))
print


Output:

                                              *************
*****          *****
******                  ***
* *                         ****
******* *                             **
****      *                               **
******   *     *                                **
*****       *     *      ***                         **
****          *      *     *   *                          *
**            *       *     *   *                    *****  *
***            *       *     *     *                  *    *  **
**             *        *     *     *                  *    *   **
**              *        *    *    **                  *      *   *
*               *         *   *    *                    *      *   *
**              *          *   *   *                     *      *    *
*               *          *    ***                       *      *   *
*               *           *                               **   *    *
*                *           *                                 ***     *
**                *           *                                         *
*                *            *                                         *
**                *           *                                         **
*                 *           *                                         **
**                *           *                                          * *
* *                *           *                                          *  *
**                 *          *                                           *  *
**                *           *                                           *  *
**                *           *           *****                           *  *
**                *           *          **   **          **              *  *
**                 *          *          *     *         ** **            *  *
*                  *          *          **   **        **   **           *  *
*                  *           *        *  ****         **   * *          *  *
*                  *          *          *  **           ****  *          *  *
*                   *          *         ***               *   *          *  *
**     *             *           *                          ****          *   *
**    * *            *            *                                      *   *
*    *   *            *           *                                     *    *
** **    *             *           **                                  *     *
* *      *             *             *              *                **      *
*        *              *             ***          ***             **        *
*         *              *               ***                    ***          *
*         *               *                *****            ****             *
*          *              *               *     **     *****                 *
*           *             *                *      ****     *                 *
*            *            *                *              *                  *
*             **           *                *              *                 *
*             *           *                 *              *                 *
*              *           *                *              *                *
*               **         *                *             *                 *
*                 *         *               *             *                 *
*                  **      *                *           **                 *
*                    ******                 *          *                   *
*                       *****                *       **                    *
*                      *     *               *      *                      *
*                    *       *               *** **                       *
*                   *        *                  *        **              *
*                   *        *                         **  *             *
*                  *         *                    *****    *             *
*                  *         *                   *         *             *
*                 *          *                ***         *              *
*                *           *               *            *              *
*               *             *              *            *             *
*               *             *              *            *             *
*               *             *               *           *             *
*              *             *               *           *             *
**************              **               *          *             *
*              *          *              *
**************            *             *
*            *
************

• Can you please add the output? – A.L Apr 23 '14 at 17:10
• Wow, thanks for formatting. Couldn't find Python highlighting. Output added. – avall Apr 23 '14 at 17:48
• You're welcome. :) AFAIK, the highlighting requires to use the file extension of the language: <!-- language: lang-py --> – A.L Apr 23 '14 at 17:50

# R

For each point in the matrix, hide the character if it's surrounded by asterisks on right, left, top and bottom. This is naive but works very well.

text = scan(commandArgs(T)[1], what='raw', sep="\n", quiet=T)

height = length(text); width = max(sapply(text, nchar))

mat_2 = mat = matrix(unlist(strsplit(text, '')), height, width, byrow=T)

for (y in 1:nrow(mat_2)) {
for (x in 1:ncol(mat_2)) {
if (
((x < ncol(mat)) && (mat[y, x + 1] == '*')) # right
&&
((x > 1) && (mat[y, x - 1] == '*')) # left
&&
((y > 1) && (mat[y - 1, x] == '*')) # top
&&
((y < nrow(mat)) && (mat[y + 1, x] == '*')) # bottom
) {
mat_2[y,x] = ' '
}
}
}

for (a in 1:nrow(mat_2)) {
cat(paste(mat_2[a,], collapse=""), "\n")
}


Usage: Rscript script.r input_.txt

## Output

                                              *************
*****          *****
******                  ***
* *                         ****
******* *                             **
****      *                               **
******   *     *                                **
*****       *     *      ***                         **
****          *      *     *   *                          *
**            *       *     *   *                    *****  *
***            *       *     *     *                  *    *  **
**             *        *     *     *                  *    *   **
**              *        *    *    **                  *      *   *
*               *         *   *    *                    *      *   *
**              *          *   *   *                     *      *    *
*               *          *    ***                       *      *   *
*               *           *                               **   *    *
*                *           *                                 ***     *
**                *           *                                         *
*                *            *                                         *
**                *           *                                         **
*                 *           *                                         **
**                *           *                                          * *
* *                *           *                                          *  *
**                 *          *                                           *  *
**                *           *                                           *  *
**                *           *           *****                           *  *
**                *           *          **   **          **              *  *
**                 *          *          *     *         ** **            *  *
*                  *          *          **   **        **   **           *  *
*                  *           *        *  ****         **   * *          *  *
*                  *          *          *  **           ****  *          *  *
*                   *          *         ***               *   *          *  *
**     *             *           *                          ****          *   *
**    * *            *            *                                      *   *
*    *   *            *           *                                     *    *
** **    *             *           **                                  *     *
* *      *             *             *              *                **      *
*        *              *             ***          ***             **        *
*         *              *               ***                    ***          *
*         *               *                *****            ****             *
*          *              *               *     **     *****                 *
*           *             *                *      ****     *                 *
*            *            *                *              *                  *
*             **           *                *              *                 *
*             *           *                 *              *                 *
*              *           *                *              *                *
*               **         *                *             *                 *
*                 *         *               *             *                 *
*                  **      *                *           **                 *
*                    ******                 *          *                   *
*                       *****                *       **                    *
*                      *     *               *      *                      *
*                    *       *               *** **                       *
*                   *        *                  *        **              *
*                   *        *                         **  *             *
*                  *         *                    *****    *             *
*                  *         *                   *         *             *
*                 *          *                ***         *              *
*                *           *               *            *              *
*               *             *              *            *             *
*               *             *              *            *             *
*               *             *               *           *             *
*              *             *               *           *             *
**************              **               *          *             *
*              *          *              *
**************            *             *
*            *
************