我有一个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。
答案 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)
我也写了一个非常简单的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