使用opencv判断物体方向

使用opencv判断物体方向

上一篇笔记中,使用opencv框选出了各个矩形,获得了按照面积大小排序的矩形的各个顶点坐标位置的txt文件。在这篇文章中想要判断方向和旋转角度。

首先处理txt文件

def file_update(file,old_str,new_str):
    file_data = ""
    with open(file, "r", encoding="utf-8") as f:
        for line in f:
            if old_str in line:
                line = line.replace(old_str, new_str)
            file_data += line
    with open(file, "w", encoding="utf-8") as f:
        f.write(file_data)
direction_func.file_update(r".\information\coordinate_information.txt", "\n", "")
direction_func.file_update(r".\information\coordinate_information.txt", "[[", "")
direction_func.file_update(r".\information\coordinate_information.txt", "  ", ",")
direction_func.file_update(r".\information\coordinate_information.txt", "] [", ",")
direction_func.file_update(r".\information\coordinate_information.txt", "]]", "")
direction_func.file_update(r".\information\coordinate_information.txt", " ", ",")
direction_func.file_update(r".\information\coordinate_information.txt", ",,", ",")
m1x, m1y, m2x, m2y, m3x, m3y, m4x, m4y = direction_func.coordinate_value(8, r".\information\coordinate_information.txt")  # 0 8 16 24 ...

0是第一个矩形坐标,8是第二个矩形坐标,16是第三个矩形坐标,以此类推…

得到矩形坐标的8个值之后可以获得一些基本信息(不一定有用,只是我想要)

"""矩形中点(cex,ceny)"""
cenx, ceny = direction_func.center_point(m1x, m1y, m3x, m3y, m2x, m2y, m4x, m4y)
print("(cenx,ceny)=(%s,%s)" % (cenx, ceny))

"""矩形一条中线长度和角度"""
mid1x, mid1y = direction_func.middle_point(m1x, m1y, m2x, m2y)
mid2x, mid2y = direction_func.middle_point(m4x, m4y, m3x, m3y)
len1 = direction_func.length(mid1x, mid1y, mid2x, mid2y)
angle1 = direction_func.angle(mid1x, mid1y, mid2x, mid2y)
print("len1=", len1)
print("angle1=", angle1)
cv2.line(img_rect, (int(mid1x), int(mid1y)), (int(mid2x), int(mid2y)), (255, 0, 255), 2)

"""矩形另一边中线和角度"""
mid3x, mid3y = direction_func.middle_point(m1x, m1y, m4x, m4y)
mid4x, mid4y = direction_func.middle_point(m2x, m2y, m3x, m3y)
len2 = direction_func.length(mid3x, mid3y, mid4x, mid4y)
angle2 = direction_func.angle(mid3x, mid3y, mid4x, mid4y)
print("len2=", len2)
print("angle2=", angle2)
cv2.line(img_rect, (int(mid3x), int(mid3y)), (int(mid4x), int(mid4y)), (255, 0, 255), 2)

这时得到的结果:

使用opencv判断物体方向

我并不需要非常精确的旋转角度,于是把矩形长轴的旋转角度粗略当作物体旋转角度。

"""寻找长边并输出长边角度"""
angle, value = direction_func.long_axis(len1, angle1, len2, angle2)
print("angle=", angle)
if value == 1:
    cv2.line(img_rect, (int(mid3x), int(mid3y)), (int(mid4x), int(mid4y)), (55, 111, 55), 2)
if value == 2:
    cv2.line(img_rect, (int(mid1x), int(mid1y)), (int(mid2x), int(mid2y)), (55, 111, 55), 2)

这里在找到长边之后将长边换了一个颜色标识出来,并输出角度。

使用opencv判断物体方向

接下来将我们需要的矩形单独裁剪出来

"""裁剪矩形 截取需要的一个目标"""
l_up_x = min(m1x, m2x, m3x, m4x)
l_up_y = min(m1y, m2y, m3y, m4y)
r_down_x = max(m1x, m2x, m3x, m4x)
r_down_y = max(m1y, m2y, m3y, m4y)

"""裁剪图片 并保存"""
cropped_rect = Image.open(r".\images\screenshot\targets.jpg").crop((l_up_x, l_up_y, r_down_x, r_down_y))   # 左下角坐标和右上角坐标
cropped_rect.save(r".\images\screenshot\targets_one.jpg")

将裁剪出来的矩形按照之前计算出的角度旋转

"""旋转并保存旋转的图片"""
angle_rotate = 360 - float(angle)
print("angle_rotate=", angle_rotate)

tp = Image.open(r".\images\screenshot\targets_one.jpg")
tp.rotate(angle_rotate, expand=True).save(r".\images\screenshot\targets_one_rotate.jpg")
target_rect_one_rotate = cv2.imread(r".\images\screenshot\targets_one_rotate.jpg")
cv2.imshow('targets_one_rotate', target_rect_one_rotate)

使用opencv判断物体方向

将旋转后的图片一分为二再保存

"""读取保存后的图片并一分为二再保存"""
rows, cols, channels = target_rect_one_rotate.shape
print("rows=%s,cols=%s" % (rows, cols))

