有什么方法可以检查 LSD 的行输出是垂直还是水平
is there any way to check if a line output of LSD is vertical or horizontal
我在 python 和 OpenCV 中使用 LSD: LineSegmentDetector,现在的问题是我想计算检测到的水平线数和检测到的垂直线数。
img = cv2.imread("test/images.jpg")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 100, 200, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
linesL = lsd(gray)
for line in linesL:
x1, y1, x2, y2, width = map(int,line)
length = line_length(x1,y1,x2,y2)
if line[-1]<3:
lines_img = cv2.line(img, (x1,y1), (x2,y2), (0,0,0),1)
show_img(lines_img,"FLD")
线数组[[x1,y1,x2,y2,width],....]
我也尝试过形态学操作和 houghlinesP,但它们表现不佳。
正如您知道端点的坐标,您可以简单地计算直线的斜率
slope = (y2 - y1) / (x2 - x1)
如果斜率为0,那么直线是水平的,如果是无穷大,那么直线是垂直的。
在实践中,您很少会有等于 0 或无穷大的斜率。所以简单地设置一个阈值:
if abs(slope) < 1:
print("It's an horizontal line!")
elif abs(slope) > 100:
print("It's a vertical line!")
else:
print("It's... a line!")
如果您真的只关心水平线和垂直线,另一个简单的解决方案是比较 x 值和 y 值:
if abs(x1 - x2) < 5:
print("It's a vertical line!")
elif abs(y1 - y2) < 5:
print("It's an horizontal line!")
else:
print("It's... a line!")
编辑:我在斜率比较中添加了绝对值。
我们可以用斜率来解决这个问题。我们知道角度线的斜率是 y
s 和 x
s
之差的比率 arctan
slope_as_angle = atan((y1 - y2) / (x1 - x2))
最好使用 atan2
而不是 atan
。为简单起见,我们使用度数代替弧度:
slope_as_angle = math.degrees(math.atan2((y1 - y2), (x1 - x2)))
现在让我们看看线条在不同倾斜角度下的样子:
for i in range(0, 360, 20):
x = 10 * math.cos(math.radians(i))
y = 10 * math.sin(math.radians(i))
spl = math.degrees(math.atan2(y - 0, x - 0)) % 360
plt.plot([0, x], [0, y], label=str(i))
plt.legend()
plt.show()
请注意,我们正在获取 (0, 0) 和 (cos
、sin
) 之间的所有线的倾斜角(参见:Cartesian to Polar),每个 20 degrees
.
现在我们需要一个逻辑来理解给定倾斜角的线是垂直的还是水平的:
水平
我会说倾斜角在 [160, 200] 或大于 340 或小于 20 之间的每条线都是水平的。
if 160 < angle < 200 or 340 < angle or angle < 20
更好的方法:
if 160 < angle < 200 or not 20 < angle < 340
垂直
我会说倾斜角在 [60, 120] 或 [240, 300] 之间的每条线都是垂直的。
if 60< angle < 120 or 240 < angle < 300.
让我们指定一个极限变量作为阈值,以便我们可以随意更改它:
对于水平线:
if (not limit < spl <= 360 - limit) or (180 - limit <= spl < 180 + limit):
垂直线:
if (90 - limit < spl < 90 + limit) or (270 - limit < spl < 270 + limit):
要检查的代码是:
def check_the_line(slope, limit=10):
if (not limit < spl <= 360 - limit) or (180 - limit <= spl < 180 + limit):
return "h"
elif (90 - limit < spl < 90 + limit) or (270 - limit < spl < 270 + limit):
return "v"
return "o"
让我们验证一下:
import math
from matplotlib import pyplot as plt
fig, (ax1, ax2, ax3) = plt.subplots(3, 1)
limit = 10
def check_the_line(slope, limit=10):
if (not limit < spl <= 360 - limit) or (180 - limit <= spl < 180 + limit):
return "h"
elif (90 - limit < spl < 90 + limit) or (270 - limit < spl < 270 + limit):
return "v"
return "o"
for i in range(0, 360, 1):
x = 10 * math.cos(math.radians(i))
y = 10 * math.sin(math.radians(i))
spl = math.degrees(math.atan2(y, x)) % 360
ax1.plot([0, x], [0, y])
if check_the_line(spl, limit=limit) == "h":
ax2.plot([0, x], [0, y])
elif check_the_line(spl, limit=limit) == "v":
ax3.plot([0, x], [0, y])
ax1.set_title("All lines")
ax1.set_xlim([-10, 10])
ax1.set_ylim([-10, 10])
ax2.set_title("Horizontal Lines")
ax2.set_xlim([-10, 10])
ax2.set_ylim([-10, 10])
ax3.set_title("Vertical Lines")
ax3.set_xlim([-10, 10])
ax3.set_ylim([-10, 10])
plt.show()
我在 python 和 OpenCV 中使用 LSD: LineSegmentDetector,现在的问题是我想计算检测到的水平线数和检测到的垂直线数。
img = cv2.imread("test/images.jpg")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 100, 200, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
linesL = lsd(gray)
for line in linesL:
x1, y1, x2, y2, width = map(int,line)
length = line_length(x1,y1,x2,y2)
if line[-1]<3:
lines_img = cv2.line(img, (x1,y1), (x2,y2), (0,0,0),1)
show_img(lines_img,"FLD")
线数组[[x1,y1,x2,y2,width],....]
我也尝试过形态学操作和 houghlinesP,但它们表现不佳。
正如您知道端点的坐标,您可以简单地计算直线的斜率
slope = (y2 - y1) / (x2 - x1)
如果斜率为0,那么直线是水平的,如果是无穷大,那么直线是垂直的。 在实践中,您很少会有等于 0 或无穷大的斜率。所以简单地设置一个阈值:
if abs(slope) < 1:
print("It's an horizontal line!")
elif abs(slope) > 100:
print("It's a vertical line!")
else:
print("It's... a line!")
如果您真的只关心水平线和垂直线,另一个简单的解决方案是比较 x 值和 y 值:
if abs(x1 - x2) < 5:
print("It's a vertical line!")
elif abs(y1 - y2) < 5:
print("It's an horizontal line!")
else:
print("It's... a line!")
编辑:我在斜率比较中添加了绝对值。
我们可以用斜率来解决这个问题。我们知道角度线的斜率是 y
s 和 x
s
arctan
slope_as_angle = atan((y1 - y2) / (x1 - x2))
最好使用 atan2
而不是 atan
。为简单起见,我们使用度数代替弧度:
slope_as_angle = math.degrees(math.atan2((y1 - y2), (x1 - x2)))
现在让我们看看线条在不同倾斜角度下的样子:
for i in range(0, 360, 20):
x = 10 * math.cos(math.radians(i))
y = 10 * math.sin(math.radians(i))
spl = math.degrees(math.atan2(y - 0, x - 0)) % 360
plt.plot([0, x], [0, y], label=str(i))
plt.legend()
plt.show()
请注意,我们正在获取 (0, 0) 和 (cos
、sin
) 之间的所有线的倾斜角(参见:Cartesian to Polar),每个 20 degrees
.
现在我们需要一个逻辑来理解给定倾斜角的线是垂直的还是水平的:
水平
我会说倾斜角在 [160, 200] 或大于 340 或小于 20 之间的每条线都是水平的。
if 160 < angle < 200 or 340 < angle or angle < 20
更好的方法:
if 160 < angle < 200 or not 20 < angle < 340
垂直
我会说倾斜角在 [60, 120] 或 [240, 300] 之间的每条线都是垂直的。
if 60< angle < 120 or 240 < angle < 300.
让我们指定一个极限变量作为阈值,以便我们可以随意更改它:
对于水平线:
if (not limit < spl <= 360 - limit) or (180 - limit <= spl < 180 + limit):
垂直线:
if (90 - limit < spl < 90 + limit) or (270 - limit < spl < 270 + limit):
要检查的代码是:
def check_the_line(slope, limit=10):
if (not limit < spl <= 360 - limit) or (180 - limit <= spl < 180 + limit):
return "h"
elif (90 - limit < spl < 90 + limit) or (270 - limit < spl < 270 + limit):
return "v"
return "o"
让我们验证一下:
import math
from matplotlib import pyplot as plt
fig, (ax1, ax2, ax3) = plt.subplots(3, 1)
limit = 10
def check_the_line(slope, limit=10):
if (not limit < spl <= 360 - limit) or (180 - limit <= spl < 180 + limit):
return "h"
elif (90 - limit < spl < 90 + limit) or (270 - limit < spl < 270 + limit):
return "v"
return "o"
for i in range(0, 360, 1):
x = 10 * math.cos(math.radians(i))
y = 10 * math.sin(math.radians(i))
spl = math.degrees(math.atan2(y, x)) % 360
ax1.plot([0, x], [0, y])
if check_the_line(spl, limit=limit) == "h":
ax2.plot([0, x], [0, y])
elif check_the_line(spl, limit=limit) == "v":
ax3.plot([0, x], [0, y])
ax1.set_title("All lines")
ax1.set_xlim([-10, 10])
ax1.set_ylim([-10, 10])
ax2.set_title("Horizontal Lines")
ax2.set_xlim([-10, 10])
ax2.set_ylim([-10, 10])
ax3.set_title("Vertical Lines")
ax3.set_xlim([-10, 10])
ax3.set_ylim([-10, 10])
plt.show()