在上一篇笔记中,使用opencv框选出了各个矩形,获得了按照面积大小排序的矩形的各个顶点坐标位置的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是第三个矩形坐标,以此类推...
"""矩形中点(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)
"""读取保存后的图片并一分为二再保存"""
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)