python - 计算数组中的像素

标签 python arrays image matrix

我正在使用二进制 PBM 格式。当我阅读它时,我有一个包含整数的数组,其中整数是字节序数。数组中的每个整数都会转换为 0 和 1 整数的列表作为二进制表示,然后我反转该列表。像素网格从0:0开始,所以第一个像素的位置是[0:0]。

如果 x >= 8,我需要获取像素颜色。如果 x < 8,则一切正常。获取像素颜色的代码。

  def getpixel(self, x, y):
    '''PNMReader.getpixel(x, y) -> int

    Get pixel at coordinates [x:y] and return it as integer.'''
    if not isinstance(x, int) or not isinstance(y, int):
      raise(TypeError('both x and y must be integers'))
    if x < -1 or y < -1:
      raise(ValueError('both x and y are interpreted as in slice notation'))
    if x > (self.width-1):
      raise(ValueError('x cannot be equal or greater than width'))
    if y > (self.height-1):
      raise(ValueError('x cannot be equal or greater than height'))
    width, height = self.width, self.height
    x = (x, width-1)[x == -1]
    y = [y, height-1][y == -1]
    p = (y *height) +x
    width, height = self.width, self.height
    pixels = self._array_
    q = (8, width)[width -8 < 0]
    if x >= q:
      while x % q:
        y += 1
        x -= 1
    from pprint import pprint
    color = bitarray(pixels[y])[::-1][:q][x]
    print(color)
您可以在此处看到的

bitarray 是我定义的函数,用于获取整数位作为列表; self._array_ 是一个整数序列(只是从 PBM 读取的字节序数)。

如果 x >= 8,我需要修复此函数以获取像素颜色。我无法理解在这种情况下如何计算 x 和 y 的偏移量。

只接受快速有效的答案。我不想将所有位连接为一维数组,因为如果图像很大(例如,它可以是 3000x5000 像素),它可能会太慢。

我知道我可以使用一些模块,例如 imagemagickfreeimage 等,但我只能使用标准库(没有其他模块)。我需要没有绑定(bind)或非默认模块的纯 Python 解决方案。

最佳答案

如果 self._array_ 是一个整数数组,每个整数代表原始图像中光栅图像数据的一个字节,那么您可以使用普通的位操作技术提取所需的位。这是详细的解释(根据评论中的要求):

  1. 我们需要每行的宽度(以字节为单位)。这是像素宽度除以 8,但 PBM 格式用最多 7 个虚拟像素填充每行,以使每行具有精确的字节数。因此,我们需要将宽度除以 8 并向上取整,这可以使用如下整数算术来完成:

    row_width = (width + 7) // 8
    
  2. 然后我们需要找到包含我们想要的像素的字节。 PBM 栅格数据按行主序排列,因此 (x, y) 处的像素位于此字节中:

    pixel_byte = self._array_[y * row_width + x // 8]
    
  3. 您可以使用操作 ( 从整数 i 中提取位号 b(从右侧编号,最低有效位编号为 0) i >> b) & 1 (右移 b 位并屏蔽掉最低有效位)。但 PBM 将其像素布置在 big-endian order 中,第一个像素位于字节的最高有效位。所以我们想要的位是位号7 - x % 8:

    (pixel_byte >> (7 - x % 8)) & 1
    

这应该可以解决您眼前的问题。但在我看来,您的代码对于您想要做的事情来说非常复杂。一些评论:

  1. 自己调用 isinstance 并引发 TypeError 是没有意义的,因为当您尝试对参数进行整数运算时,无论如何都会发生这种情况。

  2. x > (self.width-1) 最好写成 x >= self.width

  3. Python 的切片表示法允许任何负整数,而不仅仅是 -1。例如:

    >>> range(10)[-7:-4]
    [3, 4, 5]
    
  4. 您计算了一个数字p,但您没有使用它。

  5. 您导入函数 pprint,然后不调用它。

我会写这样的东西:

import re

class Pbm(object):
    """
    Load a Binary Portable Bitmap (PBM) files and provide access to
    its pixels.  See <http://netpbm.sourceforge.net/doc/pbm.html>
    """
    _pbm_re = re.compile(r'''
       (P4)                     # 1. Magic number
       (?:\s+|\#.*\n)*          # Whitespace or comments
       ([0-9]+)                 # 2. Width of image in pixels
       (?:\s+|\#.*\n)*          # Whitespace or comments
       ([0-9]+)                 # 3. Height of image in pixels
       (?:\#.*\n)*              # Possible comments
       \s                       # A single whitespace character
       ([\000-\377]*)           # 4. Raster image data
    ''', re.X)

    def __init__(self, f):
        m = self._pbm_re.match(f.read())
        if not m:
            raise IOError("Can't parse PBM file.")
        self.width = int(m.group(2))             # Width in pixels
        self.height = int(m.group(3))            # Height in pixels
        self.row = (self.width + 7) // 8         # Width in bytes
        self.raster = m.group(4)
        if len(self.raster) != self.height * self.row:
            raise IOError("Size of raster is {} but width x height = {}."
                          .format(len(self.raster), self.height * self.row))

    def getpixel(self, x, y):
        # Negative coordinates are treated as offsets from the end,
        # like Python's slice indexes.
        if x < 0: x += self.width
        if y < 0: y += self.height
        if x < 0 or x >= self.width or y < 0 or y >= self.height:
            raise ValueError("Coords ({},{}) are out of range (0,0)-({},{})."
                             .format(x, y, self.width - 1, self.height - 1))
        return (ord(self.raster[y * self.row + x // 8]) >> (7 - x % 8)) & 1

关于python - 计算数组中的像素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12426024/

相关文章:

python - 如何测量 Python 导入延迟

html - 是否可以在 IMG 标签中使用 SVG?

android - 将 Picasso 与 Image Getter 结合使用

java - 如何将图库图像作为输入流

python - 性能 SQLAlchemy 和或

python - 从自定义包中导入大量模块

Java将数组传递给构造函数

arrays - 如何在 Rust 中执行高效的向量初始化?

c - 通过在一行中读取数组的大小和数组的元素来将整数存储为数组

python - 列表中最长的字符串