在python中,我试图将图像分成多个圆圈并计算每个圆圈中黑色像素的数量。
例如,我有一个用鱼眼镜头拍摄的图像(半球形图像)(如下图所示),我想将该图像划分为小圆圈,以捕获图像的一部分,从中间的小圆圈到整个图片。
一旦我有了圆形图像,我就可以计算每个图像中的像素数。
我尝试过:
Image=Image.new("RGB", (2000,2000))
draw = ImageDraw.Draw(image)
draw.ellipse((20,20,1800,1800),fill(255,255,255)
然后从中创建一个蒙版,但是无论我如何在绘制中更改数字。椭圆形圆圈只会捕获整个图像,但会使图像本身变小。
任何有关解决此问题的想法或建议,将不胜感激!
答案 0 :(得分:2)
您应该在OpenCV中查看此类任务。您可以将圆转换为整个轮廓并计算圆的半径。然后,您可以绘制圆形并将其绘制在蒙版上,然后执行cv2.bitwise_and
在图像上绘制圆形ROI。您可以使用自己选择的整数(在我的情况下为10)的ROI圆的半径进行迭代和运算。希望能帮助到你。干杯!
示例代码:
import cv2
import numpy as np
img = cv2.imread('circle.png')
h, w = img.shape[:2]
mask = np.zeros((h, w), np.uint8)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
kernel = np.ones((10,10),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,kernel, iterations = 2)
_, contours, hierarchy = cv2.findContours(opening,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)
extLeft = tuple(cnt[cnt[:, :, 0].argmin()][0])
extRight = tuple(cnt[cnt[:, :, 0].argmax()][0])
radius = (extRight[0] - extLeft[0])/2
print(extRight[0], extLeft[0])
print(radius)
M = cv2.moments(cnt)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
print(cx, cy)
for i in range(1,30):
if i*10<radius:
print(i*10)
cv2.circle(mask,(cx,cy), i*10, 255, -1)
res = cv2.bitwise_and(img, img, mask=mask)
pixels = np.sum(res == 255)
cv2.putText(res,'Pixel count: '+str(pixels),(30,30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255), 1, cv2.LINE_AA)
cv2.imshow('img', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
else:
res = cv2.bitwise_and(img, img, mask=opening)
pixels = np.sum(res == 255)
cv2.putText(img,'Pixel count: '+str(pixels),(30,30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255), 1, cv2.LINE_AA)
cv2.imshow('img', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
break
结果:
编辑:
尝试使用其他方法计算中间值
import cv2
import numpy as np
img = cv2.imread('circle.png')
h, w = img.shape[:2]
mask = np.zeros((h, w), np.uint8)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
kernel = np.ones((10,10),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,kernel, iterations = 2)
_, contours, hierarchy = cv2.findContours(opening,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)
cv2.imshow('img22', opening)
extLeft = tuple(cnt[cnt[:, :, 0].argmin()][0])
extRight = tuple(cnt[cnt[:, :, 0].argmax()][0])
radius = (extRight[0] - extLeft[0])/2
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
cx = int(x+(w/2))
cy = int(y+h/2)
for i in range(1,30):
if i*10<radius:
print(i*10)
cv2.circle(mask,(cx,cy), i*10, 255, -1)
res = cv2.bitwise_and(img, img, mask=mask)
pixels = np.sum(res == 255)
cv2.putText(res,'Pixel count: '+str(pixels),(30,30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255), 1, cv2.LINE_AA)
cv2.imshow('img', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
else:
res = cv2.bitwise_and(img, img, mask=opening)
pixels = np.sum(res == 255)
cv2.putText(img,'Pixel count: '+str(pixels),(30,30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255), 1, cv2.LINE_AA)
cv2.imshow('img', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
break
编辑2:
好的,所以我从您的第一个示例图像中得出的假设是,您的图像距开始将几乎是一个圆圈。因为不是这样,由于图像非常大,因此您不必以不同的方式计算中心(就像从我的第一次编辑-从边界框算起)并制作更大的内核(40,40)。另外,您必须使i达到范围阈值(例如10000)。这将起作用:
import cv2
import numpy as np
img = cv2.imread('circleroi.jpg')
h, w = img.shape[:2]
mask = np.zeros((h, w), np.uint8)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
kernel = np.ones((40,40),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,kernel, iterations = 2)
_, contours, hierarchy = cv2.findContours(opening,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)
extLeft = tuple(cnt[cnt[:, :, 0].argmin()][0])
extRight = tuple(cnt[cnt[:, :, 0].argmax()][0])
radius = (extRight[0] - extLeft[0])/2
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
cx = int(x+(w/2))
cy = int(y+h/2)
for i in range(1,10000):
if i*10<radius:
cv2.circle(mask,(cx,cy), i*10, 255, -1)
res = cv2.bitwise_and(img, img, mask=mask)
pixels = np.sum(res == 255)
cv2.putText(res,'Pixel count: '+str(pixels),(30,30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255), 1, cv2.LINE_AA)
cv2.imshow('img', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
else:
res = cv2.bitwise_and(img, img, mask=opening)
pixels = np.sum(res == 255)
cv2.putText(img,'Pixel count: '+str(pixels),(30,30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255), 1, cv2.LINE_AA)
cv2.imshow('img', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
break
答案 1 :(得分:1)
如果您对库足够熟悉,那么在纯numpy中做起来最简单:
in_loop = False
for i in range(1, x + 1):
in_loop = True
print(i)
if not in_loop:
raise Exception()
要查看各种数组是什么样的:
# Create some fake data
np.random.seed(100)
fake_im_arr = np.random.randint(low=0, high=2, size=(2000,2000))
# Function definition for creating masks
def create_circle_mask(X_arr, Y_arr, center, radius):
c_x, c_y = center
dists_sqrd = (X_arr - c_x)**2 + (Y_arr - c_y)**2
return dists_sqrd <= radius**2
# Using the two together:
center, radius = (1000, 1000), 5
size_x, size_y = fake_im_arr.shape
mask = create_circle_mask(*np.ogrid[0:size_x, 0:size_y], center=center, radius=radius)
n_black_in_circle = ((fake_im_arr == 1) & mask).sum() # This is your answer (39 in this case)