opencv 如何定位和测量图片中的物体?

cetgtptt  于 2022-11-15  发布在  其他
关注(0)|答案(1)|浏览(169)

我有这张图像

,对从第一张图像中检测长结构感兴趣,预期结果附在下一张图像中。
预期结果

我已经尝试了以下程序
1.阈值化
1.轮廓检测
1.二进制图像与水平对齐(使用旋转Angular )
1.建议需要Next from step 3,因为我的代码可以检测整个对象,但不能检测感兴趣的结构
这是我的密码

import cv2
import numpy as np
import math
iterations = 7
img00 = cv2.imread('./camera1'+str(a)+'.jpg')
gray00 = cv2.cvtColor(img00, cv2.COLOR_BGR2GRAY)

median_blur1 = cv2.medianBlur(gray00, iterations) # smoothing with median blur
ret1, thresh1 = cv2.threshold(median_blur1,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) # binarization with Otsu
# External Contour detection 
contours1, hierarchy1 = cv2.findContours(thresh1.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
try:
    cnt1 = contours1[0]
except IndexError: # Suppressing the index error to keep the camera live
    pass
# Getting the biggest contour
if len(contours1) != 0:
    # find the biggest countour (c) by the area
    c1 = max(contours1, key = cv2.contourArea)

height, width = img00.shape[:2]
center = (width/2, height/2)
x1,y1,w1,h1 = cv2.boundingRect(thresh1)
rect1 = cv2.minAreaRect(c1)
print(rect1[2])
rotate_matrix = cv2.getRotationMatrix2D(center=center, angle=rect1[2], scale=1)
binary_rotated = cv2.warpAffine(src=thresh1, M=rotate_matrix, dsize=(width, height))

contours2, hierarchy2 = cv2.findContours(binary_rotated.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnt2 = contours2[0]

x2,y2,w2,h2 = cv2.boundingRect(binary_rotated)
rect2 = cv2.minAreaRect(cnt2)
box2 = cv2.boxPoints(rect2)
box2

cv2.drawContours(binary_rotated, [box2], 0, (0, 255, 0), 2)

cv2.drawContours(img00, [box2], 0, (0, 255, 0), 2)
cv2.imshow('image', img00)
cv2.imshow('rotated_image', binary_rotated)
cv2.waitKey(0)
w3nuxt5m

w3nuxt5m1#

方法:

  • minAreaRect来自船体
  • 一些几何图形来建立一个 * 局部坐标系 *
  • 沿着对象(warpAffine)获取一维样本
  • 寻找边缘以测量钢筋厚度

要想 * 准确 * 获得中心条的中点,您需要沿着对象的一半,然后横向扫描中心条。
在我寻找索引的地方,可能会有一些偏一的错误。
我没有费心去实现一个 * 局部最大值 * 函数,尽管这会使结果更精确。我只是选择第一个高于阈值的梯度元素的索引。局部最大值可能包含多个元素。
我最喜欢的二维非最大值抑制方法之一是使用膨胀(形态学操作)来抑制局部非最大值。cv.dilate是一个选项,或者scipy.ndimage.morphology.grey_dilation。这应该是接下来的连通分量标记,因为两个相邻的元素可能都是局部最大值,当它们相等时,你不希望它们都计数,而是它们的质心。
第一个

# get box
# oriented bounding box
rrect = cv.minAreaRect(hull)
print(rrect) # (cx,cy), (w,h), angle

box = cv.boxPoints(rrect)

# roll corners so 0-1 is long edge
if norm(box[1] - box[0]) < norm(box[2] - box[1]):
    box = np.roll(box, 1, axis=0)

print(box)

canvas = cv.cvtColor(mask, cv.COLOR_GRAY2BGR)
cv.drawContours(canvas, [box.astype(int)], 0, (0, 0, 255), 2)
for i,pt in enumerate(box):
    cv.putText(canvas,
        f"[{i}]", (pt + [-10, 10]).astype(int),
        cv.FONT_HERSHEY_PLAIN, 1.8, (255, 186, 0), thickness=2)
imshow(canvas)

# local coordinate system

# assuming long edge is corner 0-1
orig = box[0].copy()
box_length = box[1] - orig
box_width = box[3] - orig
print("orig", orig)
print("vx", box_length)
print("vy", box_width)

vx = normalize(box_length)
vy = normalize(box_width)

# extend the box a little
orig -= 1*vx
box_length += 2*vx

canvas = cv.cvtColor(mask, cv.COLOR_GRAY2BGR)
cv.arrowedLine(canvas, orig.astype(int), (orig + box_length).astype(int), (0, 0, 255), 2)
cv.arrowedLine(canvas, orig.astype(int), (orig + box_width).astype(int), (0, 255, 0), 2)
imshow(canvas)

第一个

第一个


指令集

相关问题