示例#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 __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")
示例#12
0
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