如何在不使用外部模块的情况下在Python中打开/创建图像

时间:2018-07-21 16:20:51

标签: python image-processing pypy

我有一个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。

4 个答案:

答案 0 :(得分:2)

您可以编写这样的PPM文件,而无需 OpenCV numpy 或任何讨厌您的内容:-

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)

enter image description here


我也写了一个非常简单的PPM阅读器-它只读取与上面写的匹配的24位P6 PPM文件。我想可以充实处理注释,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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

您可以以与处理文本文件相同的方式打开图像文件。只需适应您的.png图像的约定即可。

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

答案 3 :(得分:0)

基于各种输入(对Mark Setchell的代码片段表示敬意),现在我能够读取rgb值,然后逐个像素地处理它们,然后编写新的图像文件,而无需使用任何外部库。当我开始所有这些工作时,我将CPython与OpenCV和Numpy一起使用,并且运行时间不少于60分钟。然后,我重新编写了没有Numpy或OpenCV的代码,并使用Pypy运行了该代码:仅用了两分钟即可完成!尽管ppm文件的大小与原始jpg相比非常大。 Mark写的ppm部分已解决。他还提出了一种自动处理可变标头的方法(对我来说很豪华...)。这描述了我的过程,只显示了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