width = int(cols)
width_mid = int(width / 2)
longth = int(rows)
longth_mid = int(longth / 2)

direction_func.half_image(r".\images\screenshot\targets_one_rotate.jpg", width, longth, longth_mid)

img_uphalf = cv2.imread(r".\images\screenshot\targets_one_rotate_uphalf.jpg")
img_downhalf = cv2.imread(r".\images\screenshot\targets_one_rotate_downhalf.jpg")

使用opencv判断物体方向

使用函数判断上下半黑白颜色占比

def bw_ratio(img):
    x = img.shape[0]
    y = img.shape[1]
    bk = 0
    wt = 0
    for i in range(x):
        for j in range(y):
            if img[i, j].any() == 0:
                bk += 1
            else:
                wt += 1
                rate1 = wt / (x * y)
                rate2 = bk / (x * y)  # round()第二个值为保留几位有效小数。
    ratio_w = round(rate1 * 100, 2)
    ratio_b = round(rate2 * 100, 2)
    return ratio_w, ratio_b
"""判断上下部分白黑比例"""
ratio_w, ratio_b = direction_func.bw_ratio(img)
ratio_w_up, ratio_b_up = direction_func.bw_ratio(img_uphalf)
ratio_w_down, ratio_b_down = direction_func.bw_ratio(img_downhalf)
print("白色占比:%s,黑色占比:%s" % (ratio_w, ratio_b))
print("上半部分白色占比:%s,黑色占比:%s" % (ratio_w_up, ratio_b_up))
print("下半部分白色占比:%s,黑色占比:%s" % (ratio_w_down, ratio_b_down))
"""比较黑白比 0为up 1为down"""
result = direction_func.direction_judge(ratio_w_up, ratio_w_down)
print("0为up,1为down:", result)

白色占比更大的一半视为头部

使用opencv判断物体方向

将判断为头部的半边矩形圈选出来

"""画半个矩形"""
x12, y12 = direction_func.middle_point(m1x, m1y, m2x, m2y)
x23, y23 = direction_func.middle_point(m2x, m2y, m3x, m3y)
x34, y34 = direction_func.middle_point(m3x, m3y, m4x, m4y)
x41, y41 = direction_func.middle_point(m4x, m4y, m1x, m1y)
print(direction_func.length(m1x, m1y, m2x, m2y))
print(direction_func.length(m2x, m2y, m3x, m3y))
if direction_func.length(m1x, m1y, m2x, m2y) < direction_func.length(m2x, m2y, m3x, m3y):
    if result == 0:
        newBox = [[m1x, m1y], [m2x, m2y], [x23, y23], [x41, y41]]
        point = np.array(newBox).astype(int)
        cv2.line(img_rect, tuple(point[0]), tuple(point[1]), (0, 0, 255), 3)
        cv2.line(img_rect, tuple(point[1]), tuple(point[2]), (0, 0, 255), 3)
        cv2.line(img_rect, tuple(point[2]), tuple(point[3]), (0, 0, 255), 3)
        cv2.line(img_rect, tuple(point[3]), tuple(point[0]), (0, 0, 255), 3)
    if result == 1:
        newBox = [[x41, y41], [x23, y23], [m3x, m3y], [m4x, m4y]]
        point = np.array(newBox).astype(int)
        cv2.line(img_rect, tuple(point[0]), tuple(point[1]), (0, 0, 255), 3)
        cv2.line(img_rect, tuple(point[1]), tuple(point[2]), (0, 0, 255), 3)
        cv2.line(img_rect, tuple(point[2]), tuple(point[3]), (0, 0, 255), 3)
        cv2.line(img_rect, tuple(point[3]), tuple(point[0]), (0, 0, 255), 3)
else:
    if result == 0:
        newBox = [[m2x, m2y], [x12, y12], [x34, y34], [m3x, m3y]]
        point = np.array(newBox).astype(int)
        cv2.line(img_rect, tuple(point[0]), tuple(point[1]), (0, 0, 255), 3)
        cv2.line(img_rect, tuple(point[1]), tuple(point[2]), (0, 0, 255), 3)
        cv2.line(img_rect, tuple(point[2]), tuple(point[3]), (0, 0, 255), 3)
        cv2.line(img_rect, tuple(point[3]), tuple(point[0]), (0, 0, 255), 3)
    if result == 1:
        newBox = [[m1x, m1y], [x12, y12], [x34, y34], [m4x, m4y]]
        point = np.array(newBox).astype(int)
        cv2.line(img_rect, tuple(point[0]), tuple(point[1]), (0, 0, 255), 3)
        cv2.line(img_rect, tuple(point[1]), tuple(point[2]), (0, 0, 255), 3)
        cv2.line(img_rect, tuple(point[2]), tuple(point[3]), (0, 0, 255), 3)
        cv2.line(img_rect, tuple(point[3]), tuple(point[0]), (0, 0, 255), 3)

大功告成!

使用opencv判断物体方向

Original: https://blog.csdn.net/weixin_49828565/article/details/126663318
Author: 小小小小能
Title: 使用opencv判断物体方向

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/638169/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球