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)

이때 얻은 결과는 다음과 같습니다.

 

아주 정확한 회전 각도는 필요하지 않기 때문에 대략 직사각형의 장축 회전 각도를 객체의 회전 각도로 사용합니다.

"""寻找长边并输出长边角度"""
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)

여기서는 긴 변을 찾은 후 긴 변의 색상을 변경하여 식별하고 각도를 출력합니다.

다음으로 필요한 직사각형을 개별적으로 잘라냅니다.

"""裁剪矩形 截取需要的一个目标"""
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)

 

 회전된 이미지를 2개로 나누어 저장합니다.

"""读取保存后的图片并一分为二再保存"""
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")

 

함수를 사용하여 상반부와 하반부의 흑백 비율을 결정합니다.

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)

흰색 비율이 더 높은 절반이 머리로 간주됩니다.

 머리라고 판단되는 반 직사각형에 동그라미를 치세요

"""画半个矩形"""
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)

이제 끝났습니다!

Guess you like

Origin blog.csdn.net/weixin_49828565/article/details/126663318