Как нарисовать закрашенный круг без умножения? - PullRequest
1 голос
/ 16 декабря 2011

Скажите, что вы находитесь в ограниченной вычислительной среде, где операция умножения дорогая или недоступна.У вас есть доступ к потоку пикселей для изображения известных размеров.Как бы вы нарисовали наложение круга на изображение?

Ответы [ 2 ]

2 голосов
/ 18 декабря 2011

Известный алгоритм окружности средней точки рисует окружность, используя только сложение и вычитание.

2 голосов
/ 16 декабря 2011

Вот скрипт Python, который демонстрирует, как нарисовать круг без умножения. Он использует формулу x 2 + y 2 > r 2 , чтобы проверить, находится ли текущая позиция пикселя (x, y) вне круга.

Можно поддерживать текущее вычисление квадратов значений, используя сложение , поскольку скорость изменения разности квадратов соседних индексов пикселей составляет 2 . Итерируя по пикселям, вы будете продолжать добавлять число (назовите этот номер z) к своим вычислениям "квадратов", и для каждого пикселя вы также добавите 2 к z.

Функция __init__ ниже содержит некоторые операции умножения. Однако, если размеры изображения постоянны, компилятор выполнит умножение и загрузит только результат на устройство. Если размеры изображения не являются постоянными, «медленное» умножение необходимо выполнять только один раз при запуске, а не один раз на пиксель.

#!/usr/bin/env python

class CircularMaskGenerator:
    '''Generates a circular "mask" for an image.
    Maintains a running computation of squared values to eliminate the need for multiplication'''

    def __init__(self, w, h):
        self.image_width = w
        self.image_height = h

        # Precompute some important values.
        # The embedded device doesn't actaully have to do this math; the
        # compiler does it before loading the code onto the device.

        self.half_image_width = self.image_width >> 1
        self.half_image_height = self.image_height >> 1
        self.radius = self.half_image_height

        self.squared_half_image_width = self.half_image_width*self.half_image_width
        self.squared_half_image_height = self.half_image_height*self.half_image_height
        self.squared_radius = self.radius*self.radius

        # The "deltas" are the difference between the squared values of adjacent pixel indices.
        self.initial_x_squared_delta = 1 - self.image_width
        self.initial_y_squared_delta = 1 - self.image_height

        self.resetFrame()

    def resetFrame(self):

        # Start with a white binary image
        import Image
        self.image = Image.new("1", (self.image_width, self.image_height), 1)
        self.pixels = self.image.load()

        # Reset indices
        self.resetColumnIndex()
        self.resetRowIndex()

    def processPixel(self):

        # Write a black pixel if we're outside the circle
        if self.current_x_squared + self.current_y_squared > self.squared_radius:
            self.pixels[(self.current_column_index, self.current_row_index)] = 0

        self.updateIndices()

    def updateIndices(self):
        '''Update the indices and squares values'''

        self.incrementColumnIndex()

        # Wrap to the next row if necessary
        if self.current_column_index == self.image_width:
            self.incrementRowIndex()

            # Wrap to the next frame if necessary
            if self.current_row_index == self.image_height:
                self.writeImage()
                self.resetFrame()

    def incrementColumnIndex(self):
        self.current_column_index += 1
        self.current_x_squared += self.current_x_squared_delta
        self.current_x_squared_delta += 2

    def resetColumnIndex(self):
        self.current_column_index = 0
        self.current_x_squared = self.squared_half_image_width
        self.current_x_squared_delta = self.initial_x_squared_delta

    def incrementRowIndex(self):
        '''The row increment has to send the column index back to the left.'''

        self.resetColumnIndex()

        self.current_row_index += 1
        self.current_y_squared += self.current_y_squared_delta
        self.current_y_squared_delta += 2

    def resetRowIndex(self):
        self.current_row_index = 0
        self.current_y_squared = self.squared_half_image_height
        self.current_y_squared_delta = self.initial_y_squared_delta

    def writeImage(self):
        '''Save the image in PNG format in the current directory'''
        self.image.save("output.png", "PNG")

# =============================================================================
def simulate_system():

    image_width = 800
    image_height = 600

    # initialize the system
    circle_processor = CircularMaskGenerator(image_width, image_height)

    # supply a pixel stream to drive the system
    for i in xrange(image_width*image_height):
        circle_processor.processPixel()

# =============================================================================
if __name__ == "__main__":
    simulate_system()

Этот код создает центрированный круг примерно так:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...