1388 lines
54 KiB
Python
1388 lines
54 KiB
Python
import copy
|
||
import math
|
||
|
||
import cv2
|
||
import numpy as np
|
||
from matplotlib import pyplot
|
||
from numpy import where, mean
|
||
from scipy import optimize
|
||
from skimage import morphology
|
||
from sklearn.cluster import OPTICS
|
||
from config import opt
|
||
|
||
|
||
# 图片预处理
|
||
def process_map(img, opt):
|
||
def get_wall_area(map, area):
|
||
'''
|
||
. map 获取墙壁的图像
|
||
. stats 连通域信息
|
||
. area 面积
|
||
'''
|
||
map_ = copy.copy(map)
|
||
map_[map != 255] = 0
|
||
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(map_, connectivity=8)
|
||
temp = []
|
||
for i in range(1, num_labels):
|
||
if stats[i, 4] > area:
|
||
temp.append(i)
|
||
wall_area = np.zeros((map.shape[0], map.shape[1]), np.uint8)
|
||
for i in range(0, len(temp)):
|
||
mask = labels == temp[i]
|
||
wall_area[:, :][mask] = 255
|
||
|
||
return wall_area
|
||
|
||
def get_NONwall_area(map, stats, area, num_labels, labels):
|
||
'''
|
||
. map 获取墙壁的图像
|
||
. stats 连通域信息
|
||
. area 面积
|
||
'''
|
||
temp = []
|
||
for i in range(1, num_labels):
|
||
|
||
mask = labels == i
|
||
|
||
if stats[i, 4] < area:
|
||
temp.append(i)
|
||
|
||
elif np.max(map[:, :][mask]) in Intensity_value:
|
||
temp.append(i)
|
||
|
||
NONwall_area = np.zeros((map.shape[0], map.shape[1]), np.uint8)
|
||
for i in range(0, len(temp)):
|
||
mask = labels == temp[i]
|
||
NONwall_area[:, :][mask] = 255
|
||
return NONwall_area
|
||
|
||
def get_rotate_angle(wall_area, length, opt):
|
||
temp = copy.copy(wall_area)
|
||
# temp = cv2.pyrUp(temp)
|
||
# temp = cv2.pyrUp(temp)
|
||
edges = cv2.Canny(temp, 50, 150, apertureSize=5)
|
||
|
||
lines = cv2.HoughLines(edges, 1, np.pi / 180, length)
|
||
|
||
# if (lines == None):
|
||
# return wall_area
|
||
temp = np.zeros((wall_area.shape[0], wall_area.shape[1]))
|
||
np.zeros((wall_area.shape[0], wall_area.shape[1]))
|
||
alfa = 0
|
||
theta_temp = [0]
|
||
for line in lines:
|
||
n = 0
|
||
rho = line[0][0]
|
||
theta = line[0][1]
|
||
a = np.cos(theta)
|
||
b = np.sin(theta)
|
||
x0 = a * rho
|
||
y0 = b * rho
|
||
x1 = int(x0 + 1000 * (-b))
|
||
y1 = int(y0 + 1000 * (a))
|
||
x2 = int(x0 - 1000 * (-b))
|
||
y2 = int(y0 - 1000 * (a))
|
||
# alfa = alfa + np.mod(theta, 90 / 360 * np.pi)
|
||
# alfa = theta
|
||
|
||
theta_array = np.array(theta_temp)
|
||
n = 0
|
||
for i in range(theta_array.shape[0]):
|
||
x = np.abs(theta - theta_array[i])
|
||
if (0 < x < 0.15 * np.pi):
|
||
n = 1
|
||
break
|
||
if (n == 1):
|
||
continue
|
||
theta_temp.append(theta)
|
||
wall_area = rotate_bound(wall_area, -np.mod(theta, 180 / 360 * np.pi) / np.pi * 180) # 摆正图像
|
||
temp = rotate_bound(temp, -np.mod(theta, 180 / 360 * np.pi) / np.pi * 180) # 摆正图像
|
||
# wall_area_ = cv2.dilate(wall_area_, kernel) # 腐蚀膨胀,去除墙上语义点
|
||
temp_ = connect_door(wall_area, opt.k, opt.m) # 封闭区域
|
||
temp[temp_ > 0] = 0
|
||
temp = temp_ + temp
|
||
|
||
|
||
wall_area = rotate_bound(wall_area, np.mod(theta, 180 / 360 * np.pi) / np.pi * 180)
|
||
temp = rotate_bound(temp, np.mod(theta, 180 / 360 * np.pi) / np.pi * 180)
|
||
|
||
wall_area[temp > 0] = 255
|
||
|
||
|
||
return wall_area
|
||
|
||
def rotate_bound(image, angle):
|
||
'''
|
||
. 旋转图片
|
||
. @param image opencv读取后的图像
|
||
. @param angle (逆)旋转角度
|
||
'''
|
||
|
||
# img = cv2.imread("img/1.jpg")
|
||
(h, w) = image.shape[:2] # 返回(高,宽,色彩通道数),此处取前两个值返回
|
||
# 抓取旋转矩阵(应用角度的负值顺时针旋转)。参数1为旋转中心点;参数2为旋转角度,正的值表示逆时针旋转;参数3为各向同性的比例因子
|
||
M = cv2.getRotationMatrix2D((w / 2, h / 2), -angle, 1.0)
|
||
# 计算图像的新边界维数
|
||
|
||
# 调整旋转矩阵以考虑平移
|
||
|
||
# 执行实际的旋转并返回图像
|
||
return cv2.warpAffine(image, M, (image.shape[1], image.shape[0])) # borderValue 缺省,默认是黑色
|
||
# return M
|
||
|
||
def get_map(img, ratio):
|
||
"""
|
||
:param img:
|
||
:param ratio: 获取地图,2表示有效面积的2倍
|
||
:return:
|
||
"""
|
||
ratio = (ratio - 1) / 2
|
||
# b = np.nonzero(img)
|
||
# x_min = np.min(b[0])
|
||
# y_min = np.min(b[1])
|
||
# x_max = np.max(b[0])
|
||
# y_max = np.max(b[1])
|
||
# x_l = x_max - x_min
|
||
# y_l = y_max - y_min
|
||
# if x_l < 150:
|
||
# ratio = ratio + 0.5
|
||
# map = np.zeros((x_max - x_min, y_max - y_min))
|
||
# temp = img[int(max(x_min - ratio * x_l, 0)):int(min(x_max + x_l * ratio, img.shape[1])),
|
||
# int(max(0, y_min - ratio * y_l)):int(min(img.shape[0], ratio * y_l + y_max))]
|
||
'''
|
||
去掉未占用区域
|
||
'''
|
||
|
||
temp_x = np.zeros((img.shape[0], 50), np.uint8)
|
||
|
||
map = np.hstack((temp_x, img))
|
||
temp_y = np.zeros((50, map.shape[1]), np.uint8)
|
||
map = np.vstack((temp_y, map))
|
||
# map = np.zeros((img.shape[0], 50), np.uint8)
|
||
temp_x = np.zeros((map.shape[0], 40), np.uint8)
|
||
map = np.hstack((map, temp_x))
|
||
temp_y = np.zeros((40, map.shape[1]), np.uint8)
|
||
map = np.vstack((map, temp_y))
|
||
|
||
# map = copy.copy(img)
|
||
map[map < 70] = 255
|
||
map[map <= 100] = 0
|
||
map[map == 0] = 1
|
||
map[map == 255] = 0
|
||
map[map == 1] = 255
|
||
"墙壁灰度值为1"
|
||
return map
|
||
|
||
def draw_rgb(map):
|
||
def rgb_semantics(number):
|
||
output = np.array((5, 5, 5), np.uint8)
|
||
if number == 115:
|
||
'0号物体'
|
||
output[0] = 232
|
||
output[1] = 221
|
||
output[2] = 203
|
||
elif number == 116:
|
||
'1号物体'
|
||
output[0] = 205
|
||
output[1] = 179
|
||
output[2] = 128
|
||
elif number == 117:
|
||
'2号物体'
|
||
output[0] = 3
|
||
output[1] = 101
|
||
output[2] = 100
|
||
elif number == 118:
|
||
'3号物体'
|
||
output[0] = 3
|
||
output[1] = 54
|
||
output[2] = 73
|
||
elif number == 119:
|
||
'4号物体'
|
||
output[0] = 3
|
||
output[1] = 22
|
||
output[2] = 52
|
||
elif number == 120:
|
||
'5号物体'
|
||
output[0] = 237
|
||
output[1] = 222
|
||
output[2] = 139
|
||
elif number == 121:
|
||
'6号物体'
|
||
output[0] = 251
|
||
output[1] = 178
|
||
output[2] = 23
|
||
elif number == 150:
|
||
'7号物体'
|
||
output[0] = 96
|
||
output[1] = 143
|
||
output[2] = 159
|
||
elif number == 151:
|
||
'8号物体'
|
||
output[0] = 1
|
||
output[1] = 77
|
||
output[2] = 103
|
||
elif number == 152:
|
||
'9号物体'
|
||
output[0] = 254
|
||
output[1] = 67
|
||
output[2] = 101
|
||
elif number == 153:
|
||
'10号物'
|
||
output[0] = 252
|
||
output[1] = 157
|
||
output[2] = 154
|
||
elif number == 154:
|
||
'11号物体'
|
||
output[0] = 249
|
||
output[1] = 205
|
||
output[2] = 173
|
||
elif number == 155:
|
||
'12号物体'
|
||
output[0] = 200
|
||
output[1] = 200
|
||
output[2] = 169
|
||
elif number == 156:
|
||
'13号物体'
|
||
output[0] = 131
|
||
output[1] = 175
|
||
output[2] = 155
|
||
elif number == 200:
|
||
'14号物体'
|
||
output[0] = 229
|
||
output[1] = 187
|
||
output[2] = 129
|
||
elif number == 201:
|
||
'15号物体'
|
||
output[0] = 161
|
||
output[1] = 23
|
||
output[2] = 21
|
||
elif number == 202:
|
||
'16号物体'
|
||
output[0] = 118
|
||
output[1] = 77
|
||
output[2] = 57
|
||
elif number == 203:
|
||
'17号物体'
|
||
output[0] = 17
|
||
output[1] = 63
|
||
output[2] = 61
|
||
elif number == 204:
|
||
'18号物体'
|
||
output[0] = 60
|
||
output[1] = 79
|
||
output[2] = 57
|
||
elif number == 205:
|
||
'19号物体'
|
||
output[0] = 95
|
||
output[1] = 92
|
||
output[2] = 51
|
||
elif number == 206:
|
||
'20号物体'
|
||
output[0] = 179
|
||
output[1] = 214
|
||
output[2] = 110
|
||
elif number == 207:
|
||
'21号物体'
|
||
output[0] = 227
|
||
output[1] = 160
|
||
output[2] = 93
|
||
elif number == 208:
|
||
'22号物体'
|
||
output[0] = 178
|
||
output[1] = 190
|
||
output[2] = 126
|
||
elif number == 209:
|
||
'23号物体'
|
||
output[0] = 56
|
||
output[1] = 13
|
||
output[2] = 49
|
||
else:
|
||
output[0] = 5
|
||
output[1] = 5
|
||
output[2] = 5
|
||
return output
|
||
|
||
output = np.zeros((map.shape[0], map.shape[1], 3), np.uint8)
|
||
output_b = copy.copy(map)
|
||
output_g = copy.copy(map)
|
||
output_r = copy.copy(map)
|
||
|
||
for i in range(np.array(Intensity_value).shape[0]):
|
||
intensity = Intensity_value[i]
|
||
output_r[map == intensity] = rgb_semantics(intensity)[0]
|
||
output_g[map == intensity] = rgb_semantics(intensity)[1]
|
||
output_b[map == intensity] = rgb_semantics(intensity)[2]
|
||
|
||
output[:, :, 0] = output_b
|
||
output[:, :, 1] = output_g
|
||
output[:, :, 2] = output_r
|
||
return output
|
||
|
||
# 行扫描,间隔k时,进行填充,填充值为1
|
||
|
||
# 将门口连起来
|
||
def connect_door(wall_area, k, m):
|
||
"""
|
||
|
||
:param wall_area:
|
||
:param k: 门宽
|
||
:param m: 墙壁长度
|
||
:return:
|
||
"""
|
||
|
||
def edge_connection(img, size, k, m):
|
||
for i in range(size):
|
||
Yi = np.where(img[i, :] > 220)
|
||
if len(Yi[0]) >= m: # 可调整 (墙壁长度)
|
||
for j in range(0, len(Yi[0]) - 1):
|
||
if Yi[0][j + 1] - Yi[0][j] <= k:
|
||
# img[min(i - 1, img.shape[0] - 1), Yi[0][j]:Yi[0][j + 1]] = 255
|
||
img[min(i, img.shape[0] - 1), Yi[0][j]:Yi[0][j + 1]] = 255
|
||
# img[i, Yi[0][j]:Yi[0][j + 1]] = 255
|
||
# img[min(i + 1, img.shape[0]-1), Yi[0][j]:Yi[0][j + 1]] = 255
|
||
return img
|
||
|
||
img = copy.copy(wall_area)
|
||
g = edge_connection(img, img.shape[0], k, m) # k设的是门的宽度, m是判为墙壁的长度
|
||
g = cv2.rotate(g, 0)
|
||
g = edge_connection(g, img.shape[1], k, m)
|
||
g = cv2.rotate(g, 2)
|
||
g = g.astype(np.uint8)
|
||
return g
|
||
|
||
'''
|
||
用于绘制地图及物体形状绘制
|
||
'''
|
||
'定义语义强度'
|
||
Intensity_value = [115, 116, 117, 118, 119, 120, 121, 150, 151, 152, 153,
|
||
154, 155, 156, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209]
|
||
# Intensity_value = [153]
|
||
map = get_map(img, 4)
|
||
'插值处理,提高分辨率'
|
||
map = cv2.resize(map, (map.shape[1] * 2, map.shape[0] * 2), interpolation=cv2.INTER_NEAREST)
|
||
|
||
map_ori = copy.copy(map)
|
||
|
||
wall_area = get_wall_area(map, opt.acreage) # 获取墙壁区域
|
||
NON_wall_area = map - wall_area
|
||
|
||
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
|
||
wall_area = cv2.dilate(wall_area, kernel)
|
||
|
||
connect_line = get_rotate_angle(wall_area, opt.length, opt) # 连接
|
||
connect_line = cv2.erode(connect_line, kernel, iterations=3)
|
||
connect_line[connect_line < 150] = 0
|
||
connect_line[connect_line > 0] = 255
|
||
|
||
temp1 = copy.copy(connect_line)
|
||
temp2 = copy.copy(NON_wall_area)
|
||
temp1[temp1 > 0] = 1
|
||
temp = temp1 * temp2
|
||
NON_wall_area[temp != 0] = 0
|
||
result = connect_line + NON_wall_area
|
||
result[result > 255] = 255
|
||
result = result.astype(np.uint8)
|
||
|
||
result[result == 0] = 254
|
||
result[result == 255] = 0
|
||
result[result == 254] = 255
|
||
|
||
# cv2.imwrite("result.png", result)
|
||
'''
|
||
用于提取区域
|
||
'''
|
||
|
||
map_ = copy.copy(map) # 用于封闭区域
|
||
map_[map_ > 0] = 255
|
||
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(map_, connectivity=8)
|
||
wall_area_ = get_wall_area(map_, opt.acreage) # 获取墙壁区域
|
||
NON_wall_area_ = map_ - wall_area_
|
||
|
||
wall_area_ = cv2.dilate(wall_area_, kernel)
|
||
|
||
connect_line_ = get_rotate_angle(wall_area_, opt.length, opt) # 连接
|
||
connect_line_[connect_line_ < 150] = 0
|
||
connect_line_[connect_line_ > 0] = 255
|
||
|
||
temp1_ = copy.copy(connect_line_)
|
||
temp2_ = copy.copy(NON_wall_area_)
|
||
temp1_[temp1_ > 0] = 1
|
||
temp_ = temp1_ * temp2_
|
||
NON_wall_area[temp_ != 0] = 0
|
||
result_ = connect_line_ + NON_wall_area_
|
||
result_[result_ > 255] = 255
|
||
result_ = result_.astype(np.uint8)
|
||
|
||
result_[result_ == 0] = 254
|
||
result_[result_ == 255] = 0
|
||
result_[result_ == 254] = 255
|
||
|
||
|
||
# wall_area_ = rotate_bound(wall_area, -alfa / np.pi * 180) # 摆正图像
|
||
# # wall_area_ = cv2.dilate(wall_area_, kernel) # 腐蚀膨胀,去除墙上语义点
|
||
#
|
||
# connect_line = connect_door(wall_area_, opt.k, opt.m) # 封闭区域
|
||
# connect_line_ = rotate_bound(connect_line, alfa / np.pi * 180)
|
||
|
||
map_ori[map_ori == 0] = 254
|
||
map_ori[map_ori == 255] = 0
|
||
map_ori[map_ori == 254] = 255
|
||
|
||
return result, result_, map_ori
|
||
|
||
|
||
# 绘制物体形状
|
||
def obj_outline(map, opt, map_ori):
|
||
'''
|
||
. 绘制物体形状
|
||
. @param map 语义地图
|
||
. @param Semantic_map 场景分类图
|
||
. @param opt 参数
|
||
'''
|
||
|
||
def rotate_bound(image, angle):
|
||
'''
|
||
. 旋转图片
|
||
. @param image opencv读取后的图像
|
||
. @param angle (逆)旋转角度
|
||
'''
|
||
|
||
# img = cv2.imread("img/1.jpg")
|
||
(h, w) = image.shape[:2] # 返回(高,宽,色彩通道数),此处取前两个值返回
|
||
# 抓取旋转矩阵(应用角度的负值顺时针旋转)。参数1为旋转中心点;参数2为旋转角度,正的值表示逆时针旋转;参数3为各向同性的比例因子
|
||
M = cv2.getRotationMatrix2D((w / 2, h / 2), -angle, 1.0)
|
||
# 计算图像的新边界维数
|
||
|
||
# 调整旋转矩阵以考虑平移
|
||
|
||
# 执行实际的旋转并返回图像
|
||
return cv2.warpAffine(image, M, (image.shape[1], image.shape[0])) # borderValue 缺省,默认是黑色
|
||
# return M
|
||
|
||
# 根据不同语义物体得到不同参数
|
||
def get_parameter(item, opt):
|
||
'''
|
||
. 得到物体参数
|
||
. @param item 物体的强度值
|
||
. @param opt 物体参数
|
||
'''
|
||
if (item == 115):
|
||
min_samples = opt.min_samples_115
|
||
max_eps = opt.max_eps_115
|
||
shape = opt.shape_115 # 0是圆形,1是矩形
|
||
size = opt.size_115 # 0是按轮廓,1是直接画正矩形
|
||
color = [232, 221, 203]
|
||
filter_point_num = 0
|
||
elif (item == 116):
|
||
min_samples = opt.min_samples_116
|
||
max_eps = opt.max_eps_116
|
||
shape = opt.shape_116 # 0是圆形,1是矩形
|
||
size = opt.size_116 # 0是按轮廓,1是直接画正矩形
|
||
color = [205, 179, 128]
|
||
filter_point_num = 0
|
||
elif (item == 117):
|
||
min_samples = opt.min_samples_117
|
||
max_eps = opt.max_eps_117
|
||
shape = opt.shape_117 # 0是圆形,1是矩形
|
||
size = opt.size_117 # 0是按轮廓,1是直接画正矩形
|
||
color = [3, 101, 100]
|
||
filter_point_num = 0
|
||
elif (item == 118):
|
||
min_samples = opt.min_samples_118
|
||
max_eps = opt.max_eps_118
|
||
shape = opt.shape_118 # 0是圆形,1是矩形
|
||
size = opt.size_118 # 0是按轮廓,1是直接画正矩形
|
||
color = [3, 54, 73]
|
||
filter_point_num = 0
|
||
elif (item == 119):
|
||
min_samples = opt.min_samples_119
|
||
max_eps = opt.max_eps_119
|
||
shape = opt.shape_119 # 0是圆形,1是矩形
|
||
size = opt.size_119 # 0是按轮廓,1是直接画正矩形
|
||
color = [3, 22, 52]
|
||
filter_point_num = 0
|
||
elif (item == 120):
|
||
min_samples = opt.min_samples_120
|
||
max_eps = opt.max_eps_120
|
||
shape = opt.shape_120 # 0是圆形,1是矩形
|
||
size = opt.size_120 # 0是按轮廓,1是直接画正矩形
|
||
color = [237, 22, 139]
|
||
filter_point_num = 0
|
||
elif (item == 121):
|
||
min_samples = opt.min_samples_121
|
||
max_eps = opt.max_eps_121
|
||
shape = opt.shape_121 # 0是圆形,1是矩形
|
||
size = opt.size_121 # 0是按轮廓,1是直接画正矩形
|
||
color = [251, 178, 23]
|
||
filter_point_num = 0
|
||
elif (item == 150):
|
||
min_samples = opt.min_samples_150
|
||
max_eps = opt.max_eps_150
|
||
shape = opt.shape_150 # 0是圆形,1是矩形
|
||
size = opt.size_150 # 0是按轮廓,1是直接画正矩形
|
||
color = [96, 143, 159]
|
||
filter_point_num = 0
|
||
elif (item == 151):
|
||
min_samples = opt.min_samples_151
|
||
max_eps = opt.max_eps_151
|
||
shape = opt.shape_151 # 0是圆形,1是矩形
|
||
size = opt.size_151 # 0是按轮廓,1是直接画正矩形
|
||
color = [1, 77, 103]
|
||
filter_point_num = 0
|
||
elif (item == 152):
|
||
min_samples = opt.min_samples_152
|
||
max_eps = opt.max_eps_152
|
||
shape = opt.shape_152 # 0是圆形,1是矩形
|
||
size = opt.size_152 # 0是按轮廓,1是直接画正矩形
|
||
color = [254, 67, 101]
|
||
filter_point_num = 0
|
||
elif (item == 153):
|
||
min_samples = opt.min_samples_153
|
||
max_eps = opt.max_eps_153
|
||
shape = opt.shape_153 # 0是圆形,1是矩形
|
||
size = opt.size_153 # 0是按轮廓,1是直接画正矩形
|
||
color = [252, 157, 154]
|
||
filter_point_num = 0
|
||
elif (item == 154):
|
||
min_samples = opt.min_samples_154
|
||
max_eps = opt.max_eps_154
|
||
shape = opt.shape_154 # 0是圆形,1是矩形
|
||
size = opt.size_154 # 0是按轮廓,1是直接画正矩形
|
||
color = [249, 205, 173]
|
||
filter_point_num = 0
|
||
elif (item == 155):
|
||
min_samples = opt.min_samples_155
|
||
max_eps = opt.max_eps_155
|
||
shape = opt.shape_155 # 0是圆形,1是矩形
|
||
size = opt.size_155 # 0是按轮廓,1是直接画正矩形
|
||
color = [200, 200, 169]
|
||
filter_point_num = 0
|
||
elif (item == 156):
|
||
min_samples = opt.min_samples_156
|
||
max_eps = opt.max_eps_156
|
||
shape = opt.shape_156 # 0是圆形,1是矩形
|
||
size = opt.size_156 # 0是按轮廓,1是直接画正矩形
|
||
color = [131, 175, 155]
|
||
filter_point_num = 0
|
||
elif (item == 200):
|
||
min_samples = opt.min_samples_200
|
||
max_eps = opt.max_eps_200
|
||
shape = opt.shape_200 # 0是圆形,1是矩形
|
||
size = opt.size_200 # 0是按轮廓,1是直接画正矩形
|
||
color = [229, 187, 129]
|
||
filter_point_num = 0
|
||
elif (item == 201):
|
||
min_samples = opt.min_samples_201
|
||
max_eps = opt.max_eps_201
|
||
shape = opt.shape_201 # 0是圆形,1是矩形
|
||
size = opt.size_201 # 0是按轮廓,1是直接画正矩形
|
||
color = [161, 23, 21]
|
||
filter_point_num = 0
|
||
elif (item == 202):
|
||
min_samples = opt.min_samples_202
|
||
max_eps = opt.max_eps_202
|
||
shape = opt.shape_202 # 0是圆形,1是矩形
|
||
size = opt.size_202 # 0是按轮廓,1是直接画正矩形
|
||
color = [118, 77, 57]
|
||
filter_point_num = 0
|
||
elif (item == 203):
|
||
min_samples = opt.min_samples_203
|
||
max_eps = opt.max_eps_203
|
||
shape = opt.shape_203 # 0是圆形,1是矩形
|
||
size = opt.size_203 # 0是按轮廓,1是直接画正矩形
|
||
color = [17, 63, 61]
|
||
filter_point_num = 0
|
||
elif (item == 204):
|
||
min_samples = opt.min_samples_204
|
||
max_eps = opt.max_eps_204
|
||
shape = opt.shape_204 # 0是圆形,1是矩形
|
||
size = opt.size_204 # 0是按轮廓,1是直接画正矩形
|
||
color = [60, 79, 57]
|
||
filter_point_num = 0
|
||
elif (item == 205):
|
||
min_samples = opt.min_samples_205
|
||
max_eps = opt.max_eps_205
|
||
shape = opt.shape_205 # 0是圆形,1是矩形
|
||
size = opt.size_205 # 0是按轮廓,1是直接画正矩形
|
||
color = [95, 92, 51]
|
||
filter_point_num = 0
|
||
elif (item == 209):
|
||
min_samples = opt.min_samples_209
|
||
max_eps = opt.max_eps_209
|
||
shape = opt.shape_209 # 0是圆形,1是矩形
|
||
size = opt.size_209 # 0是按轮廓,1是直接画正矩形
|
||
color = [56, 13, 49]
|
||
filter_point_num = 0
|
||
|
||
return min_samples, max_eps, shape, size, color, filter_point_num
|
||
|
||
def filter_point(X, filter_point_num):
|
||
obj_collect = np.zeros((map.shape[0], map.shape[1]), np.uint8)
|
||
row = X[:, 0].astype(int)
|
||
col = X[:, 1].astype(int)
|
||
obj_collect[row, col] = 1
|
||
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(obj_collect, connectivity=8)
|
||
if (item == 204):
|
||
for i in range(num_labels):
|
||
if (stats[i, 4] <= filter_point_num):
|
||
mask = labels == i
|
||
obj_collect[:, :][mask] = 0
|
||
y, x = np.where(obj_collect == 1) # y是行,x是列
|
||
X = np.zeros((x.shape[0], 2))
|
||
X[:, 0] = y
|
||
X[:, 1] = x
|
||
return X
|
||
|
||
# 画物体轮廓
|
||
def draw_outline(X, item, min_samples, max_eps, shape, color, size, filter_point_num, output):
|
||
'''
|
||
. 得到物体参数
|
||
. @param X 语义物体的行列坐标
|
||
. @param item 语义物体的强度值
|
||
. @param min_samples 聚类的最小样本数
|
||
. @param max_eps 聚类的最大半径
|
||
. @param shape 语义物体绘制形状参数( 0代表绘制圆形,1代表绘制矩形)
|
||
. @param color 语义物体的色彩
|
||
. @param size 语义物体绘制轮廓的参数(0代表按轮廓绘制,1代表绘制正矩形)
|
||
. @param output 已经绘制过某个物体形状的 map图片
|
||
'''
|
||
|
||
# 聚类(OPTICS算法)
|
||
# X = X.astype(np.uint8)
|
||
|
||
yhat = OPTICS(min_samples=min_samples, max_eps=max_eps, cluster_method='dbscan').fit_predict(X)
|
||
# 检索唯一群集
|
||
clusters = np.unique(yhat)
|
||
|
||
'''
|
||
画散点图
|
||
为每个群集的样本创建散点图
|
||
'''
|
||
# for cluster in clusters: # 获取此群集的示例的行索引
|
||
# row_ix = where(yhat == cluster) # 创建这些样本的散布
|
||
# pyplot.scatter(X[row_ix, 0], X[row_ix, 1]) # 绘制散点图
|
||
# pyplot.show()
|
||
'''
|
||
找最小外接矩形 (绘制形状)
|
||
'''
|
||
color = color[::-1]
|
||
|
||
for cluster in clusters:
|
||
n = 0
|
||
# 获取此群集的示例的行索引,将每个物体从map中提取出来
|
||
if (cluster == -1):
|
||
n = 1
|
||
continue
|
||
|
||
row_ix = where(yhat == cluster)
|
||
if row_ix[0].shape[0] <= 1:
|
||
continue
|
||
|
||
obj = np.zeros((map.shape[0], map.shape[1]), np.uint8)
|
||
row = X[row_ix, 0].astype(int)
|
||
col = X[row_ix, 1].astype(int)
|
||
obj[row, col] = 1
|
||
|
||
if (item == 118 or item == 119 or item == 153 or item == 202):
|
||
# if (item == 899):
|
||
skeleton0 = morphology.skeletonize(obj)
|
||
skeleton = skeleton0.astype(np.uint8) * 255
|
||
temps = copy.copy(skeleton)
|
||
|
||
temp_outline = np.zeros((output.shape[0], output.shape[1], 3), np.uint8)
|
||
for i in range(60, 0,-1):
|
||
|
||
lines = cv2.HoughLines(skeleton, 1, np.pi / 180, i)
|
||
if (lines is not None):
|
||
if lines.shape[0] >0:
|
||
break
|
||
|
||
if (lines is None):
|
||
n = 1
|
||
continue
|
||
|
||
alfa = 0
|
||
for line in lines:
|
||
rho = line[0][0]
|
||
theta = line[0][1]
|
||
a = np.cos(theta)
|
||
b = np.sin(theta)
|
||
x0 = a * rho
|
||
y0 = b * rho
|
||
theta = np.mod(theta, 90 / 180 * np.pi)
|
||
if (theta > 45 / 180 * np.pi):
|
||
theta = abs(theta - 90 / 180 * np.pi)
|
||
x1 = int(x0 + 1000 * (-b))
|
||
y1 = int(y0 + 1000 * (a))
|
||
x2 = int(x0 - 1000 * (-b))
|
||
y2 = int(y0 - 1000 * (a))
|
||
# cv2.line(temps, (x1, y1), (x2, y2), 255, 2)
|
||
|
||
|
||
alfa = theta + alfa
|
||
|
||
alfa = alfa / lines.shape[0]
|
||
|
||
skeleton = rotate_bound(skeleton, np.mod(alfa, 90 / 180 * np.pi) / np.pi * 180) # 摆正图像 角度为正值的时候,是顺时针旋转
|
||
skeleton_ = copy.copy(skeleton)
|
||
# skeleton_[skeleton_ != 0] = 9
|
||
skeleton_ = (skeleton_ / 255 * 9).astype(np.uint8)
|
||
# output = rotate_bound(output, -np.mod(alfa, 90 / 360 * np.pi) / np.pi * 180)
|
||
img_blur = cv2.blur(copy.copy(skeleton_), (3, 3))
|
||
# img_blur = img_blur * 9
|
||
img_blur[img_blur != 2] = 0
|
||
img_blur[img_blur == 2] = 255
|
||
# img_blur[img_blur == 2] = 255
|
||
# img_blur[img_blur != 255] = 0
|
||
img_blur[skeleton == 0] = 0
|
||
corners = np.where(img_blur != 0)
|
||
corners = np.array(corners)
|
||
#
|
||
corners = cv2.goodFeaturesToTrack(skeleton, 50, 0.1, 10)
|
||
corners = np.int0(corners)
|
||
temp_x = []
|
||
temp_y = []
|
||
for i in corners:
|
||
x, y = i.ravel() # x是行,y是列
|
||
temp_x.append(x)
|
||
temp_y.append(y)
|
||
|
||
temp_X = np.array(temp_x)
|
||
temp_Y = np.array(temp_y)
|
||
a = np.min(temp_X)
|
||
b = np.min(temp_Y)
|
||
c = np.max(temp_X)
|
||
d = np.max(temp_Y)
|
||
|
||
cv2.rectangle(temp_outline, (a, b), (c, d), color, -1)
|
||
|
||
temp_outline = rotate_bound(temp_outline, -np.mod(alfa, 90 / 180 * np.pi) / np.pi * 180)
|
||
temp = cv2.cvtColor(temp_outline, cv2.COLOR_BGR2GRAY) # 方便用mask
|
||
temp[temp > 0] = 255
|
||
output[temp_outline > 0] = 0
|
||
mask = 255 == temp
|
||
output[:, :, 0][mask] = color[0]
|
||
output[:, :, 1][mask] = color[1]
|
||
output[:, :, 2][mask] = color[2]
|
||
|
||
continue
|
||
|
||
if (shape == 1):
|
||
# 计算外接矩形
|
||
box = outer_rectangle(obj, size)
|
||
# color = color[::-1]
|
||
|
||
# 画图
|
||
if (size == 0):
|
||
# 外接矩形缩放
|
||
# vertices = shrink_rectangle(box)
|
||
vertices = box
|
||
output = cv2.drawContours(output, [vertices], 0, color, -1, lineType=cv2.LINE_4)
|
||
elif (size == 1):
|
||
# 外接矩形缩放
|
||
# vertices = shrink_rectangle(box)
|
||
vertices = box
|
||
cv2.rectangle(output, (vertices[0, 0], vertices[0, 1]), (vertices[2, 0], vertices[2, 1]), color, -1)
|
||
elif (shape == 0):
|
||
# 计算最小拟合圆
|
||
|
||
circle_x = col
|
||
circle_y = row
|
||
center, radius = fit_circle(circle_x, circle_y)
|
||
# binary, contours, hierarchy = cv2.findContours(obj, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
||
# center, radius = outer_circle(obj)
|
||
cv2.circle(output, center, radius, color, -1)
|
||
# else:
|
||
# ellipse = outer_ellipse(obj)
|
||
# if (len(ellipse) != 0):
|
||
# cv2.ellipse(output, ellipse, color, -1)
|
||
|
||
return output, n
|
||
|
||
# 计算最小外接矩形
|
||
def outer_rectangle(obj, size):
|
||
'''
|
||
. 计算最小外接矩形
|
||
. @param obj 语义物体的位置信息
|
||
. @param size 语义物体绘制轮廓的参数(0代表按轮廓绘制,1代表绘制正矩形)
|
||
'''
|
||
binary, contours, hierarchy = cv2.findContours(obj, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
||
contour = []
|
||
for cont in contours:
|
||
contour.extend(cont)
|
||
if (size == 0):
|
||
min_rect = cv2.minAreaRect(np.array(contour))
|
||
box = cv2.boxPoints(min_rect)
|
||
# box = np.round(box)
|
||
box = np.int0(box)
|
||
|
||
# 排序
|
||
temp = np.where(box == np.min(box[:, 0])) # box的第0列是列,第1列是行
|
||
if temp[0].shape[0] > 1:
|
||
left = np.min(box[:, 0])
|
||
right = np.max(box[:, 0])
|
||
up = np.min(box[:, 1])
|
||
down = np.max(box[:, 1])
|
||
top_point_x = left
|
||
top_point_y = up
|
||
right_point_x = right
|
||
right_point_y = up
|
||
bottom_point_x = right
|
||
bottom_point_y = down
|
||
left_point_x = left
|
||
left_point_y = down
|
||
vertices = np.array(
|
||
[[top_point_x, top_point_y], [right_point_x, right_point_y], [bottom_point_x, bottom_point_y],
|
||
[left_point_x, left_point_y]])
|
||
return vertices
|
||
left_point_x = np.min(box[:, 0])
|
||
right_point_x = np.max(box[:, 0])
|
||
top_point_y = np.min(box[:, 1])
|
||
bottom_point_y = np.max(box[:, 1])
|
||
|
||
left_point_y = box[:, 1][np.where(box[:, 0] == left_point_x)][0]
|
||
right_point_y = box[:, 1][np.where(box[:, 0] == right_point_x)][0]
|
||
top_point_x = box[:, 0][np.where(box[:, 1] == top_point_y)][0]
|
||
bottom_point_x = box[:, 0][np.where(box[:, 1] == bottom_point_y)][0]
|
||
|
||
vertices = np.array(
|
||
[[top_point_x, top_point_y], [right_point_x, right_point_y], [bottom_point_x, bottom_point_y],
|
||
[left_point_x, left_point_y]])
|
||
return vertices
|
||
elif (size == 1):
|
||
x, y, w, h = cv2.boundingRect(np.array(contour))
|
||
vertices = np.array([[x, y], [x + w, y], [x + w, y + h],
|
||
[x, y + h]])
|
||
return vertices
|
||
|
||
# 计算最小拟合椭圆
|
||
def outer_ellipse(obj):
|
||
'''
|
||
. 计算最小拟合椭圆
|
||
. @param obj 语义物体的位置信息
|
||
'''
|
||
binary, contours, hierarchy = cv2.findContours(obj, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
|
||
contour = []
|
||
for cont in contours:
|
||
contour.extend(cont)
|
||
|
||
if (len(contour) < 6):
|
||
ellipse = ()
|
||
else:
|
||
ellipse = cv2.fitEllipse(np.array(contour))
|
||
|
||
return ellipse
|
||
|
||
# 计算最小外接圆
|
||
def outer_circle(obj):
|
||
'''
|
||
. 计算最小外接圆
|
||
. @param obj 语义物体的位置信息
|
||
'''
|
||
binary, contours, hierarchy = cv2.findContours(obj, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
|
||
contour = []
|
||
for cont in contours:
|
||
contour.extend(cont)
|
||
|
||
(x, y), radius = cv2.minEnclosingCircle(np.array(contour))
|
||
|
||
center = (int(round(x)), int(round(y)))
|
||
radius = int(round(radius))
|
||
return center, radius
|
||
|
||
# 计算最小拟合圆
|
||
def calc_R(xc, yc, x, y):
|
||
return np.sqrt((x - xc) ** 2 + (y - yc) ** 2)
|
||
|
||
def f_2(c, x, y):
|
||
Ri = calc_R(*c, x, y)
|
||
|
||
return Ri - Ri.mean()
|
||
|
||
def fit_circle(x, y):
|
||
'''
|
||
. 计算最小外接圆
|
||
. @param x 语义物体的所在列
|
||
. @param x 语义物体的所在行
|
||
'''
|
||
x_m = mean(x)
|
||
y_m = mean(y)
|
||
x = x.ravel()
|
||
y = y.ravel()
|
||
center_estimate = x_m, y_m
|
||
center_2, _ = optimize.leastsq(f_2, center_estimate, args=(x, y))
|
||
xc_2, yc_2 = center_2
|
||
Ri_2 = calc_R(xc_2, yc_2, x, y)
|
||
# 拟合圆的半径
|
||
R_2 = Ri_2.mean()
|
||
center = (int(round(xc_2)), int(round(yc_2)))
|
||
radius = int(round(R_2))
|
||
return center, radius
|
||
|
||
# 外接矩形内缩
|
||
def shrink_rectangle(box):
|
||
'''
|
||
. 外接矩形内缩
|
||
. @param box 语义物体的轮廓信息
|
||
'''
|
||
temp = np.where(box == np.min(box[:, 0])) # box的第0列是列,第1列是行
|
||
if temp[0].shape[0] > 1:
|
||
left = np.min(box[:, 0])
|
||
right = np.max(box[:, 0])
|
||
up = np.min(box[:, 1])
|
||
down = np.max(box[:, 1])
|
||
top_point_x = left + 1
|
||
top_point_y = up + 1
|
||
right_point_x = right - 1
|
||
right_point_y = up + 1
|
||
bottom_point_x = right - 1
|
||
bottom_point_y = down - 1
|
||
left_point_x = left + 1
|
||
left_point_y = down - 1
|
||
vertices = np.array(
|
||
[[top_point_x, top_point_y], [right_point_x, right_point_y], [bottom_point_x, bottom_point_y],
|
||
[left_point_x, left_point_y]])
|
||
return vertices
|
||
|
||
left_point_x = np.min(box[:, 0])
|
||
right_point_x = np.max(box[:, 0])
|
||
top_point_y = np.min(box[:, 1])
|
||
bottom_point_y = np.max(box[:, 1])
|
||
|
||
left_point_y = box[:, 1][np.where(box[:, 0] == left_point_x)][0]
|
||
right_point_y = box[:, 1][np.where(box[:, 0] == right_point_x)][0]
|
||
top_point_x = box[:, 0][np.where(box[:, 1] == top_point_y)][0]
|
||
bottom_point_x = box[:, 0][np.where(box[:, 1] == bottom_point_y)][0]
|
||
|
||
vertices = np.array(
|
||
[[top_point_x, top_point_y], [right_point_x, right_point_y], [bottom_point_x, bottom_point_y],
|
||
[left_point_x, left_point_y]])
|
||
|
||
if top_point_x > bottom_point_x:
|
||
vertices[0, 0] = vertices[0, 0] - 1
|
||
vertices[0, 1] = vertices[0, 1] + 1
|
||
vertices[2, 0] = vertices[2, 0] + 1
|
||
vertices[2, 1] = vertices[2, 1] - 1
|
||
if top_point_x < bottom_point_x:
|
||
vertices[0, 0] = vertices[0, 0] + 1
|
||
vertices[0, 1] = vertices[0, 1] + 1
|
||
vertices[2, 0] = vertices[2, 0] - 1
|
||
vertices[2, 1] = vertices[2, 1] - 1
|
||
if right_point_y > left_point_y:
|
||
vertices[1, 0] = vertices[1, 0] - 1
|
||
vertices[1, 1] = vertices[1, 1] - 1
|
||
vertices[3, 0] = vertices[3, 0] + 1
|
||
vertices[3, 1] = vertices[3, 1] + 1
|
||
if right_point_y < left_point_y:
|
||
vertices[1, 0] = vertices[1, 0] - 1
|
||
vertices[1, 1] = vertices[1, 1] + 1
|
||
vertices[3, 0] = vertices[3, 0] + 1
|
||
vertices[3, 1] = vertices[3, 1] - 1
|
||
return vertices
|
||
|
||
# 添加图例
|
||
def draw_legend(img, item, color, k):
|
||
obj_name = {'115': 'Dog basin', '116': 'Bar chair base', '117': 'Fan base', '118': 'Washing machine',
|
||
'119': 'Refrigerator', '120': 'Toilet', '121': 'Weighing scale', '150': 'Wire', '151': 'TV',
|
||
'152': 'Desk',
|
||
'153': 'Carpet', '154': 'Rag', '155': 'Tea table', '156': 'TV cabinet', '200': 'Slippers',
|
||
'201': 'Sock', '202': 'Wardrobe', '203': 'Bed', '204': 'Sofa', '205': 'Chair', '209': 'Pet feces'}
|
||
color = color[::-1]
|
||
text = obj_name[str(item)]
|
||
font = cv2.FONT_HERSHEY_TRIPLEX
|
||
# cv2.rectangle(img, (output.shape[1] - 140, 10 + k * 17), (output.shape[1] - 120, 20 + k * 17), color, -1)
|
||
# cv2.putText(img, text, (output.shape[1] - 100, 20 + k * 17), font, 0.4, color, 1, cv2.LINE_AA)
|
||
cv2.rectangle(img, (10, 10 + k * 17), (30, 20 + k * 17), color, -1)
|
||
cv2.putText(img, text, (40, 20 + k * 17), font, 0.5, color, 1, cv2.LINE_8)
|
||
return img
|
||
|
||
# 语义物体的强度值
|
||
# obj_value = [152, 121, 200, 115, 205, 117, 203]
|
||
obj_value = [115, 116, 117, 118, 119, 120, 121, 150, 151, 152, 153,
|
||
154, 155, 156, 200, 201, 202, 203, 204, 205, 209]
|
||
# obj_value = [153]
|
||
|
||
obj_legend = []
|
||
# output是最后画上物体形状的总图
|
||
# output = Semantic_map
|
||
# output = np.zeros((map.shape[0], map.shape[1], 3), np.uint8)
|
||
# output[:, :, 0] = map
|
||
# output[:, :, 1] = map
|
||
# output[:, :, 2] = map
|
||
|
||
k = 0
|
||
|
||
output = np.zeros((map.shape[0], map.shape[1], 3), np.uint8)
|
||
legend_color = np.zeros((map.shape[0], map.shape[1], 3), np.uint8)
|
||
# output[:, :, 0] = map
|
||
# output[:, :, 1] = map
|
||
# output[:, :, 2] = map
|
||
|
||
# 对每个物体绘制形状
|
||
for item in iter(obj_value):
|
||
if ((map == item).any()):
|
||
# min_samples, max_eps, shape, size, color = get_parameter(item)
|
||
min_samples, max_eps, shape, size, color, filter_point_num = get_parameter(item, opt)
|
||
# num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(map, connectivity=8)
|
||
|
||
y, x = np.where(map == item) # y是行,x是列
|
||
X = np.zeros((x.shape[0], 2))
|
||
X[:, 0] = y
|
||
X[:, 1] = x
|
||
X = filter_point(X, filter_point_num)
|
||
if ((X.shape[0] == 0) or (min_samples > X.shape[0])):
|
||
continue
|
||
else:
|
||
n = 0
|
||
output, n = draw_outline(X, item, min_samples, max_eps, shape, color, size, filter_point_num, output)
|
||
|
||
if n != 1:
|
||
if item not in obj_legend:
|
||
obj_legend.append(item)
|
||
legend_color = draw_legend(legend_color, item, color, k)
|
||
k = k + 1
|
||
|
||
output = output + legend_color
|
||
# legend_color[legend_color == 0] = 255
|
||
# img1 = cv2.cvtColor(output, cv2.COLOR_BGR2GRAY) # 方便统计尺寸
|
||
|
||
return output
|
||
|
||
|
||
# 场景识别
|
||
def get_labels(img, semantic, opt, img_, map_ori):
|
||
def get_wall_area(map, num_labels, labels, stats, area):
|
||
'''
|
||
. map 获取墙壁的图像
|
||
. stats 连通域信息
|
||
. area 面积
|
||
'''
|
||
temp = []
|
||
for i in range(1, num_labels):
|
||
if stats[i, 4] > area: # 第i个区域的面积大于阈值,则为墙壁
|
||
temp.append(i)
|
||
wall_area = np.zeros((map.shape[0], map.shape[1]), np.uint8)
|
||
for i in range(0, len(temp)):
|
||
mask = labels == temp[i]
|
||
wall_area[:, :][mask] = 255
|
||
return wall_area
|
||
|
||
# def draw_legend(img,scene,color,k):
|
||
# obj_name = {'0':'Dog basin','1':'Fan base','2':'Weighing scale','3':'Desk','4':'Slippers'}
|
||
# color = color[::-1]
|
||
# text = obj_name[str(scene)]
|
||
# font = cv2.FONT_HERSHEY_DUPLEX
|
||
# cv2.rectangle(img, (output.shape[1] - 140, 50+k*17), (output.shape[1] - 120, 60+k*17), color, -1)
|
||
# cv2.putText(img, text, (output.shape[1] - 100, 60+k*17), font, 0.4, color, 1, cv2.LINE_AA)
|
||
# return img
|
||
|
||
def Scene(obj_label):
|
||
'''
|
||
:param obj_label:
|
||
:return: index "bedroom","livingroom","bathroom","kitchen" ,"unknow"
|
||
'''
|
||
Intensity_value = [115, 116, 117, 118, 119, 120, 121, 150, 151, 152, 153,
|
||
154, 155, 156, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209]
|
||
p_sce = np.ones((1, 5)) * 0.25
|
||
p_sce[0][4] = 0
|
||
|
||
p_obj_sce = np.array([[0, 0, 0, 0],
|
||
[0, 0, 0, 0],
|
||
[0, 0, 0, 0],
|
||
[0.01, 0.04, 0.8, 0],
|
||
[0.02, 0.2, 0, 0.8],
|
||
[0, 0, 0.99, 0],
|
||
[0, 0, 0, 0],
|
||
[0, 0, 0, 0],
|
||
[0.4, 0.4, 0, 0],
|
||
[0.2, 0.4, 0, 0],
|
||
[0, 0, 0, 0],
|
||
[0, 0, 0, 0],
|
||
[0.1, 0.4, 0, 0],
|
||
[0.4, 0.6, 0, 0],
|
||
[0, 0, 0, 0],
|
||
[0, 0, 0, 0],
|
||
[0.8, 0, 0, 0],
|
||
[0.99, 0, 0, 0],
|
||
[0.05, 0.5, 0, 0],
|
||
[0, 0, 0, 0],
|
||
[0, 0, 0, 0],
|
||
[0, 0, 0, 0],
|
||
[0, 0, 0, 0]
|
||
|
||
])
|
||
p_temp = 1.0
|
||
p_obj = 0.3 # 目标检测出的置信度
|
||
pre_scene = np.zeros((1, 5))
|
||
if (len(obj_label) == 0):
|
||
pre_scene[0][4] = 1
|
||
else:
|
||
for i in range(4):
|
||
for j in range(len(obj_label)):
|
||
k = obj_label[j]
|
||
sum_temp = np.sum(p_obj_sce[k])
|
||
if (sum_temp == 0):
|
||
pre_scene[0][4] = 1
|
||
continue
|
||
m = p_obj_sce[k, i]
|
||
p_temp = (1.0 - (m / sum_temp * p_obj)) * p_temp
|
||
pre_scene[0][i] = 1 - p_temp
|
||
p_temp = 1.0
|
||
if np.max(pre_scene[0, 0:4]) > 0.1:
|
||
pre_scene[0][4] = 0
|
||
sce_index = np.argmax(pre_scene)
|
||
return sce_index
|
||
|
||
def connect(pic, opt):
|
||
hahaha = copy.copy(pic)
|
||
|
||
# hahaha[hahaha == 0] = 254
|
||
# hahaha[hahaha == 255] = 0
|
||
hahaha[hahaha == 255] = 1
|
||
|
||
skeleton0 = morphology.skeletonize(hahaha)
|
||
skeleton_ = skeleton0.astype(np.uint8) * 9
|
||
skeleton = skeleton0.astype(np.uint8) * 255
|
||
img_blur = cv2.blur(copy.copy(skeleton_), (3, 3))
|
||
# img_blur = img_blur * 9
|
||
img_blur[img_blur != 2] = 0
|
||
img_blur[img_blur == 2] = 255
|
||
img_blur[skeleton_ == 0] = 0
|
||
corners = np.where(img_blur != 0)
|
||
corners = np.array(corners)
|
||
|
||
# corners = cv2.goodFeaturesToTrack(skeleton, 200, 0.01, 3)
|
||
# corners = np.int0(corners)
|
||
# skeleton = skeleton / 255
|
||
# kernel = np.ones((1, 9))
|
||
temp_x = []
|
||
temp_y = []
|
||
for i in range(corners.shape[1]):
|
||
x = corners[0, i]
|
||
y = corners[1, i]
|
||
# cov_corner = np.array([[skeleton[y - 1, x - 1], skeleton[y, x - 1], skeleton[y + 1, x - 1]],
|
||
# [skeleton[y - 1, x], skeleton[y, x], skeleton[y + 1, x]],
|
||
# [skeleton[y - 1, x + 1], skeleton[y, x + 1], skeleton[y + 1, x + 1]]])
|
||
# cov_corner[cov_corner > 0] = 1
|
||
# cov_corner = cov_corner.reshape(9, 1)
|
||
|
||
# a3 = np.dot(kernel, cov_corner)
|
||
# if a3 == 2:
|
||
temp_x.append(x)
|
||
temp_y.append(y)
|
||
cv2.circle(skeleton, (y, x), 3, 255, -1)
|
||
|
||
|
||
|
||
temp_X = np.array(temp_x)
|
||
temp_Y = np.array(temp_y)
|
||
temp = np.vstack((temp_X, temp_Y)).transpose()
|
||
distance = 10000 * np.ones((temp.shape[0], temp.shape[0]))
|
||
for i in range(temp.shape[0]):
|
||
for j in range(i, temp.shape[0]):
|
||
distance[i, j] = np.sqrt((temp[i][0] - temp[j][0]) ** 2 + (temp[i][1] - temp[j][1]) ** 2)
|
||
distance[distance == 0] = 10000
|
||
if distance[i, j] < opt.distance:
|
||
# z = np.argmin(distance[i, :])
|
||
cv2.line(pic, (temp[i, 1], temp[i, 0]), (temp[j, 1], temp[j, 0]), 255, 3)
|
||
|
||
return pic
|
||
|
||
# 计算最小外接矩形
|
||
|
||
def outer_rectangle(obj):
|
||
'''
|
||
. 计算最小外接矩形
|
||
. @param obj 语义物体的位置信息
|
||
. @param size 语义物体绘制轮廓的参数(0代表按轮廓绘制,1代表绘制正矩形)
|
||
'''
|
||
binary, contours, hierarchy = cv2.findContours(obj, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
||
contour = []
|
||
for cont in contours:
|
||
contour.extend(cont)
|
||
|
||
min_rect = cv2.minAreaRect(np.array(contour))
|
||
box = cv2.boxPoints(min_rect)
|
||
# box = np.round(box)
|
||
box = np.int0(box)
|
||
|
||
# 排序
|
||
temp = np.where(box == np.min(box[:, 0])) # box的第0列是列,第1列是行
|
||
if temp[0].shape[0] > 1:
|
||
left = np.min(box[:, 0])
|
||
right = np.max(box[:, 0])
|
||
up = np.min(box[:, 1])
|
||
down = np.max(box[:, 1])
|
||
top_point_x = left
|
||
top_point_y = up
|
||
right_point_x = right
|
||
right_point_y = up
|
||
bottom_point_x = right
|
||
bottom_point_y = down
|
||
left_point_x = left
|
||
left_point_y = down
|
||
vertices = np.array(
|
||
[[top_point_x, top_point_y], [right_point_x, right_point_y], [bottom_point_x, bottom_point_y],
|
||
[left_point_x, left_point_y]])
|
||
return vertices
|
||
left_point_x = np.min(box[:, 0])
|
||
right_point_x = np.max(box[:, 0])
|
||
top_point_y = np.min(box[:, 1])
|
||
bottom_point_y = np.max(box[:, 1])
|
||
|
||
left_point_y = box[:, 1][np.where(box[:, 0] == left_point_x)][0]
|
||
right_point_y = box[:, 1][np.where(box[:, 0] == right_point_x)][0]
|
||
top_point_x = box[:, 0][np.where(box[:, 1] == top_point_y)][0]
|
||
bottom_point_x = box[:, 0][np.where(box[:, 1] == bottom_point_y)][0]
|
||
|
||
vertices = np.array(
|
||
[[top_point_x, top_point_y], [right_point_x, right_point_y], [bottom_point_x, bottom_point_y],
|
||
[left_point_x, left_point_y]])
|
||
return vertices
|
||
|
||
img1 = cv2.cvtColor(semantic, cv2.COLOR_BGR2GRAY) # 方便统计尺寸
|
||
|
||
img1[img1 > 0] = 1 # 提取语义
|
||
img2 = img * img1 # 提取语义
|
||
|
||
Intensity_value = [115, 116, 117, 118, 119, 120, 121, 150, 151, 152, 153,
|
||
154, 155, 156, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209]
|
||
'只保留墙壁空间'
|
||
temp = copy.copy(img)
|
||
temp[temp == 0] = 254
|
||
temp[temp == 255] = 0
|
||
temp[temp == 254] = 255
|
||
temp[temp < 254] = 0
|
||
|
||
img3 = copy.copy(temp) # 提取非语义非墙壁区域
|
||
img3[img3 > 0] = 1
|
||
img3[img1 > 0] = 0
|
||
|
||
Semantic_map = np.zeros((img.shape[0], img.shape[1], 3), np.uint8)
|
||
temp = temp.astype(np.uint8)
|
||
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(temp, connectivity=8)
|
||
wall_area = get_wall_area(img, num_labels, labels, stats, opt.length)
|
||
|
||
img_[img_ == 0] = 254
|
||
img_[img_ == 255] = 0
|
||
img_[img_ == 254] = 255
|
||
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(img_, connectivity=8)
|
||
wall_area_ = get_wall_area(img_, num_labels, labels, stats, opt.length)
|
||
"pic 为分割区域的结果,作为一张区域分割后的地图,将分割结果传给后续场景识别,场景识别结果绘制在图Semantic_map,"
|
||
pic = copy.copy(wall_area_)
|
||
pic = connect(pic, opt)
|
||
img3[wall_area > 0] = 0
|
||
img3 = img3 * 255
|
||
img3[img3 == 0] = 254
|
||
img3[img3 == 255] = 0
|
||
img3[img3 == 254] = 255
|
||
|
||
wall_area[wall_area == 0] = 254
|
||
wall_area[wall_area == 255] = 0
|
||
wall_area[wall_area == 254] = 255
|
||
|
||
pic[pic == 0] = 254
|
||
pic[pic == 255] = 0
|
||
pic[pic == 254] = 255
|
||
wall_area_color = np.zeros((wall_area.shape[0], wall_area.shape[1], 3), np.uint8)
|
||
wall_area_color[:, :, 0] = wall_area
|
||
wall_area_color[:, :, 1] = wall_area
|
||
wall_area_color[:, :, 2] = wall_area
|
||
'提取房间'
|
||
|
||
room_num_labels, room_labels, room_stats, room_centroids = cv2.connectedComponentsWithStats(pic,
|
||
connectivity=8)
|
||
k = 0
|
||
scene_legend = []
|
||
|
||
for i in range(2, room_num_labels):
|
||
if room_stats[i, 4] < 200:
|
||
continue
|
||
room = np.zeros((wall_area.shape[0], wall_area.shape[1]))
|
||
obj_label = []
|
||
mask = room_labels == i
|
||
room[:, :][mask] = 1
|
||
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
|
||
room = cv2.dilate(room, kernel, iterations=1)
|
||
room_temp = copy.copy(room)
|
||
room_temp = room_temp.astype(np.uint8)
|
||
|
||
room_box = outer_rectangle(room_temp)
|
||
room_outline_RGB = np.zeros((room_temp.shape[0], room_temp.shape[1], 3), np.uint8)
|
||
room_outline_RGB = cv2.drawContours(room_outline_RGB, [room_box], 0, (0, 255, 0), -1, lineType=cv2.LINE_4)
|
||
room_outline = cv2.cvtColor(room_outline_RGB, cv2.COLOR_BGR2GRAY)
|
||
room_outline[room_outline > 0] = 1
|
||
room = room_outline
|
||
# Semantic_area = room_outline * img2
|
||
Semantic_area = room * img2
|
||
Semantic_area = list(Semantic_area.flatten())
|
||
Semantic_area = list(set(Semantic_area))
|
||
Semantic_area.sort()
|
||
for i in range(len(Semantic_area)):
|
||
if Semantic_area[i] in Intensity_value:
|
||
obj_label.append(Intensity_value.index(Semantic_area[i]))
|
||
# obj_label_test = [] # 用于测试
|
||
# cv2.imshow("room",room*255)
|
||
# cv2.waitKey(0)
|
||
scene = Scene(obj_label)
|
||
if scene == 0:
|
||
Semantic_map[:, :, 0][room > 0] = 70
|
||
Semantic_map[:, :, 1][room > 0] = 80
|
||
Semantic_map[:, :, 2][room > 0] = 90
|
||
color = [70, 80, 90]
|
||
if scene == 1:
|
||
Semantic_map[:, :, 0][room > 0] = 100
|
||
Semantic_map[:, :, 1][room > 0] = 180
|
||
Semantic_map[:, :, 2][room > 0] = 120
|
||
color = [100, 180, 120]
|
||
if scene == 2:
|
||
Semantic_map[:, :, 0][room > 0] = 210
|
||
Semantic_map[:, :, 1][room > 0] = 67
|
||
Semantic_map[:, :, 2][room > 0] = 170
|
||
color = [210, 67, 170]
|
||
if scene == 3:
|
||
Semantic_map[:, :, 0][room > 0] = 150
|
||
Semantic_map[:, :, 1][room > 0] = 48
|
||
Semantic_map[:, :, 2][room > 0] = 88
|
||
color = [150, 48, 88]
|
||
# if scene == 4:
|
||
# Semantic_map[:, :, 0][mask] = 134
|
||
# Semantic_map[:, :, 1][mask] = 231
|
||
# Semantic_map[:, :, 2][mask] = 143
|
||
# color = [134, 231, 143]
|
||
# if scene not in scene_legend:
|
||
# scene_legend.append(scene)
|
||
# Semantic_map = draw_legend(Semantic_map, scene, color, k)
|
||
# k = k + 1
|
||
# img3[img3 > 0] = 255
|
||
|
||
Semantic_map = Semantic_map + wall_area_color
|
||
Semantic_map[img1 > 0] = 0
|
||
# semantic[img1 < 1] = 0
|
||
Semantic_map = Semantic_map + semantic
|
||
Semantic_map[img3 == 0] = 0
|
||
|
||
p = cv2.cvtColor(copy.copy(Semantic_map), cv2.COLOR_BGR2GRAY) # 方便统计尺寸
|
||
|
||
map_ori_RGB = np.zeros((map_ori.shape[0], map_ori.shape[1], 3), np.uint8)
|
||
map_ori_RGB[:, :, 0][map_ori > 0] = 255
|
||
map_ori_RGB[:, :, 1][map_ori > 0] = 255
|
||
map_ori_RGB[:, :, 2][map_ori > 0] = 255
|
||
map_ori[p > 0] = 0
|
||
map_ori_RGB = map_ori_RGB + Semantic_map
|
||
map_ori_RGB[img1 > 0] = 0
|
||
map_ori_RGB = map_ori_RGB + semantic
|
||
map_ori_RGB[img3 == 0] = 0
|
||
return map_ori_RGB
|
||
|
||
|
||
if __name__ == "__main__":
|
||
img = cv2.imread("path/map/map6.png", 0)
|
||
cv2.flip(img, 0, img) # 图片翻转
|
||
map, map_, map_ori = process_map(img, opt) # map:仅把门连起来; map_:把门连起来,成片语义点当成墙; map_ori: 无处理原图
|
||
# map_test = cv2.imread("mappp.jpg", 0)
|
||
output = obj_outline(map_ori, opt, map_ori) # 参考map,画map_ori上
|
||
Semantic_map = get_labels(map, output, opt, map_, map_ori)
|
||
cv2.imwrite("/path/result/Semantic_map.png",Semantic_map)
|
||
cv2.imshow("Semantic_map",Semantic_map)
|
||
cv2.waitKey(0) |