Python 确定给定图像圆形样本的平均颜色?

Python 确定给定图像圆形样本的平均颜色?,python,image-processing,Python,Image Processing,我试图实现的是类似于photoshop/gimp的滴管工具:对图像中给定区域进行圆形采样,并返回该圆形采样的平均颜色 我发现的最简单的方法是取一个“常规”正方形样本,将其屏蔽为一个圆,然后将其减少到1个像素,但这对CPU的要求非常高(尤其是重复数百万次时) 一种数学上更复杂的方法是,取一个正方形区域,仅对该样本中圆形区域内的像素进行平均,但重复确定哪个像素在该圆形区域内或不在该圆形区域内,同样需要CPU 有没有一种更简洁、对CPU要求更低的方法来实现这一点?这里有一个skimage.draw.c

我试图实现的是类似于photoshop/gimp的滴管工具:对图像中给定区域进行圆形采样,并返回该圆形采样的平均颜色

我发现的最简单的方法是取一个“常规”正方形样本,将其屏蔽为一个圆,然后将其减少到1个像素,但这对CPU的要求非常高(尤其是重复数百万次时)

一种数学上更复杂的方法是,取一个正方形区域,仅对该样本中圆形区域内的像素进行平均,但重复确定哪个像素在该圆形区域内或不在该圆形区域内,同样需要CPU


有没有一种更简洁、对CPU要求更低的方法来实现这一点?

这里有一个
skimage.draw.circle()
的小示例,它实际上并不绘制圆,但提供圆内点的坐标,可用于索引Numpy数组

#!/usr/bin/env python3

import numpy as np
from skimage.io import imsave
from skimage.draw import circle

# Make rectangular canvas of mid-grey
w, h = 200, 100
img = np.full((h, w), 128, dtype=np.uint8)

