이전 노트에서 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)