def processImage(pixels): ''' #filename = 'images/3_1.png' Image.open(filename) img = Image.open(filename).convert('L') ''' h, w = pixels.shape ''' pixels = img.load() pixels = np.reshape([pixels[i, j] for j in range(h) for i in range(w)], (h, w)) ''' '''БИНАРИЗАЦИЯ''' Binarization.binarize(pixels) # image.imsave('debug228.png', pixels, vmin=0, vmax=255, cmap="gray", origin='upper') '''СКЕЛЕТИЗАЦИЯ''' Sceletonization.thinning(pixels, w, h) '''ВЫДЕЛЕНИЕ КЛЮЧЕВЫХ ПИКСЕЛЕЙ''' keyPixels = FeatureExtraction.keyPixels( np.array([[Utils.bin_px(pixels[i, j]) for j in range(w)] for i in range(h)]), w, h) keyMatrix = Utils.matrix_by_xy(keyPixels, h, w) FeatureExtraction.reduceKeyPixelBlobs( keyPixels, keyMatrix) #TODO поменять на итерационный vectorPoints = [] bendPixels = FeatureExtraction.computeBendPoints(pixels, keyPixels, vectorPoints) '''ПОСТРОЕНИЕ СОЕДИНИТЕЛЬНЫХ РЁБЕР''' k = 0 for i in vectorPoints: k += 1 blackPixels = Utils.xy_from_matrix( np.array([[Utils.bin_px(pixels[i, j]) for j in range(w)] for i in range(h)]), h, w) startPoints = keyPixels + bendPixels tempKeyPixels = [] for i in GraphUtils.leeAlgorithm(startPoints, blackPixels): tempKeyPixels.append(list(map(lambda _: _.coord, i))) edges = [] for i in tempKeyPixels: if not (i[::-1] in edges or i in edges): edges.append(i) r = 0 for i in edges: r += 1 # Ищем коэффициенты изгиба coefficient = [] for i in edges: x1 = i[0][0] x2 = i[-1][0] y1 = i[0][1] y2 = i[-1][1] d = np.sqrt((x1 - x2)**2 + (y1 - y2)**2) p = GraphUtils.fullLen(i) / d coefficient.append(p) vectors = [] for i in range(len(edges)): vector = np.array((0., 0.)) for t in range(len(edges[i]) - 1): j = np.array(edges[i][t]) k = np.array(edges[i][t + 1]) vector += (k - j) * 2**-t vectors.append(vector) '''ПОСТРОЕНИЕ МОДЕЛИ''' def threeInARow(points): for first in range(len(points) - 2): for last in range(2, len(points)): for mid in range(first + 1, last): if Line(0, xy1=points[first], xy2=points[last]).on_line(points[mid]): return True return False def intersection_line_segment(A, B, C, M1, M2): temp1 = A * M1[0] + B * M1[1] + C temp2 = A * M2[0] + B * M2[1] + C return temp1 * temp2 < 0 def approximation(edges, vectors, i, P_list, S_list, O_list): O = edges[i][0] S = edges[i][-1] OM = vectors[i] OS = (S[0] - O[0], S[1] - O[1]) c = np.sqrt((O[0] - S[0])**2 + (O[1] - S[1])**2) length = GraphUtils.fullLen(edges[i]) cos_alpha = (OM[0] * OS[0] + OM[1] * OS[1]) / ( np.sqrt(OM[0]**2 + OM[1]**2) * np.sqrt(OS[0]**2 + OS[1]**2)) if cos_alpha != 1: a = (c**2 - length**2) / (2 * (c * cos_alpha - length)) cos_beta = OM[0] / np.sqrt(OM[0]**2 + OM[1]**2) sin_beta = np.sqrt(1 - cos_beta**2) delta_x = a * cos_beta delta_y = a * sin_beta P = O[0] + delta_x, O[1] + delta_y OP = P[0] - O[0], P[1] - O[1] # С ОТРАЖЕНИЕМ if (OS[0] * OM[1] - OS[1] * OM[0]) * (OS[0] * OP[1] - OS[1] * OP[0]) >= 0: P_list.append(P) S_list.append(S) O_list.append(O) else: S_list.append(S) O_list.append(O) # TODO: отражение точки относительно отрезка temp_line = Line(0, xy1=O, xy2=S) A, B, C = temp_line.A, temp_line.B, temp_line.C first_matrix = np.array([[A, B], [B, -A]], dtype=np.float32) second_vector = np.array([-C, B * P[0] - A * P[1]], dtype=np.float32) x1, y1 = np.linalg.solve(first_matrix, second_vector) P = (2 * x1 - P[0], 2 * y1 - P[1]) P_list.append(P) else: P_list.append(edges[i][len(edges[i]) // 2]) O_list.append(O) S_list.append(S) def fivePointsToConic(points, f=1.0): from numpy.linalg import lstsq x = points[:, 0] y = points[:, 1] if max(x.shape) < 5: raise ValueError('Need >= 5 points to solve for conic section') A = np.vstack([x**2, x * y, y**2, x, y]).T fullSolution = lstsq(A, f * np.ones(x.size)) (a, b, c, d, e) = fullSolution[0] return (a, b, c, d, e, f) P_list = [] S_list = [] O_list = [] ellipses = [] for i in range(len(edges)): # Геометрия if coefficient[i] >= 1.1 or len( edges[i]) < 5 or threeInARow(edges[i][:3] + edges[i][:-3:-1]): approximation(edges, vectors, i, P_list, S_list, O_list) # Эллипсы и матан else: if len(edges[i]) >= 5: vector_a = [ edges[i][0], edges[i][len(edges[i]) // 4], edges[i][len(edges[i]) // 2], edges[i][len(edges[i]) // 4 * 3], edges[i][-1] ] try: max_V = fivePointsToConic(np.array(vector_a)) except: print("shit") if max_V[1]**2 / 4 - max_V[0] * max_V[2] < 0: ellipses.append(MyEllipsis(max_V)) ellipses[-1].set_interval(edges[i][0], edges[i][-1], edges[i][len(edges[i]) // 2]) else: approximation(edges, vectors, i, P_list, S_list, O_list) OPS_points = list(zip(O_list, P_list, S_list)) # # print(key_pixels) #PlotModel(segments=segments, arcs=ellipses_dict, keyPoints=keyPixels, # lines=lines_dict, intersections=[]) '''ВЫДЕЛЕНИЕ ВЕКТОРА''' line = [] featureVector = [] x = step y = step while x < 100: line.append([Line(1, A=1, B=0, C=-(w / 100) * x)]) x += step while y < 100: line.append([Line(1, A=0, B=1, C=-(h / 100) * y)]) y += step for it in line: A, B, C = it[0].A, it[0].B, it[0].C it.append(0) featureVector.append(0) for ell in ellipses: crossings = ell.crossings(A, B, C) it[-1] += crossings featureVector[-1] += crossings for O, P, S in OPS_points: if intersection_line_segment(A, B, C, O, P): it[-1] += 1 featureVector[-1] += 1 if intersection_line_segment(A, B, C, P, S): it[-1] += 1 featureVector[-1] += 1 segments = [[O, P] for O, P, _ in OPS_points] + [[S, P] for _, P, S in OPS_points] ellipses_dict = list(map(lambda _: _.as_dict(), ellipses)) lines_dict = list(map(lambda _: _[0].as_dict(), line)) return featureVector