def is_coord_border_simplify(tf_map, coord, width, height, n, k, hard_check): ''' 주어진 coord 좌표가 한 contours의 외곽인지 ( 따라서 이어줘야 하는 것인지 ) 판별 하는 함수. ''' count = 0 for diff in [(0, 1), (0, -1), (1,0), (-1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1)]: if utility.can_go(coord[0], coord[1], width, height, x_diff=diff[0], y_diff=diff[1]): count += 1 if count < 2: return True lu = 0 ru = 0 ld = 0 rd = 0 for y_diff in range(-1 * n, n): for x_diff in range(-1 * n, n): if utility.can_go(coord[0], coord[1], width, height, x_diff=x_diff, y_diff=y_diff): if tf_map[coord[1] + y_diff][coord[0] + x_diff]: if y_diff > 0: if x_diff > 0: rd += 1 else: ld += 1 else: if x_diff > 0: ru += 1 else: lu += 1 return abs(rd - ld) > k and abs(ru - lu) > k and abs(ru - rd) > k and abs(lu - ld) > k
def select_outside_pixel(divided_class, selected_class, width, height, x, y, n): # 주어진 경계에 대해서 만약 거리 안에 있다면 그 class로 변환. for x_diff in range(-1*n, n+1, 1): for y_diff in range(-1*n, n+1, 1): if utility.can_go(x, y, width, height, x_diff=x_diff, y_diff=y_diff): if utility.get_pixel_distance((x, y), (x + x_diff, y + y_diff)) <= n: divided_class[y + y_diff][x + x_diff] = selected_class
def is_coord_border(tf_map, coord, width, height, n, k, hard_check=False): ''' 주어진 coord 좌표가 한 contours의 외곽인지 ( 따라서 이어줘야 하는 것인지 ) 판별 하는 함수. ''' check_lr = False # Left and Right Check. check_ud = False # Up and Down check. l_count = 0 # Left Coord number. r_count = 0 # Right Coord number. u_count = 0 # Up Coord number. d_count = 0 # Down Coord number. # Check LR for y_diff in range(-1 * n , n): for x_diff in range(-1 * n, 0): if utility.can_go(coord[0], coord[1], width, height, x_diff=x_diff, y_diff=y_diff): if tf_map[coord[1] + y_diff][coord[0] + x_diff]: # 해당 좌표로 이동 가능하면서, 해당 좌표의 값이 True 인 경우, l_count += 1 for y_diff in range(-1 * n , n): for x_diff in range(1, n + 1): if utility.can_go(coord[0], coord[1], width, height, x_diff=x_diff, y_diff=y_diff): if tf_map[coord[1] + y_diff][coord[0] + x_diff]: # 해당 좌표로 이동 가능하면서, 해당 좌표의 값이 True 인 경우, r_count += 1 # Check UD for x_diff in range(-1 * n , n): for y_diff in range(-1 * n, 0): if utility.can_go(coord[0], coord[1], width, height, x_diff=x_diff, y_diff=y_diff): if tf_map[coord[1] + y_diff][coord[0] + x_diff]: # 해당 좌표로 이동 가능하면서, 해당 좌표의 값이 True 인 경우, u_count += 1 for x_diff in range(-1 * n , n): for y_diff in range(1, n + 1): if utility.can_go(coord[0], coord[1], width, height, x_diff=x_diff, y_diff=y_diff): if tf_map[coord[1] + y_diff][coord[0] + x_diff]: # 해당 좌표로 이동 가능하면서, 해당 좌표의 값이 True 인 경우, d_count += 1 check_lr = abs(l_count - r_count) < k check_ud = abs(u_count - d_count) < k # hard_check가 체크되어 있다면, 두 조건을 모두 달성해야 True, 아니라면 둘 중 하나만 달성해도 괜찮음. # 외곽이라면 True 아니면 False를 Return 해야하므로, not을 붙여준다. if hard_check: return not( check_lr and check_ud ) else: return not( check_lr or check_ud )
def find_adjac_class_number(divided_class, class_border, width, height): # 근처의 인접한 class number를 return. ret_class_number = [] for c in class_border: for direction in range(0, 4): if utility.can_go(c[0], c[1], width, height, direction=direction): if divided_class[c[1] + utility.dir_y[direction]][c[0] + utility.dir_x[direction]] not in ret_class_number: ret_class_number.append(divided_class[c[1] + utility.dir_y[direction]][c[0] + utility.dir_x[direction]]) return ret_class_number
def is_border(divided_class, coord, width, height): # Check if given coord is outside of area. # 단순히 외곽에 0이 있으면 외곽점으로 본다. neighbor_list = [] for direction in range(4): if utility.can_go(coord[0], coord[1], width, height, direction=direction): neighbor = divided_class[coord[1] + utility.dir_y[direction]][coord[0] + utility.dir_x[direction]] if neighbor not in neighbor_list: neighbor_list.append(neighbor) return len(neighbor_list) > 1
def get_around_pixel_list(divided_class, width, height, w, h): class_kind = [] class_number = [] class_coord = [] for diff in [(0, -1), (0, 1), (1, -1), (1, 0), (1, 1), (-1, -1), (-1, 0), (-1, 1)]: if utility.can_go(w, h, width, height, x_diff=diff[0], y_diff=diff[1]): if divided_class[h + diff[1]][w + diff[0]] in class_kind: class_number[class_kind.index(divided_class[h + diff[1]][w + diff[0]])] += 1 class_coord[class_kind.index(divided_class[h + diff[1]][w + diff[0]])].append((w + diff[0], h + diff[1])) else: class_kind.append(divided_class[h + diff[1]][w + diff[0]]) class_number.append(0) class_coord.append([(w + diff[0], h + diff[1])]) return class_kind, class_number, class_coord
def bfs(mask, visited, start_index, img_size, masking_function=isTrue): ''' mask 되어있는 영역 내에서, divided_class 내부에서 연결된 모든 좌표의 coord와 경계의 coord를 return. ''' count = 1 que = [(start_index[0], start_index[1])] total_coord = [] boundary_coordinate = [] # BFS로 Mask 처리하기. while que: now = que[0] del que[0] # 방문한 곳은 방문하지 않음. if visited[now[1]][now[0]]: continue # Class Dividing 처리. visited[now[1]][now[0]] = True if masking_function(mask[now[1]][now[0]]): total_coord.append(now) count += 1 # 경계를 체크하기 위한 Flag zero_boundary = False for direction in range(0, 4): # 해당 방향으로 갈 수 있고, mask 가 칠해진 곳이라면, queue 에 집어넣는다. if utility.can_go(now[0], now[1], img_size[0], img_size[1], direction=direction): if masking_function(mask[now[1] + utility.dir_y[direction]][now[0] + utility.dir_x[direction]]): que.append((now[0] + utility.dir_x[direction], now[1] + utility.dir_y[direction])) else: # 근처에 0 Class ( 아무것도 없는 공간 == mask[x][y] 가 Flase ) 가 있다면, 경계선이다. zero_boundary = True if zero_boundary: boundary_coordinate.append(now) return total_coord, boundary_coordinate, count
def divided_into_classed_color_based(image, divided_class, class_total, class_number_max, width, height, div_threshold=60): ''' Image의 색을 기준으로, 현재 주어진 Class Total의 Pixel들을 Clustering 한다. 나눠진 class_number는 class_number_max + 1 부터 차례로 부여된다. 만약 색상이 크게 차이나지 않는다면 나누지 않음. image : 색을 참조할 Image. class_total : 나눌 Coord List. class_number_max : 부여할 Class Number 기준. div_threshold : 나눌 Color Space Diff 기준. ''' # Get each pixel`s colors. tf_map = utility.make_tf_map([class_total], width, height, border=False) total_length = len(class_total) visited = [False for _ in range(total_length)] visited[0] = True class_index_divided = [[0]] class_total_divided = [[class_total[0]]] class_index = [-1 for _ in range(total_length)] class_index[0] = 0 now_class_index_max = 1 tf_map[class_total[0][1]][class_total[0][0]] = False for i in range(total_length - 1): for direction in range(4): if utility.can_go(class_total[i][0], class_total[i][1], width, height, direction=direction): x = class_total[i][0] + utility.dir_x[direction] y = class_total[i][1] + utility.dir_y[direction] if not tf_map[y][x]: continue tf_map[y][x] = False j = class_total.index((x, y)) if utility.get_cielab_distance( image[y][x], image[class_total[i][1]][ class_total[i][0]]) < div_threshold: class_index_divided[class_index[i]].append(j) class_total_divided[class_index[i]].append(class_total[j]) class_index[j] = class_index[i] else: class_index_divided.append([j]) class_total_divided.append([class_total[j]]) class_index[j] = now_class_index_max now_class_index_max += 1 class_number = [ class_number_max + i for i in range(1, now_class_index_max + 1) ] for i in range(len(class_number)): matrix_processing.set_area(divided_class, class_total_divided[i], class_number[i]) class_border = [ matrix_processing.check_border(divided_class, class_total_divided[i], width, height) for i in range(len(class_number)) ] class_count = [ len(class_total_divided[i]) for i in range(len(class_number)) ] return class_number, class_total_divided, class_border, class_count