计算正方形周围的框
calculate box around square
我想检测图像中的正方形,如下所示:
我想通过在正方形角周围绘制一种 3 维 框来突出正方形,如下图所示:
我如何精确计算所有线坐标以便稍后绘制“3 维”框? (给出的是黑色方块的4个角点)
注意:您可以在此处找到我想要实现的目标的视频https://www.youtube.com/watch?v=oSq9V2b5AZ8。
如果你愿意帮助我,如果你分享一些代码行如何计算 4 个缺失点以及如何知道哪些点匹配在一起以从 startPoint(x,y) 画一条线,我会非常高兴到端点(x,y)。例如 js 中的某些行会有很大帮助 :)
首先找到轮廓,然后 select 极值点。然后指定新的 3D 角并使用 cv2.line().
绘制它们
示例:
import cv2
import numpy as np
import imutils
image = cv2.imread('3d2.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.threshold(gray, 190, 255, cv2.THRESH_BINARY)[1]
cv2.bitwise_not(thresh, thresh)
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
c = max(cnts, key=cv2.contourArea)
extLeft = tuple(c[c[:, :, 0].argmin()][0])
extRight = tuple(c[c[:, :, 0].argmax()][0])
extTop = tuple(c[c[:, :, 1].argmin()][0])
extBot = tuple(c[c[:, :, 1].argmax()][0])
leftx = int(extLeft[0])
lefty = int(extLeft[1]) - 90
rightx = int(extRight[0])
righty = int(extRight[1]) -90
topx = int(extTop[0])
topy = int(extTop[1]) -90
bottomx = int(extBot[0])
bottomy = int(extBot[1]) -90
leftc = (leftx, lefty)
rightc = (rightx, righty)
topc = (topx, topy)
bottomc = (bottomx, bottomy)
line = cv2.line(image, extLeft, leftc, (0,255,0), 2)
line = cv2.line(image, extRight, rightc, (0,255,0), 2)
line = cv2.line(image, extTop, topc, (0,255,0), 2)
line = cv2.line(image, extBot, bottomc, (0,255,0), 2)
line = cv2.line(image, bottomc, leftc, (0,255,0), 2)
line = cv2.line(image, rightc, topc, (0,255,0), 2)
line = cv2.line(image, leftc, topc, (0,255,0), 2)
line = cv2.line(image, rightc, topc, (0,255,0), 2)
line = cv2.line(image, bottomc, rightc, (0,255,0), 2)
cv2.drawContours(image, [c], -1, (0,255,0), 2)
cv2.imshow("Image", image)
cv2.imwrite('3Dbox1.png', image)
cv2.waitKey(0)
结果:
您当然可以按照自己的意愿制作新的点(例如,如果您想要与图片中的相同,请给出 x+50 和 y-150):
编辑:
要使框旋转,请尝试使用可以从 cv2.minAreaRect() 函数获得的角度,如下所示:
import cv2
import numpy as np
import imutils
cap = cv2.VideoCapture(0)
while True:
try:
ret, image = cap.read()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.threshold(gray, 190, 255, cv2.THRESH_BINARY)[1]
#cv2.bitwise_not(thresh, thresh)
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
c = max(cnts, key=cv2.contourArea)
rect = cv2.minAreaRect(c)
angle = rect[2]
extLeft = tuple(c[c[:, :, 0].argmin()][0])
extRight = tuple(c[c[:, :, 0].argmax()][0])
extTop = tuple(c[c[:, :, 1].argmin()][0])
extBot = tuple(c[c[:, :, 1].argmax()][0])
if angle < 0:
leftx = int(extLeft[0]) - int(angle)
lefty = int(extLeft[1]) - 50 + int(angle)
rightx = int(extRight[0]) - int(angle)
righty = int(extRight[1]) -50 + int(angle)
topx = int(extTop[0]) - int(angle)
topy = int(extTop[1]) -50 + int(angle)
bottomx = int(extBot[0]) - int(angle)
bottomy = int(extBot[1]) -50 + int(angle)
leftc = (leftx, lefty)
rightc = (rightx, righty)
topc = (topx, topy)
bottomc = (bottomx, bottomy)
line = cv2.line(image, extLeft, leftc, (0,255,0), 2)
line = cv2.line(image, extRight, rightc, (0,255,0), 2)
line = cv2.line(image, extTop, topc, (0,255,0), 2)
line = cv2.line(image, extBot, bottomc, (0,255,0), 2)
line = cv2.line(image, bottomc, leftc, (0,255,0), 2)
line = cv2.line(image, rightc, topc, (0,255,0), 2)
line = cv2.line(image, leftc, topc, (0,255,0), 2)
line = cv2.line(image, rightc, topc, (0,255,0), 2)
line = cv2.line(image, bottomc, rightc, (0,255,0), 2)
cv2.drawContours(image, [c], -1, (0,255,0), 2)
elif angle > 0:
leftx = int(extLeft[0]) + int(angle)
lefty = int(extLeft[1]) + 50 + int(angle)
rightx = int(extRight[0]) + int(angle)
righty = int(extRight[1]) +50 + int(angle)
topx = int(extTop[0]) + int(angle)
topy = int(extTop[1]) +50 + int(angle)
bottomx = int(extBot[0]) + int(angle)
bottomy = int(extBot[1]) +50 + int(angle)
leftc = (leftx, lefty)
rightc = (rightx, righty)
topc = (topx, topy)
bottomc = (bottomx, bottomy)
line = cv2.line(image, extLeft, leftc, (0,255,0), 2)
line = cv2.line(image, extRight, rightc, (0,255,0), 2)
line = cv2.line(image, extTop, topc, (0,255,0), 2)
line = cv2.line(image, extBot, bottomc, (0,255,0), 2)
line = cv2.line(image, bottomc, leftc, (0,255,0), 2)
line = cv2.line(image, rightc, topc, (0,255,0), 2)
line = cv2.line(image, leftc, topc, (0,255,0), 2)
line = cv2.line(image, rightc, topc, (0,255,0), 2)
line = cv2.line(image, bottomc, rightc, (0,255,0), 2)
cv2.drawContours(image, [c], -1, (0,255,0), 2)
except:
pass
cv2.imshow("Image", image)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
如果您的照片是等轴测视图,这将简化为以下问题:
您想找到对应于立方体的三个正交边的三个向量的测量值。
边 1:(X1,Y1,Z1)
Edge2: (X2, Y2, Z2)
Edge3: (X3, Y3, Z3)
根据您的图像,您可以测量其中两个向量的 X 和 Y 值,留下 5 个未知值。
由于所有三个边都是正交的,因此您也知道它们的点积为零。
最后,由于您处理的是立方体,所以您知道每个向量都具有相同的大小。
这给了你五个方程来求解五个未知变量,它可以唯一标识一个解。
我想检测图像中的正方形,如下所示:
我想通过在正方形角周围绘制一种 3 维 框来突出正方形,如下图所示:
我如何精确计算所有线坐标以便稍后绘制“3 维”框? (给出的是黑色方块的4个角点)
注意:您可以在此处找到我想要实现的目标的视频https://www.youtube.com/watch?v=oSq9V2b5AZ8。
如果你愿意帮助我,如果你分享一些代码行如何计算 4 个缺失点以及如何知道哪些点匹配在一起以从 startPoint(x,y) 画一条线,我会非常高兴到端点(x,y)。例如 js 中的某些行会有很大帮助 :)
首先找到轮廓,然后 select 极值点。然后指定新的 3D 角并使用 cv2.line().
绘制它们示例:
import cv2
import numpy as np
import imutils
image = cv2.imread('3d2.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.threshold(gray, 190, 255, cv2.THRESH_BINARY)[1]
cv2.bitwise_not(thresh, thresh)
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
c = max(cnts, key=cv2.contourArea)
extLeft = tuple(c[c[:, :, 0].argmin()][0])
extRight = tuple(c[c[:, :, 0].argmax()][0])
extTop = tuple(c[c[:, :, 1].argmin()][0])
extBot = tuple(c[c[:, :, 1].argmax()][0])
leftx = int(extLeft[0])
lefty = int(extLeft[1]) - 90
rightx = int(extRight[0])
righty = int(extRight[1]) -90
topx = int(extTop[0])
topy = int(extTop[1]) -90
bottomx = int(extBot[0])
bottomy = int(extBot[1]) -90
leftc = (leftx, lefty)
rightc = (rightx, righty)
topc = (topx, topy)
bottomc = (bottomx, bottomy)
line = cv2.line(image, extLeft, leftc, (0,255,0), 2)
line = cv2.line(image, extRight, rightc, (0,255,0), 2)
line = cv2.line(image, extTop, topc, (0,255,0), 2)
line = cv2.line(image, extBot, bottomc, (0,255,0), 2)
line = cv2.line(image, bottomc, leftc, (0,255,0), 2)
line = cv2.line(image, rightc, topc, (0,255,0), 2)
line = cv2.line(image, leftc, topc, (0,255,0), 2)
line = cv2.line(image, rightc, topc, (0,255,0), 2)
line = cv2.line(image, bottomc, rightc, (0,255,0), 2)
cv2.drawContours(image, [c], -1, (0,255,0), 2)
cv2.imshow("Image", image)
cv2.imwrite('3Dbox1.png', image)
cv2.waitKey(0)
结果:
您当然可以按照自己的意愿制作新的点(例如,如果您想要与图片中的相同,请给出 x+50 和 y-150):
编辑:
要使框旋转,请尝试使用可以从 cv2.minAreaRect() 函数获得的角度,如下所示:
import cv2
import numpy as np
import imutils
cap = cv2.VideoCapture(0)
while True:
try:
ret, image = cap.read()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.threshold(gray, 190, 255, cv2.THRESH_BINARY)[1]
#cv2.bitwise_not(thresh, thresh)
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
c = max(cnts, key=cv2.contourArea)
rect = cv2.minAreaRect(c)
angle = rect[2]
extLeft = tuple(c[c[:, :, 0].argmin()][0])
extRight = tuple(c[c[:, :, 0].argmax()][0])
extTop = tuple(c[c[:, :, 1].argmin()][0])
extBot = tuple(c[c[:, :, 1].argmax()][0])
if angle < 0:
leftx = int(extLeft[0]) - int(angle)
lefty = int(extLeft[1]) - 50 + int(angle)
rightx = int(extRight[0]) - int(angle)
righty = int(extRight[1]) -50 + int(angle)
topx = int(extTop[0]) - int(angle)
topy = int(extTop[1]) -50 + int(angle)
bottomx = int(extBot[0]) - int(angle)
bottomy = int(extBot[1]) -50 + int(angle)
leftc = (leftx, lefty)
rightc = (rightx, righty)
topc = (topx, topy)
bottomc = (bottomx, bottomy)
line = cv2.line(image, extLeft, leftc, (0,255,0), 2)
line = cv2.line(image, extRight, rightc, (0,255,0), 2)
line = cv2.line(image, extTop, topc, (0,255,0), 2)
line = cv2.line(image, extBot, bottomc, (0,255,0), 2)
line = cv2.line(image, bottomc, leftc, (0,255,0), 2)
line = cv2.line(image, rightc, topc, (0,255,0), 2)
line = cv2.line(image, leftc, topc, (0,255,0), 2)
line = cv2.line(image, rightc, topc, (0,255,0), 2)
line = cv2.line(image, bottomc, rightc, (0,255,0), 2)
cv2.drawContours(image, [c], -1, (0,255,0), 2)
elif angle > 0:
leftx = int(extLeft[0]) + int(angle)
lefty = int(extLeft[1]) + 50 + int(angle)
rightx = int(extRight[0]) + int(angle)
righty = int(extRight[1]) +50 + int(angle)
topx = int(extTop[0]) + int(angle)
topy = int(extTop[1]) +50 + int(angle)
bottomx = int(extBot[0]) + int(angle)
bottomy = int(extBot[1]) +50 + int(angle)
leftc = (leftx, lefty)
rightc = (rightx, righty)
topc = (topx, topy)
bottomc = (bottomx, bottomy)
line = cv2.line(image, extLeft, leftc, (0,255,0), 2)
line = cv2.line(image, extRight, rightc, (0,255,0), 2)
line = cv2.line(image, extTop, topc, (0,255,0), 2)
line = cv2.line(image, extBot, bottomc, (0,255,0), 2)
line = cv2.line(image, bottomc, leftc, (0,255,0), 2)
line = cv2.line(image, rightc, topc, (0,255,0), 2)
line = cv2.line(image, leftc, topc, (0,255,0), 2)
line = cv2.line(image, rightc, topc, (0,255,0), 2)
line = cv2.line(image, bottomc, rightc, (0,255,0), 2)
cv2.drawContours(image, [c], -1, (0,255,0), 2)
except:
pass
cv2.imshow("Image", image)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
如果您的照片是等轴测视图,这将简化为以下问题:
您想找到对应于立方体的三个正交边的三个向量的测量值。
边 1:(X1,Y1,Z1)
Edge2: (X2, Y2, Z2)
Edge3: (X3, Y3, Z3)
根据您的图像,您可以测量其中两个向量的 X 和 Y 值,留下 5 个未知值。
由于所有三个边都是正交的,因此您也知道它们的点积为零。
最后,由于您处理的是立方体,所以您知道每个向量都具有相同的大小。
这给了你五个方程来求解五个未知变量,它可以唯一标识一个解。