import copy import math import cv2 import numpy as np from matplotlib import pyplot from numpy import where, mean from scipy import optimize from sklearn.cluster import OPTICS from config import opt # 图片预处理 def process_map(img, opt): def get_wall_area(map, stats, area): ''' . map 获取墙壁的图像 . stats 连通域信息 . area 面积 ''' 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): ''' . map 获取墙壁的图像 . stats 连通域信息 . area 面积 ''' 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_rotate_angle(wall_area, length, opt): edges = cv2.Canny(wall_area, 50, 150, apertureSize=3) lines = cv2.HoughLines(edges, 1, np.pi / 180, length) # output = np.zeros((img.shape[0], img.shape[1], 3), np.uint8) 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 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 # print(theta) # cv2.line(output, (x1, y1), (x2, y2), (0, 0, 255), 2) wall_area_ = rotate_bound(wall_area, -np.mod(theta, 90 / 360 * np.pi) / 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, np.mod(theta, 90 / 360 * np.pi) / np.pi * 180) # cv2.namedWindow("wall", 0) # cv2.imshow("wall", output) # cv2.waitKey(0) alfa = alfa / lines.shape[0] print(alfa) # cv2.namedWindow("wall", 0) # cv2.imshow("wall", output) # cv2.waitKey(0) return connect_line_ 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)) map = 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))] ''' 去掉未占用区域 ''' 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) # print(Yi) if len(Yi[0]) >= m: # 可调整 (墙壁长度) for j in range(0, len(Yi[0]) - 1): if Yi[0][j + 1] - Yi[0][j] <= k: img[i, 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, 1.2) '插值处理,提高分辨率' map = cv2.resize(map, (map.shape[1] * 2, map.shape[0] * 2), interpolation=cv2.INTER_NEAREST) num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(map, connectivity=8) wall_area = get_wall_area(map, stats, opt.acreage) # 获取墙壁区域 NON_wall_area = get_NONwall_area(map, stats, opt.acreage) NON_wall_area = NON_wall_area / 255 NON_wall_area = NON_wall_area * map 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) # 连接 # 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) connect_line_[connect_line_ < 150] = 0 connect_line_[connect_line_ > 0] = 255 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 # result = filter_wrong_point(result, Intensity_value) # output_rgb = draw_rgb(NON_wall_area) # connect_line_rgb = np.zeros((map.shape[0], map.shape[1], 3), np.uint8) # connect_line_rgb[:, :, 0] = copy.copy(connect_line_) # connect_line_rgb[:, :, 1] = copy.copy(connect_line_) # connect_line_rgb[:, :, 2] = copy.copy(connect_line_) # connect_line_rgb[connect_line_rgb < 65] = 0 # result_rgb = connect_line_rgb + output_rgb # cv2.namedWindow("input_map", 0) # cv2.imshow("input_map", map) # cv2.namedWindow("wall", 0) # cv2.imshow("wall", connect_line) # cv2.namedWindow("map", 0) # cv2.imshow("map", map) # cv2.namedWindow("output", 0) # cv2.imshow('output', result_rgb) # cv2.namedWindow("result", 0) # cv2.imshow('result', result) # cv2.waitKey() # cv2.destroyAllWindows() # cv2.imwrite("result_rgb.png", result_rgb) cv2.imwrite("result.png", result) return result # 绘制物体形状 def obj_outline(map, Semantic_map, opt): ''' . 绘制物体形状 . @param map 语义地图 . @param Semantic_map 场景分类图 . @param opt 参数 ''' # 根据不同语义物体得到不同参数 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] return min_samples, max_eps, shape, size, color # 画物体轮廓 def draw_outline(X, item, min_samples, max_eps, shape, color, size, 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: # 获取此群集的示例的行索引,将每个物体从map中提取出来 if (cluster == -1): continue row_ix = where(yhat == cluster) # print(row_ix[0].shape[0]) if row_ix[0].shape[0] <= 1: continue if (item == 115 and row_ix[0].shape[0] <= 2): continue if (item == 116 and row_ix[0].shape[0] <= 4): continue if (item == 117 and row_ix[0].shape[0] <= 4): continue if (item == 118 and row_ix[0].shape[0] <= 2): continue if (item == 119 and row_ix[0].shape[0] <= 2): continue if (item == 120 and row_ix[0].shape[0] <= 2): continue if (item == 121 and row_ix[0].shape[0] <= 4): continue if (item == 150 and row_ix[0].shape[0] <= 4): continue if (item == 151 and row_ix[0].shape[0] <= 4): continue if (item == 152 and row_ix[0].shape[0] <= 4): continue if (item == 153 and row_ix[0].shape[0] <= 2): continue if (item == 154 and row_ix[0].shape[0] <= 2): continue if (item == 155 and row_ix[0].shape[0] <= 2): continue if (item == 156 and row_ix[0].shape[0] <= 2): continue if (item == 200 and row_ix[0].shape[0] <= 2): continue if (item == 201 and row_ix[0].shape[0] <= 2): continue if (item == 202 and row_ix[0].shape[0] <= 2): continue if (item == 203 and row_ix[0].shape[0] <= 2): continue if (item == 204 and row_ix[0].shape[0] <= 2): continue if (item == 205 and row_ix[0].shape[0] <= 2): continue if (item == 209 and row_ix[0].shape[0] <= 2): 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 # cv2.namedWindow("obj", 0) # cv2.imshow('obj',obj) 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) return output # 计算最小外接矩形 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列是行 # print(temp[0].shape[0]) 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 box 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 box 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_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)) print(x, y, radius) return center, radius # 计算最小拟合圆 def calc_R(xc, yc): return np.sqrt((x - xc) ** 2 + (y - yc) ** 2) def f_2(c): Ri = calc_R(*c) return Ri - Ri.mean() def fit_circle(x, y): ''' . 计算最小外接圆 . @param x 语义物体的所在列 . @param x 语义物体的所在行 ''' x_m = mean(x) y_m = mean(y) center_estimate = x_m, y_m center_2, _ = optimize.leastsq(f_2, center_estimate) xc_2, yc_2 = center_2 Ri_2 = calc_R(xc_2, yc_2) # 拟合圆的半径 R_2 = Ri_2.mean() center = (int(round(xc_2)), int(round(yc_2))) radius = int(round(R_2)) print(xc_2, yc_2, radius) return center, radius # 外接矩形内缩 def shrink_rectangle(box): ''' . 外接矩形内缩 . @param box 语义物体的轮廓信息 ''' temp = np.where(box == np.min(box[:, 0])) # box的第0列是列,第1列是行 # print(temp[0].shape[0]) 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]]) # print(vertices) 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', '152': 'Desk', '153': 'Carpet', '154': 'Rag', '155': 'Tea table', '156': 'TV cabinet', '200': 'Slippers', '201': 'Sock', '202': 'Wardrobe', '203': 'Bed', '204': 'Sofa', '205': 'Chair'} color = color[::-1] text = obj_name[str(item)] font = cv2.FONT_HERSHEY_DUPLEX # 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.4, color, 1, cv2.LINE_AA) 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, 206, 207, 208, 209] # obj_value = [152, 117] obj_value = [] 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 # cv2.namedWindow("map", 0) # cv2.imshow("map", map) k = 0 # 对每个物体绘制形状 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 = get_parameter(item, opt) y, x = np.where(map == item) # y是行,x是列 X = np.zeros((x.shape[0], 2)) X[:, 0] = y X[:, 1] = x output = draw_outline(X, item, min_samples, max_eps, shape, color, size, output) if item not in obj_legend: output = draw_legend(output, item, color, k) k = k + 1 img1 = cv2.cvtColor(output, cv2.COLOR_BGR2GRAY) # 方便统计尺寸 return output # 场景识别 def get_labels(img): def get_wall_area(map, 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" ''' print(obj_label) 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.2, 0, 0], [0, 0, 0, 0], [0.2, 0.4, 0, 0.01], [0.01, 0.04, 0.8, 0], [0.02, 0.2, 0, 0.8], [0, 0, 0.99, 0], [0.6, 0.4, 0.1, 0], [0.6, 0.6, 0, 0.1], [0.4, 0.4, 0, 0], [0, 0.4, 0, 0], [0, 0, 0, 0], [0.1, 0.1, 0.2, 0.1], [0.1, 0.7, 0, 0], [0.4, 0.4, 0, 0], [0.45, 0.34, 0.32, 0], [0.27, 0.26, 0, 0], [0.8, 0, 0, 0], [0.99, 0, 0, 0], [0.05, 0.9, 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) print(pre_scene) return sce_index 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 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, stats, 400) wall_area[wall_area == 0] = 254 wall_area[wall_area == 255] = 0 wall_area[wall_area == 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(wall_area, 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 Semantic_area = room * img # cv2.imshow('area', Semantic_area) # cv2.waitKey(1000) 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 = [] # 用于测试 scene = Scene(obj_label) print(scene) # print(obj_label) if scene == 0: Semantic_map[:, :, 0][mask] = 70 Semantic_map[:, :, 1][mask] = 80 Semantic_map[:, :, 2][mask] = 90 color = [70, 80, 90] if scene == 1: Semantic_map[:, :, 0][mask] = 100 Semantic_map[:, :, 1][mask] = 180 Semantic_map[:, :, 2][mask] = 120 color = [100, 180, 120] if scene == 2: Semantic_map[:, :, 0][mask] = 210 Semantic_map[:, :, 1][mask] = 67 Semantic_map[:, :, 2][mask] = 170 color = [210, 67, 170] if scene == 3: Semantic_map[:, :, 0][mask] = 150 Semantic_map[:, :, 1][mask] = 48 Semantic_map[:, :, 2][mask] = 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 Semantic_map = Semantic_map + wall_area_color return Semantic_map if __name__ == "__main__": img = cv2.imread("map.png", 0) cv2.flip(img, 0, img) # 图片翻转 map = process_map(img, opt) ''' 对床、洗衣机和马桶自己赋语义 ''' # 床 map[276:292, 212:224] = 203 map[276:288, 282:296] = 203 map[332:334, 208:210] = 255 map[330:344, 210:220] = 203 map[326:344, 282:294] = 203 # 洗衣机 map[368:392, 438:448] = 118 # 马桶 map[340:356, 428:448] = 120 # 袜子 map[238:244, 531:533] = 201 map[242:244, 529:533] = 201 # 电线 map[259:263, 509:511] = 150 map[261:263, 507:509] = 150 cv2.imwrite("mappp.jpg", map) Semantic_map = get_labels(map) output = obj_outline(map, Semantic_map, opt) cv2.imwrite('output.png', output) cv2.namedWindow("output", 0) cv2.imshow("output", output) cv2.waitKey(0)