我的任务是在二值图像中找到正方形的中心,边长和旋转Angular 。此外,我还提供了以下信息:给定一个白色(=True)背景的二进制图像,其中包含一个黑色(=False)旋转的正方形,返回所述正方形的质心(x,y),其边长(l)和其旋转Angular (alpha)。正方形将始终完全包含在图像中,即。它的任何边都不与图像边界相交。返回Angular alpha
(以度为单位),其中0°是直立的,相当于...,-180°,-90°,90°,180°,...,旋转的正方向是逆时针。请注意img
的形状是(高度,宽度),y轴优先(行优先顺序)。这个任务应该只能用标准的numpy函数来解决。
我对numpy不是很熟悉,但我想我可以用下面的代码得到x和y坐标中的正方形的中心和边长:
import numpy
def find_rect(img):
x, y, l, alpha = 0, 0, 0, 0
black_pixels = np.argwhere(img==0)
y, x = np.mean(black_pixels, axis=0)
l = np.sqrt((img==0).sum())
y_max1 = black_pixels[black_pixels[:,1]>= x, 0].max()
y_max2 = black_pixels[black_pixels[:,1]<= x, 0].max()
y_max = max(y_max1, y_max2)
x_max = black_pixels[black_pixels[:, 0] == y_max, 1][0]
alpha = np.degrees(np.arctan(((y_max - y)/(x_max - x))))
return x, y, l, alpha
#the code which generates the square
from scipy.ndimage import rotate
def generate_rot_square(w, h, x, y, l, alpha):
rect = np.ones((l, l))
rect = rotate(rect, alpha)
r_h, r_w = rect.shape
r_h_1 = r_h // 2
r_h_2 = r_h - r_h_1
r_w_1 = r_w // 2
r_w_2 = r_w - r_w_1
result = np.zeros((h, w), dtype=bool)
result[y - r_h_1:y + r_h_2, x - r_w_1:x + r_w_2] = rect > 0.9
return 1 - result
但是,一旦正方形被旋转,如果正方形不再起作用,代码就会得到边长。另外,我真的没有一个关于如何得到广场的旋转Angular 的想法。也许有人能给我给予如何完成这项任务。
1条答案
按热度按时间4dc9hkyq1#
这是相当学者,所以不切实际的(在现实生活中)解决方案可能是预期的。而不是计算机视觉解决方案(使用opencv而不仅仅是numpy)。
例如,既然你确定这是一个正方形,你就知道黑色像素的数量是l²。所以计算黑色像素的数量,并取其平方根
为了求出Angular ,问问你自己,Angular α的ymax应该是多少?找到ymax,就像你做的那样,并从中推导出Angular 。
你必须能够找到Angular ,以区分实际情况,其中ymax发生在第一或第二四边形(或第三/第四,取决于y轴向上或向下。但只有两种情况需要考虑)
因此,计算图像的前半部分(x方向)的ymax 1,另一半的ymax 2
只有最大的一个是相关的。因为较小的一个意味着最大值不是一个角,而是一个边与y轴的交点(好吧,你也可以从这个交点计算,但这更复杂)。
所以,大一点的是角落。从角的位置和
l
可以推导出Angular 。我试过了它不是很精确(对于接近90度的Angular ,误差在5度左右;对于较小的Angular 更好)。即使是我,也是149,当我试着用150的时候。这是因为
>0.9
过滤掉了比它应该过滤掉的更多的像素。因此,如果
>0.9
是一个约束,那么避免依赖l
来计算Angular 可能会更准确。为此,还计算x匹配ymax(警告:这不是一个xmax。只是画一个正方形,看看它是不一样的。它应该是行ymax中唯一的黑色像素:img[ymax].argmin()
。或者,如果有多个黑色像素,则为该行中黑色像素的平均值(但是,除了Angular 0之外,应该只有几个)。那么ymax和x的比值应该与Angular 的tan
有关。我不多说了,因为你只是要小费。
但是,除了我提到的分离(x之前的max,x之后的max),或者角坐标(x匹配ymax,或者同样,冗余地,y匹配xmax)之外,你已经在做的黑色像素的计算(mean,max,min,.)都是你需要的。回想一下,如果一个正方形的圆心是
x₀,y₀
,边长是W
,旋转Angular 是α,那么这些值会是什么。然后把等式反过来。尝试不同的策略:
l
中推导出Angular 。tan(angle)
l
推导出xmax
匹配y
(因此是一个角),并从中推导(也用arctan
)Angular也许你会看到,根据估计的Angular ,一个策略是更准确的,你最终会有一种方法来选择这4个策略中更好的。
还有其他的:ymax-ymin、xmax-xmin也取决于Angular 。所以如果你能告诉它们对于给定的Angular 应该是什么,那么你就可以颠倒公式,从它们的测量值中找到Angular 是什么
编辑
一些关于角落和Angular 的精确度。
在一个正方形里,你有四个角。它们的坐标
(x+W× π 2/2×cos(β),y+W× π 2/2×sin(β))
(x+W× π 2/2×cos(β+90°),y+W× π 2/2×sin(β+90°))
(x+W× π 2/2×cos(β+180°),y+W× π 2/2×sin(β+180°))
(x+W× π 2/2×cos(β+270°),y+W× π 2/2×sin(β+270°))
β开始α+45°,α是你要找的Angular 。对我来说,从角β进行推理更方便,因为角β是我们找到角的地方。所以如果正方形不旋转,α=0,那么β=45°。因此,角的坐标为(x+W ×cos(45°)=x+W× cos 2/2× cos 2/2 = x+W/2,y+W/2
x-W/2,y+W/2
x-W/2,y-W/2
x+W/2,y-W/2
如你所见,这是意料之中的。
如果α=45°,那么β=90°,我们得到x,y+W = 2/2
x-W 2/2,y
x,y-W 2/2
x+W 2/2,y
又一次,正如预期的那样。
我们使用哪个角落并不重要:用途:正如你所说,角模90°有效,显然,角之间由90°的角倍数分隔开
所以,我们只需要找个角落,随便。
如果你看ymax,它是一个角的
y
。除非角α=0,在这种情况下,它是整条边的y
。什么是匹配
x
:它是x
,其中你在行ymax中找到0。例如,您可以通过这种方式找到它(使用
black_pixels
数组)请注意,
black_pixels[black_pixels[:,0]==ymax,1]
返回一个x
数组。所以我只拿第一个(见后面)。同样,直接处理图像,我也可以计算出
它返回
ymax
行中第一个0的索引(在x中,因为我们已经用ymax
索引了第一个轴)。如果该行中没有0,则这两种方法都将失败。但有一个。否则,
ymax
会有所不同。所以,不,你知道一个角,它的坐标是(xc,ymax)。
该点是相对于具有向量(xc-x,ymax-y)的正方形的中心(和旋转中心)。
这个向量的Angular 是
arctan((ymax-y)/(xc-x))
。因为这是你找到一个角的Angular ,我把它叫做β,我们需要去掉45°。所以Angular 是arctan((ymax-y)/(xc-x))-45
。至少如果我们正在工作的角落是在右边。或
90-that
,因为y轴向下。只是玩不同的Angular ,看看如何
arctan((ymax-y)/(xc-x))
演变.完整代码
“证明”它有效
真实的和估计的Angular 重叠得很好。