【问题标题】:How to open/create images in Python without using external modules如何在不使用外部模块的情况下在 Python 中打开/创建图像
【发布时间】:2018-07-24 08:22:35
【问题描述】:

我有一个 python 脚本,它使用 OpenCV 打开一个图像文件(.png 或 .ppm),然后将所有 RGB 值加载到一个多维 Python 数组(或列表)中,仅在 Python 数组上执行一些逐像素计算(此阶段根本不使用 OpenCV),然后使用新创建的数组(包含新的 RGB 值)再次使用 OpenCV 写入新的图像文件(此处为.png)。此脚本中根本不使用 Numpy。该程序运行良好。

问题是如何在不使用任何外部库的情况下做到这一点,无论它们是否用于图像处理(例如 OpenCV、Numpy、Scipy、Pillow 等)。总而言之,我需要使用简单的 Python 内部模块来: 1. 打开图像并读取 RGB 值和 2. 从预先计算的 RGB 值写入新图像。为此,我将使用 Pypy 而不是 CPython,以加快速度。 注意:如果重要的话,我使用的是 Windows 10。

【问题讨论】:

  • 查看要执行的操作的库的源代码。
  • 嗯?首先你说 OpenCV 没有被使用,然后你说它又被使用了。哪个?
  • 你需要同时读写PPMPNG,还是两者都足够好?
  • OpenCV 不用于“此阶段”,即用于 Python 数组的计算...

标签: python image-processing pypy


【解决方案1】:

你可以在没有 OpenCVnumpy 或任何讨厌你的东西的情况下编写这样的PPM 文件:-

import array
width,height = 800,600

PPMheader = 'P6\n' +str(width) + ' ' +str(height) + '\n255\n'

# Create and fill a red PPM image
image = array.array('B', [255, 0, 0] * width * height)

# Save as PPM image
with open('result.ppm', 'wb') as f:
   f.write(bytearray(PPMheader, 'ascii'))
   image.tofile(f)


我也编写了一个非常简单的 PPM 阅读器 - 它只读取与上面编写的文件匹配的 24 位 P6 PPM 文件。我想它可以充实处理 cmets、16 位数据和灰度数据,但这是一个开始:

#!/usr/local/bin/python3
import array

def ppmread(filename):
    with open(filename, 'rb') as f:
        # Read first line - expecting "P6"
        line = f.readline().decode('latin-1')
        if not line.startswith('P6'):
           print("ERROR: Expected PPM file to start with P6")
           return False

        # Read second line - expecting "width height"
        line = f.readline().decode('latin-1')
        dims = line.split()
        width,height=int(dims[0]),int(dims[1])

        # Read third line - expecting "255"
        line = f.readline().decode('latin-1')
        if not line.startswith('255'):
           print("ERROR: Expected 8-bit PPM with MAXVAL=255")
           return False

        image= f.read(width*height*3)

ppmread('test.ppm')

在终端中使用 ImageMagick 将 PPM 转换为 PNG 或 JPEG:

convert result.ppm -auto-level image.png

或者:

convert result.ppm -resize 1024x768 image.jpg

同样,在终端中使用 ImageMagick 将 JPEG 转换为 PPM:

convert image.jpg -depth 8 image.ppm

【讨论】:

  • 我们现在已经到了某个地方......在我复制粘贴您的代码后,我有 Traceback(最近一次调用最后一次):文件“”,第 1 行,在 中open('result.ppm', 'wb') as f: PermissionError: [Errno 13] Permission denied: 'result.ppm'
  • 你需要在可以写入的目录中运行。
  • 一旦我退出 Shell 并将其作为新文件打开,它就可以工作了。这是一个好的开始。我仍然需要弄清楚如何从图像中读取 RGB 值...
  • 不,读取我已经用相机拍摄的任意图像的 RGB 值。如果 .ppm 格式在没有外部库的 Python(或 Pypy)中最容易处理,我可以将几乎任何图像转换为 .ppm(使用 Gimp)。
  • 是的,我写了 6 行?
【解决方案2】:

使用简单的 .ppm 文件很简单:你有三行文本(P6、“宽度高度”、255),然后你有3*width*height RGB 字节。只要您不需要更复杂的 .ppm 格式变体,您就可以分别用 5 行代码编写加载程序和保存程序。

【讨论】:

  • Armin,我问这个问题的原因正是因为我无法弄清楚“5行代码”的事情。你能给我一个关于我应该使用的主要模块的提示吗(它是操作系统吗?)。有趣的是,在我问这个问题之前,我在 youtube 上观看了一些关于 Pypy 的 EuroPython 演示文稿,试图弄清楚如何让 Pypy 识别所有外部库,包括 OpenCV ......没有成功,因此我决定消除外部库来自 Pypy 代码。谢谢。
  • @NP1:如果您在阅读 PPM 文件时遇到问题,请在您的代码中发布一个新问题,并解释为什么您无法让它工作。您可能会失望地得知,没有任何外部库读取 PNG 需要超过 5 行代码,而且对于 Stack Overflow 的答案来说可能过于宽泛。
  • 您不需要任何模块。您只需打开文件(以二进制模式),从中读取三行并获取宽度和高度,然后读取所有剩余数据并获取 RGB 值数组(作为单个字节串)
【解决方案3】:

基于各种输入(对 Mark Setchell 的代码 sn-ps 表示敬意),现在我能够读取 rgb 值,然后逐像素处理它们,然后编写一个新的图像文件,所有这些都无需使用任何外部图书馆。当我开始这一切时,我将 CPython 与 OpenCV 和 Numpy 一起使用,运行时间不少于 60 分钟。然后我在没有 Numpy 或 OpenCV 的情况下重新编写了代码并使用 Pypy 运行它:只花了两分钟就完成了!尽管与原始 jpg 相比,ppm 文件的大小非常大。 Mark 解决了 write-ppm 部分。他还提出了一种自动处理可变标题的方法(对我来说很奢侈......)。这描述了我的过程,只显示了 read-ppm 部分(我相信它可以进一步清理):

# have image file as png, bmp, jpg etc. and open in GIMP.
# from GIMP, export the image file as myPicture.ppm (use ASCII option, not RAW).
# examine the header of the ppm file to find the exact locations of the width, height and maxvalue. Used Notepad.

# Python code
# BEGIN read the ppm image
h_ind=9; w_ind=8; mval_ind=10 #indexes for height, width, maxval in the ppm header
with open('myPicture.ppm','r') as ppm: # open the ppm file
    data=ppm.read()
values=data.split()
for i in range(mval_ind,len(values)):
    values[i]=int(values[i]) # convert rgb data from string to int for later numeric processing
height=int(values[h_ind]); width=int(values[w_ind]); mval=int(values[mval_ind]) # read height, width, maxvalue
rgb0 = [tuple(values[i:i+3]) for i in range(mval_ind+1, len(values), 3)] # contains all rgb values as integers
# END read the ppm image

【讨论】:

    【解决方案4】:

    您可以像打开文本文件一样打开图像文件。只需适应 .png 图像的约定即可。

    对于 PNG,请查看 https://fr.wikipedia.org/wiki/Portable_Network_Graphics 并相应地读取块

    【讨论】:

      猜你喜欢
      • 2014-07-25
      • 2021-11-08
      • 2018-08-12
      • 2015-12-28
      • 1970-01-01
      • 2019-11-16
      • 1970-01-01
      • 1970-01-01
      • 2021-07-03
      相关资源
      最近更新 更多