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