PRoblema con ejercicio en Matlab

Iniciado por Baphomet2204, 15 Octubre 2019, 20:33 PM

0 Miembros y 1 Visitante están viendo este tema.

Baphomet2204

Tomar una foto por una cámara, la foto se le saca a una hoja de árbol sobre una hoja de papel color rosa, leer la foto y obtener valor hexadecimal de los tonos amarillos, verdes y cafe descartando los colores rosa de la hoja, intentar detectar la forma de la hoja de árbol.

No he podido sacar el valor hexadecimal ni la forma, este es mi avance


Código (matlab) [Seleccionar]
imaqhwinfo 

cam=imaqhwinfo; 

cam.InstalledAdaptors;

vid=videoinput('winvideo',2,'yuy2_640x480');%ajustar para que tenga tamaño al de la caja

 

foto=getsnapshot(vid);

im_entrada=ycbcr2rgb(foto);

imshow(im_entrada)

 

im_g=rgb2gray(im_entrada);

umb=graythresh(im_g);

bw=im2bw(im_g,umb);

bw=not(bw);

bw=bwareaopen(bw,100);

[L1 Ne1]=bwlabel(bw);

propiedad=regionprops(L1);

 

 

%imshow(im_entrada);

% se selecciona la imajen para trabajar con ella y poder tomar la decicion 

%im_entrada = imread(rgb);

%Matrices que separa en tres a la imagen

imR = double(im_entrada(:,:,1)); %Componente rojo de la imagen de entrada

imG = double(im_entrada(:,:,2)); %Componente verde

imB = double(im_entrada(:,:,3)); %Componente azul

 

[N,M,Z]=size(im_entrada); %Tamaño de la imagen de entrada. N es varianle para renglos, M para columnas y Z 

%será una nueva variable que representará los tres componentes de la imagen RGB

Y = ones(N,M);

%Seis umbrales para la comparación de la imagen de entrada para obtener la

%imagen de salida. Tres umbrales serán superiores y tres serán inferiores

Tr1= 123.85;

Tr2= 238.15;

Tg1= 39.77;

Tg2= 165.23;

Tb1= 8.96;

Tb2= 126.04;

 

for i=1:N;

    for j=1:M;

        %Comparación de los tres componentes con los umbrales

        if((imR(i,j) > Tr1 && imR(i,j) < Tr2) && (imG(i,j) > Tg1 && imG(i,j) < Tg2) && (imB(i,j) > Tb1 && imB(i,j) < Tb2));

            %Si el valor cae dentro de los valores calculados del umbral,el pixel de la imagen de salida será color blanco ////////por lo cual el jitomate esta bueno 

            Y(i,j)=1;

        else

            Y(i,j)=0;

        end

    end

end

se = strel('disk',10); %Estructura morfológica. Dilatación y eroción, la región se dilata en forma de disco con un radio de 10px la redonda y después de erosiona 10px a la redonda.

imagen_cerrada = imclose(Y,se);

 

figure

%imshow(imagen_cerrada)

 

bwn = bwareaopen(imagen_cerrada,30); %Elimina los pixeles dispersos. En una imagen binaria elimina a todos los pixeles al número que se le asigna.

 

figure

[L Ne]=bwlabel(bwn);

propied=regionprops(L);

int i;

for i=0:i+1:Ne;

    area2=propied.Area;

end

for i=0:i+1:Ne1;

    area=propiedad.Area;

end

porcent=(area2/area)*100;

if(porcent>20);

    imshow([bwn,bw]);

    text=('El jitomate es comestible');

    disp(text);

   % sendUSB2(text);

     

end

disp(porcent);

imshow([bwn,bw]);

%imshow(bw);


si alguno tuviera una idea de como hacerlo, gracias de antemano
$Diseñando_vida

while(vivas)
{
       Come();
       //Duerme();
       Programa();
       Repite();
}

Serapis

#1
De entrada el color rosa, míralo como el color chicle, es decir un valor como:
Verde = 0
Rojo = 255
Azul = 255

Tomando una foto, es muy probable que ese color se difumine en varios sonos similares, mejor si se escanea, aunque el resultado tampoco será perfecto.

Lo que se pide básicamente es obtener los colores de la hoja que no sean rosa, esto es el rosa se trata como si fuera un color transparente. Sin embargo, resulta ambiguo... no se aclara como debe ser el formato devuelto (aparte de que debe ser en hexadecimal)... ni si basta indicar una sola vez cada color o no.

Así que supondremos que se pide obtener todos los colores que no sean rosa, y que no se guarda posición del píxel para dicho color, y que se guarda para cada color píxel, haya aparecido previamente dicho color o no.






constantes byte RosaR=255, RosaA=255, RosaV=0  // valor canales del rosa-chicle
byte nivSimil  // nivel de similitud
byte r, a, v   // canal de cada colores
int f, p     // num filas y valor píxel
string hexColor  // color en hexadecimal.
int ancho, alto  // medidas d ela imagen
array int Imagen(,)   // array de dos dimensiones o unidimensional si se calcula fila a fila la posición absoluta del píxel...

