从图像生成布尔矩阵

时间:2017-09-14 14:14:36

标签: python numpy python-imaging-library

我试图通过随机选择一个像素来对图像进行分类,然后找到图像中与原始像素颜色空间中的某个欧几里德距离的所有像素。我目前的剧本需要花费相当长的时间。我想知道我是否能够使用这个等式来生成一个布尔矩阵,以便更快地处理图像。

( x-cx ) ^2 + (y-cy) ^2 + (z-cz) ^ 2 < r^2 

以下是我现在使用的代码:

import PIL, glob, numpy, random, math, time


def zone_map(picture, threshold):
    im = PIL.Image.open(picture)
    pix = im.load()
    [width, height] = im.size
    mask = numpy.zeros((width,height))
    while 0 in mask:
        x = random.randint(0, width)
        y = random.randint(0, height)
        if mask[x, y] == 0:
            point = pix[x,y]
            to_average = {(x, y): pix[x, y]}
            start = time.clock()
            for row in range(0, width):
                for column in range(0, height):
                    if euclid_dist(point, pix[row,column]) <= threshold:
                        to_average[(row,column)] = pix[row, column]
            #to_average = in_sphere(pix, point)
            end = time.clock()
            print(end - start)
            to_average_sum = (0, 0, 0)
            for value in to_average.values():
                to_average_sum = tuple_sum(to_average_sum, value)
            average = tuple_divide(to_average_sum, len(to_average.values()))
            for coordinate in to_average.keys():
                pix[coordinate] = average
                mask[coordinate] = 1
                unique, counts = numpy.unique(mask, return_counts=True)
                progress = dict(zip(unique, counts))
                print((progress[1] / progress[0])*100, '%')
    im.save()

    return im

def euclid_dist(tuple1, tuple2):
    """
    Finds euclidian distance between two points in n dimensional sapce
    """
    tot_sq = 0
    for num1, num2 in zip(tuple1, tuple2):
        tot_sq += (num1 + num2)**2
    return math.sqrt(tot_sq)

def tuple_sum(tuple1, tuple2):
    """
    Returns tuple comprised of sums of input tuples 
    """
    sums = []
    for num1, num2 in zip(tuple1, tuple2):
        sums.append(num1 + num2)
    return tuple(sums)

def tuple_divide(tuple1, divisor):
    """
    Divides numerical values of tuples by divisisor, yielding integer results
    """
    quotients = []
    for value in tuple1:
        quotients.append(int(round(value/divisor)))
    return tuple(quotients)

有关如何合并所描述的布尔矩阵的任何信息,或任何其他关于如何加快这一点的想法,将不胜感激。

1 个答案:

答案 0 :(得分:2)

只需将图像加载为numpy数组,然后使用数组操作而不是循环像素:

import numpy as np
import matplotlib.pyplot as plt
import PIL

def zone_map(picture, threshold, show=True):

    with PIL.Image.open(picture) as img:
        rgb = np.array(img, dtype=np.float)

    height, width, _ = rgb.shape

    mask = np.zeros_like(rgb)
    while not np.any(mask):

        # get random pixel
        position = np.random.randint(height), np.random.randint(width)
        color = rgb[position]

        # get euclidean distance of all pixels in colour space
        distance = np.sqrt(np.sum((rgb - color)**2, axis=-1))

        # threshold
        mask = distance < threshold
        if show: # show output
            fig, (ax1, ax2) = plt.subplots(1,2)
            ax1.imshow(rgb.astype(np.uint8))
            ax2.imshow(mask, cmap='gray')
            fig.suptitle('Random color: {}'.format(color))

    return mask

def test():
    zone_map("Lenna.jpg", threshold=20)
    plt.show()

enter image description here