def __init__(self, ventana, idioma): """ Constructor de la clase ventana que nos proporciona las inicializaciones de variables y de objetos que vana a ser encesarios para su gestion e implementacion de los metodos que va a contener la ventana. @param ventana: instancia de la clase que crea la ventana. """ self.idioma = idioma if self.idioma == "ESP": self.dic = Diccionario() else: self.dic = DiccionarioING() self.ventana = ventana self.ventana.ax = self.ventana.fig.add_subplot(111) self.procesado = ProcesadoDeImagen() self.procesado_de_lineas = ProcesadoDeLineas() self.img = self.procesado.leer_imagen(self.ventana.path) self.ventana.ax = self.ventana.fig.add_subplot(111) self.ventana.ax.set_xlim([0, self.img.shape[1]]) self.ventana.ax.set_ylim([self.img.shape[0], 0]) self.ventana.ax.imshow(self.img, interpolation=self.dic.md_v_ori) if os.name == 'nt': self.ref_numeros = self.procesado.obtener_numeros(self.img) else: self.ref_numeros = 100 self.color = [] self.ventana.pestannas.button.setEnabled(False) self.ventana.pestannas.button_fijar.setEnabled(False) self.terminar = False self.detectado = True self.automatic_mode = ProcesadoAutomatico()
def __init__(self): """ Constructor de la clase que instancia las clases para aprobechar los metodos ya implementados anteriormente. """ self.proce_lines = ProcesadoDeLineas() self.proce_img = ProcesadoDeImagen()
def test_segmentos_verdad(self): procesado=ProcesadoDeLineas() g=nx.Graph() lines=[((128, 72), (164, 18)), ((24, 43), (12, 31)), ((55, 71), (31, 49)), ((136, 59), (163, 19)), ((11, 31), (4, 24)), ((34, 51), (25, 43)), ((109, 42), (90, 18)), ((51, 67), (30, 48)), ((116, 50), (92, 20))] g=procesado.combina(8, 4, lines, g) k_components = apxa.k_components(g) segmentos_de_verdad = procesado.segmentos_verdad(k_components, lines) self.assertEqual(segmentos_de_verdad,[((164, 18), (128, 72)), ((55, 71), (4, 24)), ((116, 50), (90, 18))]) print("OK,test_segmentos_verdad")
def test_dot(self): procesado=ProcesadoDeLineas() x=(871, 183) y=(892, 183) dot=procesado.dot(x, y) self.assertEqual(dot,810421) try: dot=procesado.dot([], []) except IndexError as ast: self.assertEqual(ast.args[0],'list index out of range') print("OK,test_segments_distance")
def test_segments_intersect(self): procesado=ProcesadoDeLineas() x=((128, 72), (164, 18)) y=((24, 43), (12, 31)) intersec=procesado.segments_intersect(x, y) self.assertEqual(intersec,False) y=((18, 164), (128, 72)) intersec=procesado.segments_intersect(x, y) self.assertEqual(intersec,True) try: intersec=procesado.segments_intersect(0,0) except TypeError as ex: self.assertEqual(ex.args[0],'\'int\' object is not iterable') print("OK,test_segments_intersect")
def test_combina_segmentos(self): procesado=ProcesadoDeLineas() segmentos=[((128, 72), (164, 18)), ((136, 59), (163, 19))] combinado=procesado.combina_segmentos(segmentos) self.assertEqual(combinado,((164, 18), (128, 72))) segmentos=[((670, 196), (661, 185)), ((680, 209), (674, 201)), ((685, 215), (681, 210)), ((677, 206), (659, 183))] combinado=procesado.combina_segmentos(segmentos) self.assertEqual(combinado,((685, 215), (659, 183))) try: combinado=procesado.combina_segmentos([]) except ValueError as ver: self.assertEqual(ver.args[0],'zero-size array to reduction operation maximum which has no identity') print("OK,test_combina_segmentos")
def test_ang(self): procesado=ProcesadoDeLineas() x=((128, 72), (164, 18)) y=((24, 43), (12, 31)) ang = procesado.ang(x, y) self.assertEqual(round(ang,2),78.69) x=((820, 257), (826, 242)) y=((820, 254), (822, 249)) ang = procesado.ang(x, y) self.assertEqual(round(ang,2),0.0) x=((871, 183), (892, 183)) y=((910, 182), (893, 182)) ang = procesado.ang(x, y) self.assertEqual(round(ang,2),180.0) print("OK,test_ang")
def test_combina(self): procesado=ProcesadoDeLineas() g=nx.Graph() lines=[((128, 72), (164, 18)), ((24, 43), (12, 31)), ((55, 71), (31, 49)), ((136, 59), (163, 19)), ((11, 31), (4, 24)), ((34, 51), (25, 43)), ((109, 42), (90, 18)), ((51, 67), (30, 48)), ((116, 50), (92, 20))] graf=procesado.combina(8, 4, lines, g) self.assertEqual(graf.nodes(),[0, 1, 2, 3, 4, 5, 6, 7, 8]) self.assertEqual(graf.edges(),[(0, 3), (1, 4), (1, 5), (1, 7), (2, 5), (2, 7), (5, 7), (6, 8)]) self.assertNotEqual(graf.nodes(),[]) self.assertNotEqual(graf.edges(),[]) g=nx.Graph() graf=procesado.combina(8, 4, [], g) self.assertEqual(graf.nodes(),[]) self.assertEqual(graf.edges(),[]) print("OK,test_combina")
def obtencion_lineas(self, no_small2): """ A traves de este metodo vamosa a encontrar las estrias que hau en la mascara que le pasamos como parametro a nuestra funcion. @param no_small2: este parametro se corresponde con la mascara una vez que le hemos pasado el preprocesado de la imagen. @return Los segmentos obtenidos a traves de este metodo. """ self.proce_lines = ProcesadoDeLineas() lines = probabilistic_hough_line(no_small2, 30, 20, 30) G = nx.Graph() G = self.proce_lines.combina2(4, 8, 4, 1, lines, G) k_components = apxa.k_components(G) segmentos_de_verdad = self.proce_lines.segmentos_verdad( k_components, lines) segmentos_de_verdad_pintar = [] for i in segmentos_de_verdad: if self.proce_lines.longitud_linea(i, 100) > 10: segmentos_de_verdad_pintar.append(i) return segmentos_de_verdad_pintar
def test_segments_distance(self): procesado=ProcesadoDeLineas() x=((128, 72), (164, 18)) y=((24, 43), (12, 31)) dist=procesado.segments_distance(x, y) self.assertEqual(round(dist,2),107.97) y=((18, 164), (128, 72)) dist=procesado.segments_distance(x, y) self.assertEqual(dist,0) try: procesado.segments_distance(0,0) except TypeError as ex: self.assertEqual(ex.args[0],'\'int\' object is not iterable') print("OK,test_segments_distance")
def test_point_segment_distance(self): procesado=ProcesadoDeLineas() x=((128, 72), (164, 18)) y=((24, 43), (12, 31)) dist=procesado.point_segment_distance( x[0][0], x[0][1], y[0][0], y[1][0], y[0][0], y[1][0]) self.assertEqual(round(dist,2),120.07) dist=procesado.point_segment_distance( x[0][0], x[0][1], y[0][0], y[1][0], y[0][1], y[1][1]) self.assertEqual(round(dist,2),94.37) y=((24, 43), (1, 100)) dist=procesado.point_segment_distance( x[0][0], x[0][1], y[0][0], y[1][0], y[0][1], y[1][1]) self.assertEqual(round(dist,2),88.75) y=((24, 43), (1, 1900)) dist=procesado.point_segment_distance( x[0][0], x[0][1], y[0][0], y[1][0], y[0][1], y[1][1]) self.assertEqual(round(dist,2),103.28) print("OK,test_point_segment_distance")
class MediadorVentana(): """ Clase que implementa el mediador de la ventana. @author: Ismael Tobar Garcia @version: 1.0 """ def __init__(self, ventana, idioma): """ Constructor de la clase ventana que nos proporciona las inicializaciones de variables y de objetos que vana a ser encesarios para su gestion e implementacion de los metodos que va a contener la ventana. @param ventana: instancia de la clase que crea la ventana. """ self.idioma = idioma if self.idioma == "ESP": self.dic = Diccionario() else: self.dic = DiccionarioING() self.ventana = ventana self.ventana.ax = self.ventana.fig.add_subplot(111) self.procesado = ProcesadoDeImagen() self.procesado_de_lineas = ProcesadoDeLineas() self.img = self.procesado.leer_imagen(self.ventana.path) self.ventana.ax = self.ventana.fig.add_subplot(111) self.ventana.ax.set_xlim([0, self.img.shape[1]]) self.ventana.ax.set_ylim([self.img.shape[0], 0]) self.ventana.ax.imshow(self.img, interpolation=self.dic.md_v_ori) if os.name == 'nt': self.ref_numeros = self.procesado.obtener_numeros(self.img) else: self.ref_numeros = 100 self.color = [] self.ventana.pestannas.button.setEnabled(False) self.ventana.pestannas.button_fijar.setEnabled(False) self.terminar = False self.detectado = True self.automatic_mode = ProcesadoAutomatico() def obtener_color(self): """ Metodo encargado de la correccion manual de las lineas que hayan quedado sin detectar por nuestro algoritmo. """ self.ventana.pestannas.button.setEnabled(False) self.ventana.pestannas.button33.setEnabled(False) def onclick(event): """ Metodo interno de la funcion anterior que se encargara de obtener las coordenadas de los puntos que bayamos clicando. @param Event: evento que contiene las coordenadas del punto clicado. @return: Coordenadas P1 y P2 """ ix, iy = event.xdata, event.ydata coords = [] if iy != None and ix != None: self.color = self.img[int(round(iy, 0)), int(round(ix, 0))] h, s, v = self.procesado.pixelrgb_2_hsv(self.color) if s > 0.6: self.distance_red = self.procesado.distancia_al_rojo( self.img, self.color) self.img_bin = self.procesado.binarizar(self.distance_red) self.ventana.fig.canvas.mpl_disconnect(cid) self.ventana.pestannas.button.setEnabled(True) r, g, b = self.color self.ventana.pestannas.color_sele.setText("") self.ventana.pestannas.color_sele.setStyleSheet( "background-color: rgb(" + str(r) + "," + str(g) + "," + str(b) + ")") self.ventana.pestannas.button33.setEnabled(True) else: self.ventana.pestannas.button.setEnabled(False) self.color = self.img[int(round(iy, 0)), int(round(ix, 0))] h, s, v = self.procesado.pixelrgb_2_hsv(self.color) h, v = h, v self.ventana.pestannas.color_sele.setText( self.dic.md_pe_no_sel) self.ventana.pestannas.color_sele.setStyleSheet( "background-color: rgb(255,255,255)") return coords cid = self.ventana.fig.canvas.mpl_connect(self.dic.md_pe_but_press, onclick) def detectar_cuadrado(self): """ Metodo para detectar el cuadrado sobre el que poder pintar las lineas que hemos detectado. """ grises = self.procesado.binarizar_para_cuadrado(self.img) sin_ruido = skeletonize(grises) lines = probabilistic_hough_line(sin_ruido, threshold=100, line_length=200, line_gap=200) self.ventana.x_max, self.ventana.x_min, self.ventana.y_max, self.ventana.y_min = self.procesado.obtener_max_y_min( lines) if self.ventana.x_max == 0 and self.ventana.x_min == 0 and self.ventana.y_max == 0 and self.ventana.y_min == 0: self.pintar_rect = PintarRectangulo(self.ventana.ax) self.pintar_rect.connect() self.terminar = True self.detectado = False self.ventana.pestannas.button33.setEnabled(False) else: self.ventana.pestannas.button_auto.setEnabled(False) self.ventana.pestannas.button_fijar.setEnabled(False) def inicializa_pestanna_1(self): """ Metodo que inicializara la pestanna uno de la ventana es decir el cuadro principal de dicha ventana. """ #------Asignamos los componentes a un layout---------- self.ventana.layout_tabs = QtWidgets.QHBoxLayout() # layout principal - - self.ventana.laout_principal = QtWidgets.QHBoxLayout() # Layout (-) - /n 1 self.ventana.layout_primero = QtWidgets.QVBoxLayout() self.ventana.layout_primero.addWidget(self.ventana.toolbar) self.ventana.layout_primero.addWidget(self.ventana.canvas) # Layout - (-) /n 1 y 2 self.ventana.layout_tabs.addWidget(self.ventana.pestannas) self.ventana.layout_tabs.setAlignment(QtCore.Qt.AlignRight) self.ventana.laout_principal.addLayout(self.ventana.layout_primero) self.ventana.laout_principal.setStretch(0, 2) self.ventana.laout_principal.addLayout(self.ventana.layout_tabs) self.ventana.laout_principal.setStretch(2, 3) self.ventana.setLayout(self.ventana.laout_principal ) # Asignamos como principal el principal self.ventana.padre.save_file.setEnabled(False) def calcular_lineas(self, repeticiones, lon_minima): """ Metodo que se encargara de llamar a las funciones de calculo de nuestra aplicacion para mostrar y guardar las lineas que han sido calculadas por el algoritmo de deteccion de aquellas que ya esten pintadas en color rojo. """ sin_ruido = self.procesado.reducir_grosor(self.img_bin) l = [] while repeticiones > 0: lines = self.procesado.pro_hough(10, 5, 11, sin_ruido) l.extend(lines) repeticiones = repeticiones - 1 G = nx.Graph() G = self.procesado_de_lineas.combina2(4, 8, 4, 1, l, G) k_components = apxa.k_components(G) segmentos_de_verdad = self.procesado_de_lineas.segmentos_verdad( k_components, l) segmentos_de_verdad_pintar = [] for i in segmentos_de_verdad: if self.procesado_de_lineas.longitud_linea( i, self.ref_numeros) > lon_minima: segmentos_de_verdad_pintar.append(i) self.pintar_imagen_y_segmentos(segmentos_de_verdad_pintar) self.ventana.lineas = segmentos_de_verdad_pintar self.ventana.tam_segmen_verdad = len(self.ventana.lineas) self.ventana.pestannas.anadir_puntos() self.ventana.pestannas.button4.setEnabled(True) self.ventana.selec_ante = None def fijar_cuadrado_auto(self): """ Metodo apra fijar el cuadrado para seleccionar el area en el modo completamente automatico. """ self.ventana.mediador_ventana.pintar_rect.disconnect() x, y = self.ventana.mediador_ventana.pintar_rect.rect.xy x, y = int(x), int(y) self.ventana.x_max = round(x + 745, 0) self.ventana.x_min = x self.ventana.y_max = round(y + 745, 0) self.ventana.y_min = y l1 = [(self.ventana.x_min - 2, self.ventana.y_min), (self.ventana.x_max + 2, self.ventana.y_min)] l2 = [(self.ventana.x_min, self.ventana.y_min), (self.ventana.x_min, self.ventana.y_max)] l3 = [(self.ventana.x_min - 2, self.ventana.y_max), (self.ventana.x_max + 2, self.ventana.y_max)] l4 = [(self.ventana.x_max, self.ventana.y_max), (self.ventana.x_max, self.ventana.y_min)] cuadr = [] cuadr.extend([l1, l2, l3, l4]) intersecciones = self.procesado_de_lineas.filtra_intersec( self.ventana.lineas, cuadr, [ self.ventana.x_min, self.ventana.x_max, self.ventana.y_min, self.ventana.y_max ], self.ventana.pestannas.slider_lon_auto.value()) contenidas = self.procesado_de_lineas.filtra_contenidas( self.ventana.lineas, self.ventana.x_min, self.ventana.x_max, self.ventana.y_min, self.ventana.y_max, self.ventana.pestannas.slider_lon_auto.value()) lineas_verdad = [] lineas_verdad.extend(contenidas) lineas_verdad.extend(intersecciones) self.pintar_imagen_y_segmentos(lineas_verdad) self.ventana.lineas = lineas_verdad self.ventana.pestannas.anadir_puntos() self.ventana.pestannas.button_fijar.setEnabled(False) def calcular_automatic(self): """ Metodo apra calculas las estrias de forma automatica en el modo completamente automatico. """ self.ventana.pestannas.button_fijar.setEnabled(True) self.ventana.mediador_ventana.pintar_rect.connect() no_small2 = self.automatic_mode.procesado_automatico(self.img) segmentos_de_verdad_pintar = self.automatic_mode.obtencion_lineas( no_small2) self.pintar_imagen_y_segmentos(segmentos_de_verdad_pintar) self.ventana.lineas = segmentos_de_verdad_pintar self.ventana.tam_segmen_verdad = len(self.ventana.lineas) #self.ventana.pestannas.anadir_puntos() self.ventana.pestannas.button4.setEnabled(True) self.ventana.selec_ante = None def pintar_imagen_y_segmentos(self, segmentos): """ Metodo que se encargara de pintar la imagen leida y lso segmentos detectados y que esten en la tabla de segmentos o lineas dentro de nuestra aplicacion. es un metodo de actualizacion de la guipru. @param segmentos: Lista de segmentos que queremos que entre dentro de la imagen. """ self.ventana.ax.set_xlim([0, self.img.shape[1]]) self.ventana.ax.set_ylim([self.img.shape[0], 0]) self.ventana.ax.imshow(self.img, origin=self.dic.md_v_up, vmax=1, interpolation=self.dic.md_v_ori) self.ventana.ax.hold(True) final = [] if self.detectado == False: self.ventana.ax.add_patch(self.pintar_rect.r) for line in segmentos: p0, p1 = line self.ventana.ax.set_xlim([0, self.img.shape[1]]) self.ventana.ax.set_ylim([self.img.shape[0], 0]) l, = self.ventana.ax.plot((p0[0], p1[0]), (p0[1], p1[1]), self.dic.md_v_color, linewidth=2) final.append(l) self.ventana.ax.hold(False) self.ventana.canvas.draw()
class ProcesadoAutomatico(): """ Clase que contendra los metodos necesarios para poder realizar el procesado de las imagenes para obtener a partir de una simple imagen las lienas que hay en ella sin pintar de forma automatica. @author: Ismael Tobar Garcia @version: 1.0 """ def __init__(self): """ Constructor de la clase que instancia las clases para aprobechar los metodos ya implementados anteriormente. """ self.proce_lines = ProcesadoDeLineas() self.proce_img = ProcesadoDeImagen() @classmethod def procesado_automatico(self, img): """ Metodo de la clase de procesado automatico que se encargara de realizar todas las operaciones necesarias para dicho procesado y obtencion de la mascara que contiene las estrias qe hay en la imagen sin pintar de forma automatica. @param img: Se corresponde con la imagen pasada como parametro a nuestra aplicacion. @return: Imagen correspondiente a la mascara de la iamgen original. """ with warnings.catch_warnings(): warnings.simplefilter("ignore") img = rgb2grey(img) img_adapteq = exposure.equalize_adapthist(img, clip_limit=0.91, nbins=100) img_adapteq_deno = denoise_tv_chambolle(img_adapteq, weight=0.1) hxx, hxy, hyy = hessian_matrix(img_adapteq_deno, sigma=1.85, mode='wrap', cval=0.11) i1, i2 = hessian_matrix_eigvals(hxx, hxy, hyy) # @UnusedVariable image = img_as_float(i1) image = gaussian_filter(image, 1) seed = np.copy(image) seed[1:-1, 1:-1] = image.min() mask = image dilated = reconstruction(seed, mask, method='dilation') im = image - dilated thresh = threshold_li(im) thresholded = im >= thresh no_small = morphology.remove_small_objects(thresholded, min_size=155, connectivity=100) selem = diamond(1.9) dil = binary_erosion(no_small, selem, out=None) skl = skeletonize(dil) no_small2 = morphology.remove_small_objects(skl, min_size=55, connectivity=100) return no_small2 @classmethod def obtencion_lineas(self, no_small2): """ A traves de este metodo vamosa a encontrar las estrias que hau en la mascara que le pasamos como parametro a nuestra funcion. @param no_small2: este parametro se corresponde con la mascara una vez que le hemos pasado el preprocesado de la imagen. @return Los segmentos obtenidos a traves de este metodo. """ self.proce_lines = ProcesadoDeLineas() lines = probabilistic_hough_line(no_small2, 30, 20, 30) G = nx.Graph() G = self.proce_lines.combina2(4, 8, 4, 1, lines, G) k_components = apxa.k_components(G) segmentos_de_verdad = self.proce_lines.segmentos_verdad( k_components, lines) segmentos_de_verdad_pintar = [] for i in segmentos_de_verdad: if self.proce_lines.longitud_linea(i, 100) > 10: segmentos_de_verdad_pintar.append(i) return segmentos_de_verdad_pintar