- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想渲染给定的 ASCII 艺术世界地图 this GeoJSON file .
我的基本方法是将 GeoJSON 加载到 Shapely , 使用 pyproj 变换点到墨卡托,然后对我的 ASCII 艺术网格的每个字符的几何形状进行 HitTest 。
当以本初子午线为中心时,它看起来(编辑:大部分)OK:
但以纽约市( lon_0=-74
)为中心,它突然失控了:
我很确定我在这里的预测有问题。 (并且将 ASCII map 坐标转换为纬度/经度可能比转换整个几何更有效,但我不确定如何。)
import functools
import json
import shutil
import sys
import pyproj
import shapely.geometry
import shapely.ops
# Load the map
with open('world-countries.json') as f:
countries = []
for feature in json.load(f)['features']:
# buffer(0) is a trick for fixing polygons with overlapping coordinates
country = shapely.geometry.shape(feature['geometry']).buffer(0)
countries.append(country)
mapgeom = shapely.geometry.MultiPolygon(countries)
# Apply a projection
tform = functools.partial(
pyproj.transform,
pyproj.Proj(proj='longlat'), # input: WGS84
pyproj.Proj(proj='webmerc', lon_0=0), # output: Web Mercator
)
mapgeom = shapely.ops.transform(tform, mapgeom)
# Convert to ASCII art
minx, miny, maxx, maxy = mapgeom.bounds
srcw = maxx - minx
srch = maxy - miny
dstw, dsth = shutil.get_terminal_size((80, 20))
for y in range(dsth):
for x in range(dstw):
pt = shapely.geometry.Point(
(srcw*x/dstw) + minx,
(srch*(dsth-y-1)/dsth) + miny # flip vertically
)
if any(country.contains(pt) for country in mapgeom):
sys.stdout.write('*')
else:
sys.stdout.write(' ')
sys.stdout.write('\n')
最佳答案
我在底部进行编辑,发现新问题(为什么没有加拿大和Shapely和Pyproj的不可靠性)
尽管它不能完全解决问题,但我相信这种态度比使用 pyproc 和 Shapely 更有潜力,而且在 future ,如果你做更多的 Ascii 艺术,会给你更多的可能性和灵活性。首先我会写优点和缺点。
PS:最初我想在您的代码中找到问题,但是我在运行它时遇到了问题,因为 pyproj 返回了一些错误。
优点
1)我能够提取所有点(加拿大确实缺少)并旋转图像
2)处理速度非常快,因此您可以创建动画 Ascii 艺术 .
3)打印一次完成,无需循环
缺点(已知问题,可解决)
1)这种态度显然不能正确转换地理坐标 - 太平面了,它应该看起来更球形
2)我没有花时间试图找出填充边框的解决方案,所以只有边框有'*'。因此这种态度需要找到算法来填充国家。我认为这不应该是问题,因为 JSON 文件包含分隔的国家
3)除了numpy-opencv(您可以使用PIL代替)和Colorama之外,您还需要2个额外的库,因为我的示例是动画的,我需要通过将光标移动到(0,0)而不是使用os.system()来“清理”终端'cls')
4) 我让它只在 中运行 python 3 .在 python 2 中它也可以工作,但我在使用 sys.stdout.buffer 时遇到错误
将终端上的字体大小更改为最低点 所以打印的字符适合终端。字体更小,分辨率更高
动画应该看起来像 map 在“旋转”
我用了一点你的代码来提取数据。步骤在评论中
import json
import sys
import numpy as np
import colorama
import sys
import time
import cv2
#understand terminal_size as how many letters in X axis and how many in Y axis. Sorry not good name
if len(sys.argv)>1:
terminal_size = (int(sys.argv[1]),int(sys.argv[2]))
else:
terminal_size=(230,175)
with open('world-countries.json') as f:
countries = []
minimal = 0 # This can be dangerous. Expecting negative values
maximal = 0 # Expecting bigger values than 0
for feature in json.load(f)['features']: # getting data - I pretend here, that geo coordinates are actually indexes of my numpy array
indexes = np.int16(np.array(feature['geometry']['coordinates'][0])*2)
if indexes.min()<minimal:
minimal = indexes.min()
if indexes.max()>maximal:
maximal = indexes.max()
countries.append(indexes)
countries = (np.array(countries)+np.abs(minimal)) # Transform geo-coordinates to image coordinates
correction = np.abs(minimal) # because geo-coordinates has negative values, I need to move it to 0 - xaxis
colorama.init()
def move_cursor(x,y):
print ("\x1b[{};{}H".format(y+1,x+1))
move = 0 # 'rotate' the globe
for i in range(1000):
image = np.zeros(shape=[maximal+correction+1,maximal+correction+1]) #creating clean image
move -=1 # you need to rotate with negative values
# because negative one are by numpy understood. Positive one will end up with error
for i in countries: # VERY STRANGE,because parsing the json, some countries has different JSON structure
if len(i.shape)==2:
image[i[:,1],i[:,0]+move]=255 # indexes that once were geocoordinates now serves to position the countries in the image
if len(i.shape)==3:
image[i[0][:,1],i[0][:,0]+move]=255
cut = np.where(image==255) # Bounding box
if move == -1: # creating here bounding box - removing empty edges - from sides and top and bottom - we need space. This needs to be done only once
max_x,min_x = cut[0].max(),cut[0].min()
max_y,min_y = cut[1].max(),cut[1].min()
new_image = image[min_x:max_x,min_y:max_y] # the bounding box
new_image= new_image[::-1] # reverse, because map is upside down
new_image = cv2.resize(new_image,terminal_size) # resize so it fits inside terminal
ascii = np.chararray(shape = new_image.shape).astype('|S4') #create container for asci image
ascii[:,:]='' #chararray contains some random letters - dunno why... cleaning it
ascii[:,-1]='\n' #because I pring everything all at once, I am creating new lines at the end of the image
new_image[:,-1]=0 # at the end of the image can be country borders which would overwrite '\n' created one step above
ascii[np.where(new_image>0)]='*' # transforming image array to chararray. Better to say, anything that has pixel value higher than 0 will be star in chararray mask
move_cursor(0,0) # 'cleaning' the terminal for new animation
sys.stdout.buffer.write(ascii) # print into terminal
time.sleep(0.025) # FPS
#Preparation phase
x,y = grayscale.shape
3Dmatrix = np.chararray(shape = [x,y,256])
table = ' ......;;;;;;;###### ...'
for i in range(256):
3Dmatrix[:,:,i] = table[i]
x_indexes = np.arange(x*y)
y_indexes = np.arange(x*y)
chararray_image = np.chararray(shape=[x,y])
# Ready to print
...
shades = grayscale.reshape(x*y)
chararray_image[:,:] = 3Dmatrix[(x_indexes ,y_indexes ,shades)].reshape(x,y)
...
with open('world-countries.json') as f:
countries = []
minimal = 0
maximal = 0
for feature in json.load(f)['features']: # getting data - I pretend here, that geo coordinates are actually indexes of my numpy array
for k in range((len(feature['geometry']['coordinates']))):
indexes = np.int64(np.array(feature['geometry']['coordinates'][k]))
if indexes.min()<minimal:
minimal = indexes.min()
if indexes.max()>maximal:
maximal = indexes.max()
countries.append(indexes)
...
关于python - 创建 ASCII 艺术世界地图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55406036/
无论是谁读到这篇文章,我都感谢您花时间阅读。 本质上,我试图通过调用 x 个方法来生成这个精确的 ASCII 艺术,我个人考虑了 3 个: * * ** ** ***
这太琐碎了,听起来很傻,但请多多包涵。 我以前会画ASCII艺术笑脸similar to this post通过做类似的事情: Console.Write((char)1); 当我在 Windows
这样的图像转换算法是如何工作的? 我想将位图转换为 ASCII 艺术。谁能帮我看看我应该使用哪种算法? . W ,
我正在尝试为 android 制作游戏。我目前已将所有美术资源加载到 drawables 文件夹中,但我的问题是如何实际引用特定资源来渲染它? 我知道每个文件都有一个唯一的@id,我可能必须在onDr
我试图垂直反射(reflect)这门艺术。 示例: 但这是我最终得到的: 代码如下: String reverse; for(int i=1;i=0;j--) // probably the wors
我正在尝试使用 JavaScript 函数在我的网站上获取一些 ASCII 艺术作品,但结果并不是我现在想要的...... 它应该是这样的: 这是我用来尝试实现该目标的代码: function log
我正在尝试创建一个脚本,该脚本将接受用户输入(仅字母)并向用户输出 ASCII 艺术。两种输出方法是水平或垂直。我遇到的问题是如何水平打印字典值。 这是我到目前为止所拥有的: def convert(
下面的代码(用 patorjk.com Text to ASCII Art Generator 生成)给出了预期的结果(“TEST”ASCII 艺术文本): Windows:Firefox、Chrom
我正在尝试像这样打印 ascii 艺术: print(("""\ ._ o o
所以..这是(无论如何对我来说)这个程序最重要的功能。我需要这个才能工作。请不要笑..(好吧你可以笑)但是当我的程序出错时,我希望它显示这个: _ _,---._ ,
我正在尝试输入 ASCII art在 C++ 程序中,并通过手动打印每一行来实现,但结果与 ASCII 艺术完全不同。就像: 出现这种情况是因为提示无法识别字符还是我没有正确操作? 这是我正在尝试做的
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 11 年前。 Improve thi
我有一个很长的多行 ascii 艺术字符串,我想使用 Python curses 模块将其呈现给用户。我对此有点困惑,因为在 curses 中打印字符串的唯一方法是 addstr(y,x,string
目前我正在尝试读取可能包含 ASCII 艺术的 .txt 文件并使用 JQuery 在我的 HTML 文档中显示它们。简单的文本显示正确,但我有艺术格式问题。 我该如何解决这个问题? $(docume
我正在用 optparse 模块制作一个 shell 脚本,只是为了好玩,所以我想打印一个漂亮的 ascii 图来代替描述。 原来这段代码: parser = optparse.OptionParse
我是 python 的新手,把它作为一种兴趣爱好,通过一些搜索,我自己找到了一堆来自“计算实践”的练习,其中一个是关于写作的一个 ASCII 数字,如下所示。 这似乎是一个足够简单的练习,但我似乎无法
这个问题在这里已经有了答案: Render a string in HTML and preserve spaces and linebreaks (7 个答案) 关闭 9 个月前。 我该怎么做才能
我曾经为一项工作做过编程测试,其中涉及用 C# 制作 ASCii 艺术。我在这方面做得并不好,因为我对在 C#(或任何编程知识)中这样做的想法或经验知之甚少。 .NET 中是否有任何值得了解/练习的资
我正在编写一个小程序,想知道是否有办法在 R 中包含 ASCII 艺术。我在 python 中寻找等效的三个引号( """ 或 ''' )。 我尝试使用 cat或 print没有成功。 最佳答案 不幸
因此,对于我的 Java 入门类(class),我想用 ASCII 创建一个 Gingerbread 人。这是第一个作业,所以到目前为止,该类(class)仅涵盖了 println 语句。我在 OSX
我是一名优秀的程序员,十分优秀!