假设您处于受限计算环境中,乘法操作很昂贵或不可用。您可以访问已知尺寸图像的像素流。你如何在图像上画圆圈?
答案 0 :(得分:2)
这是一个Python脚本,演示了如何在不使用乘法的情况下绘制圆。它使用公式x 2 + y 2 > r 2 检查当前像素位置(x,y)是否在圆外。
从the rate of change of the difference between the squares of adjacent pixel indices is 2开始,可以使用加法来维持平方值的运行计算。当您遍历像素时,您将继续向正在运行的“正方形”计算中添加一个数字(称为z
),对于每个像素,您还将向z
添加2。
下面的__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()
此代码创建一个居中的圆圈,如下所示: