图像分析、物体形状、中心和极值
Image analysis, object shape, center and extrema
我编写了一个程序来从灰度图像构建阈值并找到其下方 对象的中心。这进一步用于将几何图形(线)绘制到对象中。 cv2.PCACompute()
函数用于寻找物体的中心。完成后,我可以画线来匹配物体的大致形状并做进一步的分析。
所以:
物体的极值是我需要找到的重要东西,而不是中心。但是为了计算它们,我需要画一条从中心开始的线。问题是,我需要告诉程序对象的 size
。现在我正试图通过检测对象的极值而不是中心来自动执行此操作。我想知道你是否可以帮助我。
输入图像:
首先构建一个 Threshold 并从中移除上面的对象:
import cv2
import numpy as np
#required to draw the length of the lins, originating from the core of object
scale = 20 #factor by which original image was scaled up
shard_size = 12*scale #length of object
#import image
img = cv2.imread('img.png', 0)
#build threshold
_, thresh = cv2.threshold(img,
235,
255,
cv2.THRESH_BINARY)
#remove upper object from image
z = 0
for x in thresh[::-1]:
v = 0
for el in x:
if el > 0:
break
v += 1
z += 1
if el > 0:
thresh[:int(-z-shard_size-2*scale)] = 0
break
如您所见,对象在顶部被切割。这是一种笨拙的方法。在下一步中 cv2.PCACompute()
用于找到对象的中心并确定其极值的方向。提供 shard_size
后,可以在对象极值方向绘制一条线。
#compute geometry of object (center + line extrema)
mat = np.argwhere(thresh == 255)
mat[:, [0, 1]] = mat[:, [1, 0]]
mat = np.array(mat).astype(np.float32)
m, e = cv2.PCACompute(mat, mean = np.array([]))
#determine coordinates of object (center + line extrema)
center = tuple(m[0])
endpoint1 = tuple(m[0] - e[0] * shard_size/2)
endpoint2 = tuple(m[0] + e[0] * shard_size/2)
#draw line into object
red_color = (0, 0, 255)
coord1 = endpoint1
coord2 = endpoint2
cv2.circle(img, center, 1, red_color)
cv2.line(img, coord1, coord2, red_color)
#save output img
cv2.imwrite('output_img.png', img)
如何找到对象的极值而不是中心,这样我就不需要再给程序 shard_size
输入了?
在这里,我使用 cv2.minAreaRect() 函数找到了对象的长度,并计算了沿质心的端点。
minAreaRect 函数为我们提供包围对象的矩形的中心、轴和角度。我使用角度信息来旋转水平矢量并生成线的端点
#Finding the contours in the image
im2, contours, hierarchy = cv2.findContours(img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
#finding the minimum area rectangle that covers the blob
rect = cv2.minAreaRect(contours[0])
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(img,[box],0,(0,0,255),2)
#Forming the line vector
v = np.matrix([[0], [1]])
#forming the rotation matrix to rotate the line vector
ang = rect[2]* np.pi / 180 #conversion to radians
rot = np.matrix([[np.cos(ang), -np.sin(ang)],[np.sin(ang), np.cos(ang)]])
#Rotating the horizontal vector
rv = rot*v
#half length of the line
lineSize = max(rect[1])*0.5
#extreme points of the line
p1 = tuple(np.array(rect[0] - lineSize*rv.T)[0].astype(int))
p2 = tuple(np.array(rect[0] + lineSize*rv.T)[0].astype(int))
cv2.line(img, p1, p2, (0,255,0), 2)
我编写了一个程序来从灰度图像构建阈值并找到其下方 对象的中心。这进一步用于将几何图形(线)绘制到对象中。 cv2.PCACompute()
函数用于寻找物体的中心。完成后,我可以画线来匹配物体的大致形状并做进一步的分析。
所以:
物体的极值是我需要找到的重要东西,而不是中心。但是为了计算它们,我需要画一条从中心开始的线。问题是,我需要告诉程序对象的 size
。现在我正试图通过检测对象的极值而不是中心来自动执行此操作。我想知道你是否可以帮助我。
输入图像:
首先构建一个 Threshold 并从中移除上面的对象:
import cv2
import numpy as np
#required to draw the length of the lins, originating from the core of object
scale = 20 #factor by which original image was scaled up
shard_size = 12*scale #length of object
#import image
img = cv2.imread('img.png', 0)
#build threshold
_, thresh = cv2.threshold(img,
235,
255,
cv2.THRESH_BINARY)
#remove upper object from image
z = 0
for x in thresh[::-1]:
v = 0
for el in x:
if el > 0:
break
v += 1
z += 1
if el > 0:
thresh[:int(-z-shard_size-2*scale)] = 0
break
如您所见,对象在顶部被切割。这是一种笨拙的方法。在下一步中 cv2.PCACompute()
用于找到对象的中心并确定其极值的方向。提供 shard_size
后,可以在对象极值方向绘制一条线。
#compute geometry of object (center + line extrema)
mat = np.argwhere(thresh == 255)
mat[:, [0, 1]] = mat[:, [1, 0]]
mat = np.array(mat).astype(np.float32)
m, e = cv2.PCACompute(mat, mean = np.array([]))
#determine coordinates of object (center + line extrema)
center = tuple(m[0])
endpoint1 = tuple(m[0] - e[0] * shard_size/2)
endpoint2 = tuple(m[0] + e[0] * shard_size/2)
#draw line into object
red_color = (0, 0, 255)
coord1 = endpoint1
coord2 = endpoint2
cv2.circle(img, center, 1, red_color)
cv2.line(img, coord1, coord2, red_color)
#save output img
cv2.imwrite('output_img.png', img)
如何找到对象的极值而不是中心,这样我就不需要再给程序 shard_size
输入了?
在这里,我使用 cv2.minAreaRect() 函数找到了对象的长度,并计算了沿质心的端点。
minAreaRect 函数为我们提供包围对象的矩形的中心、轴和角度。我使用角度信息来旋转水平矢量并生成线的端点
#Finding the contours in the image
im2, contours, hierarchy = cv2.findContours(img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
#finding the minimum area rectangle that covers the blob
rect = cv2.minAreaRect(contours[0])
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(img,[box],0,(0,0,255),2)
#Forming the line vector
v = np.matrix([[0], [1]])
#forming the rotation matrix to rotate the line vector
ang = rect[2]* np.pi / 180 #conversion to radians
rot = np.matrix([[np.cos(ang), -np.sin(ang)],[np.sin(ang), np.cos(ang)]])
#Rotating the horizontal vector
rv = rot*v
#half length of the line
lineSize = max(rect[1])*0.5
#extreme points of the line
p1 = tuple(np.array(rect[0] - lineSize*rv.T)[0].astype(int))
p2 = tuple(np.array(rect[0] + lineSize*rv.T)[0].astype(int))
cv2.line(img, p1, p2, (0,255,0), 2)