# Get coordinates of points within a central circle
Ycoords, Xcoords = circle(h//2, w//2, 45)

# Make all points in circle=200, i.e. fill circle with 200
img[Ycoords, Xcoords] = 200

# Get mean of points in circle
print(img[Ycoords, Xcoords].mean())      # prints 200.0

# DEBUG: Save image for checking
imsave('result.png',img)


关键词:Numpy、skimage、scikit image、图像处理、Python、圆、draw、圆内点的坐标、屏蔽平均值。

下面是一个
skimage.draw.circle()的小示例
,它实际上并不绘制圆,但提供圆内点的坐标,可用于索引Numpy数组

#!/usr/bin/env python3

import numpy as np
from skimage.io import imsave
from skimage.draw import circle

# Make rectangular canvas of mid-grey
w, h = 200, 100
img = np.full((h, w), 128, dtype=np.uint8)

# Get coordinates of points within a central circle
Ycoords, Xcoords = circle(h//2, w//2, 45)

# Make all points in circle=200, i.e. fill circle with 200
img[Ycoords, Xcoords] = 200

# Get mean of points in circle
print(img[Ycoords, Xcoords].mean())      # prints 200.0

# DEBUG: Save image for checking
imsave('result.png',img)


关键词:Numpy、skimage、scikit图像、图像处理、Python、圆、绘图、圆内点的坐标、蒙面平均值。

我相信有一种更简洁的方法,但是:

import math
import numpy as np
import imageio as ioimg # as scipy's i/o function is now depreciated
from skimage.draw import circle
import matplotlib.pyplot as plt


# base sample dimensions (rest below calculated on this). 
# Must be an odd number.
wh = 49
# tmp - this placement will be programmed later
dp = 500

#load work image (from same work directory)
img = ioimg.imread('830.jpg')
# convert to numpy array (droppying the alpha while we're at it)
np_img = np.array(img)[:,:,:3]
# take sample of resulting array
sample = np_img[dp:wh+dp, dp:wh+dp]

#==============
# set up numpy circle mask
## this mask will be multiplied against each RGB layer in extracted sample area

# set up basic square array
sample_mask = np.zeros((wh, wh), dtype=np.uint8)
# set up circle centre coords and radius values
xy, r = math.floor(wh/2), math.ceil(wh/2)
# use these values to populate circle area with ones
rr, cc = circle(xy, xy, r)
sample_mask[rr, cc] = 1
# add axis to make array multiplication possible (do I have to do this)
sample_mask = sample_mask[:, :, np.newaxis]

result = sample * sample_mask
# count number of nonzero values (this will be our median divisor)
nz = np.count_nonzero(sample_mask)

sample_color = []
for c in range(result.shape[2]):
    sample_color.append(int(round(np.sum(result[:,:,c])/nz)))


print(sample_color) # will return array like [225, 205, 170]
plt.imshow(result, interpolation='nearest')
plt.show()
也许在这里问这个问题是没有必要的(我已经有一段时间没有编写python了,并且希望从此开发出一些新的库),但我希望这可以作为其他有相同目标的人的参考


此操作将针对数千张图像(扫描页面)的图像中的每个像素执行(有时是数百万次),因此我担心性能问题,但多亏了numpy,此代码速度非常快。

我相信有一种更简洁的方法来实现此操作,但是:

import math
import numpy as np
import imageio as ioimg # as scipy's i/o function is now depreciated
from skimage.draw import circle
import matplotlib.pyplot as plt


# base sample dimensions (rest below calculated on this). 
# Must be an odd number.
wh = 49
# tmp - this placement will be programmed later
dp = 500

#load work image (from same work directory)
img = ioimg.imread('830.jpg')
# convert to numpy array (droppying the alpha while we're at it)
np_img = np.array(img)[:,:,:3]
# take sample of resulting array
sample = np_img[dp:wh+dp, dp:wh+dp]

#==============
# set up numpy circle mask
## this mask will be multiplied against each RGB layer in extracted sample area

# set up basic square array
sample_mask = np.zeros((wh, wh), dtype=np.uint8)
# set up circle centre coords and radius values
xy, r = math.floor(wh/2), math.ceil(wh/2)
# use these values to populate circle area with ones
rr, cc = circle(xy, xy, r)
sample_mask[rr, cc] = 1
# add axis to make array multiplication possible (do I have to do this)
sample_mask = sample_mask[:, :, np.newaxis]

result = sample * sample_mask
# count number of nonzero values (this will be our median divisor)
nz = np.count_nonzero(sample_mask)

sample_color = []
for c in range(result.shape[2]):
    sample_color.append(int(round(np.sum(result[:,:,c])/nz)))


print(sample_color) # will return array like [225, 205, 170]
plt.imshow(result, interpolation='nearest')
plt.show()
也许在这里问这个问题是没有必要的(我已经有一段时间没有编写python了,并且希望从此开发出一些新的库),但我希望这可以作为其他有相同目标的人的参考


此操作将对数千张图像(扫描页面)的图像中的每个像素执行(有时是数百万次),因此我担心性能问题,但多亏了numpy,此代码速度非常快。

创建圆形遮罩对CPU的要求并不高。你在用numpy做这些数值运算吗?如果没有,请这样做。你真的被什么事缠住了吗?只是小屁股?好的,我来试试,谢谢。不,不是被卡住了,但想知道是否有更好的东西在那里。。。我已经有一段时间没有用Python做任何有要求的事情了,我可能正在重新发明一个已经存在的轮子(我仍然找不到)。
skimage.draw.circle()
提供圆内所有点的坐标。。。提示,提示。。。创建一个圆形掩码并不是那么需要CPU。你在用numpy做这些数值运算吗?如果没有,请这样做。你真的被什么事缠住了吗?只是小屁股?好的,我来试试,谢谢。不,不是被卡住了,但想知道是否有更好的东西在那里。。。我已经有一段时间没有用Python做任何有要求的事情了,我可能正在重新发明一个已经存在的轮子(我仍然找不到)。
skimage.draw.circle()
提供圆内所有点的坐标。。。提示,提示。。。上面的方法是可行的,但是当迭代源图像(逐像素)时,速度非常慢(2500 x 4500px的图像需要一个小时)。看起来是时候让cython试试了,以10像素的增量迭代(或者类似的方式,取决于原始图像的大小)。上面的方法是可行的,但是迭代源图像时(逐像素),它的速度非常慢(2500 x 4500px的图像需要一个小时)。看起来是时候让cython试试了,以10像素的增量迭代(或者类似的方式,取决于原始图像的大小)。