fichero fiI  // fichero de entrada (Input), el de la imagen
fichero fio  // fichero  de salida (output), el del resultado

fiI.Abrir(rutaImagen) // se abre el fichero de entrada
fio.Abrir(ruta)   // se abre el fichero de salida.

alto = fiI.LeerEnCabecera(alto)
ancho = fiI.LeerEnCabecera(ancho)

// solo la que proceda... se leen los píxeles desde final de cabecera...
//    se supone que la imagen está descomprimida, sino es así, se precisa
//    el decodificador del formato de imagen para obtener el array de píxeles...
//    se da por supuesto conocer tal circunstancia.
Imagen(alto * ancho) = fiI.LeerPixeles  //lectura unidimensional
Imagen(alto, ancho) = fiI.LeerPixeles  // lectura bidimensional
fiI.Cerrar

nivSimil  = 16
bucle f por cada fila en la imagen  //imagen sería un array de píxeles, por ejemplo.
   bucle p por cada pixel en f          // p es el enésimo píxel en la f (fila) actual.
       // 1 obtener los canales del pixel.
       r  = (p and 255)
       v = ((p \ 256) and 255)
       b = (p \ 65536)
       
       // 2 descartar si es rosa o similar... vamos a suponer algún grado de similitud
       //   si, el color está 16 valores a un lado u otro por canal consideramos que es similar... y en tal caso se descarta, si no, se acepta.
      //  como dicho rosa está en los extremos, basta mirar hacia el otro extremo.
      Si (((v > = (RosaV + nivSimil  )) y ((R <= (RosaV - nivSimil)) y  ((a <= (RosaA - nivSimil)) )
          // formato: AAVVRR  (esto es primero azul, luego verde, luego rojo)
          // el operador '+' actúa como un concatenador de caracteres...
          hexcolor = (((a\16).ToChar) + ((a and 15).ToChar) + ((v\16).ToChar) + ((v and 15).ToChar)  + ((r\16).ToChar) + ((r and 15).ToChar)) + " "
          fiO.SaveToFile(appendtofinal, hexcolor)
      Sino
          fiO.SaveToFile(appendtofinal, "------ ")   // color rosa se guarda así, necesario si
          // ...se quiere mantener posición relativa de cada color que no sea rosa.
          // cada clor va separado por un espacio, para facilitar su 'lectura', visualmente...
      fin si
   siguiente
siguiente

fiO.Cerrar


Se puede optimizar, si al canal de rosa, ya se le aplica antes del bucle, el valor de similitud, en vez de ecalcularlo por cada píxel... como los valores de rosa son constantes, se rquerirán sendas variables, para ello.
Sería aún más útlil, si en vez del rosa, fuera cualquier otro color recibido por parámetro, tal color se descomprondría e sus canales, aunque en tal caso, la verificación para descartar, es más larga pues hay que descartar también los valores al otro lado del límite de cada canal, actualmente se aprovecha que el rosa, tiene sus tres canales en valores que a un lado son límite...


Falta obtener la forma... Ahora nos ocupamos de ella...
La forma es un contorno. Un contorno, es el recorrido perimetral de la forma.
Sea una imagn de X*Y medidas, podemos saber que el controno, será como máximo (X+Y) * 2 de tamaño... que es el perímetro de un rectángulo, en este caso del rectángulo que forma la imagen. Nótese que solo consideramos la forma externa, si por ejemplo la hoja tuviera uno o más rotos internos, esas formas no quedan detectadas... Eso es una fase posteiror, para aplicar una vez se entienda al menos la primera, detectar la forma externa.

Cómo se obtiene?. Básicamente definimos dos arrays uno del vertical y otro del horizontal, de una estructura que para el vertical define izquierdo y derecho y para el horizontal superior e inferior... una simple abstración, nos permite resumir ambas en inicio y fin. Cada una define un punto, una posicion, el par X,Y.


Estructura Posicion
   int X
   int Y
Fin estructura

Estructura Extremo
   posicion Inicial         // izquierda o superior
   posicion Final           // derecha o inferior
fin estructura

Array de Extremo PerimVertical(alto)
array de Extremo PerimHorizontal(ancho)

Array Extremo NumPuntos(0 a 1)  // 0 refiere vertical, 1 refiere horizontal, cantidad de puntos que cvontiene el array (el resto sobra)

int x, y, n   // punteros de avance para cada array...

Nótese que el contorno, será la línea que una dichos puntos... como también resulta ambiguo la forma en que deba ser devuelto, baste estos dos arrays y luego haz con ellos lo que quiera, posiblemente escribirlos a fichero o sarlo para dibujar en algún lienzo... y luego guardar la imagen resultante a fichero.

Aunque los siguientes bucles parezcan mucha sobrecarga de trabajo, en realidad, solo se recorre hasta encontrar un pixle que no sea similar al rosa.

// obtener la parte vertical izquierda...
n=0
bucle para y desde 0 hasta Alto-1  
   bucle para x desde 0 hasta Ancho-1  
        Si (Similar(Rosa, imagen(y, x), 16) = FALSE)
            PerimVertical(n).Inicial.X = x
            PerimVertical(n).Inicial.y = y
            n = (n +1)
            Salir del bucle
        fin si
   siguiente
siguiente
NumPuntos(0).Inicial = n   // solo los primeros 'n' puntos dle array PerimVertical son válidos

// obtener la parte vertical derecha...
n=0
bucle para y desde 0 hasta Alto-1  
   bucle para x desde Ancho-1 hasta 0 retrocediendo
        Si (Similar(Rosa, imagen(y, x), 16) = FALSE)
            PerimVertical(n).Final.X = x
            PerimVertical(n).Final.y = y
            n = (n +1)
            Salir del bucle
        fin si
   siguiente
siguiente
NumPuntos(0).Final = n  // solo los primeros 'n' puntos dle array PerimVertical son válidos

// obtener la parte horizontal superior...
n=0
bucle para x desde 0 hasta Ancho-1  
   bucle para y desde 0 hasta Alto-1  
        Si (Similar(Rosa, imagen(y, x), 16) = FALSE)
            PerimHorizontal(n).Inicial.X = x
            PerimHorizontal(n).Inicial.y = y
            n = (n +1)
            Salir del bucle
        fin si
   siguiente
siguiente
NumPuntos(1).Inicial = n   // solo los primeros 'n' puntos dle array PerimHorizontal son válidos

// obtener la parte horizontal inferior...
n=0
bucle para x desde Ancho-1 hasta 0 retrocediendo
   bucle para y desde 0 hasta Alto-1  
        Si (Similar(Rosa, imagen(y, x), 16) = FALSE)
            PerimHorizontal(n).Final.X = x
            PerimHorizontal(n).Final.y = y
            n = (n +1)
            Salir del bucle
        fin si
   siguiente
siguiente
NumPuntos(1).Final = n   // solo los primeros 'n' puntos dle array PerimHorizontal son válidos


y listo, lo que hagas luego con dichos arrays ya es cosa tuya, pués no queda definido... Como dije antes, se puede guardar a fichero, o genera la imagen de la forma, recoriendo los 4 arrays para pintar el píxel que refieren sus cordenadas... y quizás luego guardarla la imagen resultante a fichero.

Similar ahora la definimos como una función, para dejar más claro la funcionalidad de obtener el contorno.
Esta función hace lo que ya hemos hecho antes en código, pero integrado en la misma funcion.
Rosa lo pasamos entero, es más rentabale pasar los canales ya descompuestos... (para hacelro una sola vez, no con cada color).

Buleano = ColorSimilar(int Color, int colCandidato, int nivel)
   int r1, v1, a1, r2, g2, a2, r3, g3, a3

   // Descomponer el color base a comparar aplicado sus niveles máximo y minimo a cada canal...
   r1= fixToRangoByte((color and 255) + nivel)
   r2 =fixToRangoByte((color and 255) - nivel)

   g1= fixToRangoByte(((color \ 256) and 255) + nivel)
   g2 =fixToRangoByte(((color \ 256) and 255) - nivel)

   a1= fixToRangoByte((color \ 65536) + nivel)
   a2 =fixToRangoByte((color \ 65536) - nivel)

   // Descomponer el color candidato en sus canales...
   r3 = (colCandidato and 255)
   g3 = ((colCandidato\ 256) and 255)
   a3 = (colcandidato \ 65536)

   // Comparación:
   //    ejemplo para canal rojo: r= 45;  r1=(45+16) = 61;  r2= (45-16) = 29
   //        si r3 cae ente 29 y 61 el rojo es similar... igual para el resto de canales.
   Si ((r3 <= r1) y (r3 >= r2))
       Si ((g3 <= g1) y (g3 >= g2))
           Si ((a3 <= a1) y (a3 >= a2))
               devolver TRUE
           fin si
       fin si
   fin si
fin funcion

Byte = fixToRangoByte(int Valor)
   Si (valor < 0 )
      valor = 0
   osi (Valor > 255)
      valor = 255
   fin si

   devolver Valor
Fin funcion


Si en vez de hablar de similitud, pudiéramos hablar de igualdad, es decir que el rosa, no tuviera variedad tonal, el cálculo se aceleraría, pués bastaría comparar el píxel 'p', con rosa , en vez de calcular si es similar... pero sacando fotos, o escaneos, no habrá un color puro... la luminosidad del ambiente y los reflejos marcarán variaciones tonales.

Baphomet2204

Excelente amigo muchas gracias, llevaba 3 días rompiéndome la cabeza, apenas empiezo a usar matlab y quise aventarme con este problema, creo que sobrestime mis pobres capacidades en este lenguaje, gracias y un saludo
$Diseñando_vida

while(vivas)
{
       Come();
       //Duerme();
       Programa();
       Repite();
}