【问题标题】:Reading output from imagemagick subprocess in Python [duplicate]从Python中的imagemagick子进程读取输出[重复]
【发布时间】:2019-02-21 15:48:22
【问题描述】:

我想在 python 中获取文件的平均亮度。阅读了上一个问题 [Problem getting terminal output from ImageMagick's compare.exe ( Either by pipe or Python ) 我想出了:

cmd='/usr/bin/convert {} -format "%[fx:100*image.mean]\n" info: >    bright.txt'.format(full)
subprocess.call(cmd,shell=True)
with open('bright.txt', 'r') as myfile:
    x=myfile.read().replace('\n', '')
return x

上一个问题推荐使用“pythonmagick”,我可以找到它,但没有当前文档,最近的活动也很少。我想不出使用它的语法。

我知道我的代码不能令人满意,但它确实有效。 有没有更好的方法不需要 'shell=true' 或额外的文件处理?

【问题讨论】:

标签: python subprocess imagemagick


【解决方案1】:

您可能可以改进子流程,并使用Popen + PIPE 消除临时文本文件。

cmd=['/usr/bin/convert',
     full,
     '-format',
     '%[fx:100*image.mean]',
     'info:']
pid = subprocess.Popen(cmd,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE)
out, err = pid.communicate()
return float(out)

ImageMagick 还附带 identify 实用程序。同样的方法可以用...实现。

cmd=['/usr/bin/identify', '-format', '%[fx:100*image.mean]', full]

如果值得直接使用 ImageMagick 的共享库,可能值得探索。通常通过 C-API(pythonmagick、wand 等)连接。对于您所做的事情,这只会增加代码复杂性,增加模块依赖性,但绝不会提高性能或准确性。

【讨论】:

  • 没有充分的理由重新实现subprocess.check_output() 或其现代替代品subprocess.run()。一般避免subprocess.Popen(),除非你真的知道自己在做什么。
【解决方案2】:

这似乎对我有用,可以将平均值作为可以打印的变量返回。 (这有点错误。请参阅底部附近的更正)

#!/opt/local/bin/python3.6

import subprocess

cmd = '/usr/local/bin/convert lena.jpg -format "%[fx:100*mean]" info:'

mean=subprocess.call(cmd, shell=True)
print (mean)


结果是70.67860,返回到终端。

如果您解析命令的每个部分,这也适用于 shell=False。

#!/opt/local/bin/python3.6

import subprocess

cmd = ['/usr/local/bin/convert','lena.jpg','-format','%[fx:100*mean]','info:']

mean=subprocess.call(cmd, shell=False)
print (mean)


结果是70.67860,返回到终端。

下面tripleee的评论表明我上面的过程是不正确的,因为平均值显示在终端上,但实际上并没有放入变量中。

他建议使用subprocess.check_output()。以下是他的解决方案。 (谢谢你,三胞胎)

#!/opt/local/bin/python3.6

import subprocess

filename = 'lena.jpg'
mean=subprocess.check_output(
    ['/usr/local/bin/convert',
     filename,
     '-format',
     'mean=%[fx:100*mean]', 
     'info:'], universal_newlines=True)
print (mean)

打印:mean=70.6786

【讨论】:

  • 这不会捕获mean 中的输出,它只是在您尝试print 来自Python 的值之前打印在标准输出上。您想要subprocess.check_output() 或其现代替代品subprocess.run() 而不是subprocess.call()
  • @tripleee。感谢您的更正。我是 Python 的新手。但是我已经在我的帖子中发布了您的解决方案的更正。
  • 添加universal_newlines=True 以接收作为解码字符串的输出。默认情况下,操作系统在 Python 3 中对 bytes 缓冲区执行 I/O。 (或者,decodebytes 对象分开;但这很麻烦,因为您需要指定正确的编码。)
  • b 和引号不是值的一部分,它们只是 Python 的注释,用于消除 repr 版本的歧义。
  • 我不确定您所说的repr version 是什么意思。但是当它有 b 和单引号时,我将如何获取返回的变量并在进一步的计算中使用它?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-10
  • 2019-04-26
  • 2011-01-14
  • 2012-04-06
  • 1970-01-01
  • 2016-08-20
  • 2015-01-20
相关资源
最近更新 更多