elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Como proteger una cartera - billetera de Bitcoin


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  Java
| | | |-+  OpenCv + Android + Problemas con Matrices
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: OpenCv + Android + Problemas con Matrices  (Leído 2,265 veces)
Mr.Moonlight

Desconectado Desconectado

Mensajes: 26



Ver Perfil WWW
OpenCv + Android + Problemas con Matrices
« en: 6 Abril 2022, 01:25 am »

Buenas foreros!  :D
Como habréis podido leer en el título este es un asunto relacionado con programación en Java para una app Android usando la librería openCV. En resumidas cuentas el programa carga una red neuronal que ya hemos entrenado con una batería de imágenes. El programa original, por comodidad y por poca experiencia lo codificamos en Java pensando que como Android y Java van bastante de la mano no habría una dificultad grande a la hora de traducirlo para una app, bien el problema parte a la hora de proporcionarle la entrada a la red neuronal.
Código
  1.  
  2. Mat frame = new Mat(); // Matriz de OpenCv
  3. Mat fgMask = new Mat();
  4. MatOfByte mem = new MatOfByte();
  5.  
  6.        BackgroundSubtractor backSub;
  7.        backSub = Video.createBackgroundSubtractorKNN(5, 0, false);
  8.  
  9.        VideoCapture capture = new VideoCapture(0); // Captura camara por defecto
  10.        if (!capture.isOpened()) {
  11.            System.exit(0);
  12.        }
  13.  
  14.        while (true) {
  15.  
  16.            capture.read(frame);
  17.            if (frame.empty()) {
  18.                break;
  19.            }
  20.  
  21. Imgproc.cvtColor(frame, frame, Imgproc.COLOR_BGR2GRAY, 0);//Imagen a Escala de grises
  22. Imgproc.GaussianBlur(frame, frame, new Size(15, 15), 0); //Aplicamos un Suavizado
  23. backSub.apply(frame, fgMask); //Eliminamos fondo de frame y guardamos en fgMask
  24. Imgproc.resize(fgMask, fgMask, new Size(250, 250)); //redimensionamos
  25.  
  26. //      Aquí es donde hicimos el apaño para java, que no puede funcionar en Android    
  27. //      Puesto que BufferedImage e Image no existen en las librerias para Android    
  28.  
  29.               Mat image= new Mat();
  30.               Imgcodecs.imencode(".jpg", fgMask, mem);
  31.               Image im=null;
  32.  
  33.            try {
  34.                im = ImageIO.read(new ByteArrayInputStream(mem.toArray()));
  35.                BufferedImage buff = (BufferedImage)im;    
  36.                image = BufferedImage2Mat(buff);
  37.            } catch (IOException ex) {
  38.         Logger.getLogger(VideoCaptureejemplo.class.getName()).log(Level.SEVERE, null, ex);
  39.            }
  40.  
  41.  
  42.  
  43.            Mat blob = blobFromImage(image,1 ,new Size(250,250));
  44.  
  45.  
  46.  
  47.           clasificador.setInput(blob);
  48.  
  49.  
  50.  
  51.            Mat res = clasificador.forward();
  52.            System.out.println(res.dump());
  53.  
  54.  
  55.  
  56.        }
  57.  
  58.        System.exit(0);
  59.    }
  60. public static Mat BufferedImage2Mat(BufferedImage image) throws IOException {
  61.  
  62.    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  63.    ImageIO.write(image, "jpg", byteArrayOutputStream);
  64.    byteArrayOutputStream.flush();
  65.    return Imgcodecs.imdecode(new MatOfByte(byteArrayOutputStream.toByteArray()), CV_32FC1);
  66. }

Testeando y probando he llegado a la conclusión que a pesar de que la función BlobFromImage solicita una Matriz como primer parametro esta debe de estar construida de una forma un poco más especial, si yo trato de enviar una Matriz como fgMask en vez de una BufferedImage lanzará un error:
Contenido de fgMask:

Mat [ 1*1*250*250*CV_32FC1, isCont=true, isSubmat=false, nativeObj=0x1fb55df0, dataAddr=0x23991140 ]

Contenido de fgMask(BufferedImage):

Mat [ 1*3*250*250*CV_32FC1, isCont=true, isSubmat=false, nativeObj=0x1f59f110, dataAddr=0x21d63c00 ]

Código del Error:
Código:
[ERROR:0] global C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\dnn\src\dnn.cpp (3512) cv::dnn::dnn4_v20210608::Net::Impl::getLayerShapesRecursively OPENCV/DNN: [Convolution]:(sequential/conv2d/Conv2D): getMemoryShapes() throws exception. inputs=1 outputs=0/1 blobs=2
[ERROR:0] global C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\dnn\src\dnn.cpp (3515) cv::dnn::dnn4_v20210608::Net::Impl::getLayerShapesRecursively     input[0] = [ 1 1 250 250 ]
[ERROR:0] global C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\dnn\src\dnn.cpp (3523) cv::dnn::dnn4_v20210608::Net::Impl::getLayerShapesRecursively     blobs[0] = CV_32FC1 [ 16 3 3 3 ]
[ERROR:0] global C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\dnn\src\dnn.cpp (3523) cv::dnn::dnn4_v20210608::Net::Impl::getLayerShapesRecursively     blobs[1] = CV_32FC1 [ 16 1 ]
[ERROR:0] global C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\dnn\src\dnn.cpp (3525) cv::dnn::dnn4_v20210608::Net::Impl::getLayerShapesRecursively Exception message: OpenCV(4.5.3) C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\dnn\src\layers\convolution_layer.cpp:386: error: (-2:Unspecified error) Number of input channels should be multiple of 3 but got 1 in function 'cv::dnn::ConvolutionLayerImpl::getMemoryShapes'

Exception in thread "main" CvException [org.opencv.core.CvException: cv::Exception: OpenCV(4.5.3) C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\dnn\src\layers\convolution_layer.cpp:386: error: (-2:Unspecified error) Number of input channels should be multiple of 3 but got 1 in function 'cv::dnn::ConvolutionLayerImpl::getMemoryShapes'
]
    at org.opencv.dnn.Net.forward_1(Native Method)
    at org.opencv.dnn.Net.forward(Net.java:237)

¿Alguien sabe como cambiar o qué significa el segundo digito en la información de las matrices que he puesto arriba? No sé pero siento que de modificar ese caracter sin recurrir a la chapuza de BufferedImage se podría solucionar todo fácilmente.




« Última modificación: 6 Abril 2022, 16:15 pm por Mr.Moonlight » En línea

Ayudame en posicionamiento SEO en mi practica de la universidad : https://www.atorrijaoguachisnai.com/
kub0x
Enlightenment Seeker
Colaborador
***
Desconectado Desconectado

Mensajes: 1.486


S3C M4NI4C


Ver Perfil
Re: OpenCv + Android + Problemas con Matrices
« Respuesta #1 en: 6 Abril 2022, 03:28 am »

Hola,

estás obteniendo el error Number of input channels should be multiple of 3 but got 1 in function.
Revisa la parametrización ya que el nº de canales ha de ser múltiplo de 3 y tu le pastaste 1, no sé si eso te dice algo..

Saludos.


En línea

Viejos siempre viejos,
Ellos tienen el poder,
Y la juventud,
¡En el ataúd! Criaturas Al poder.

Visita mi perfil en ResearchGate

Mr.Moonlight

Desconectado Desconectado

Mensajes: 26



Ver Perfil WWW
Re: OpenCv + Android + Problemas con Matrices
« Respuesta #2 en: 6 Abril 2022, 16:05 pm »

Hola,

estás obteniendo el error Number of input channels should be multiple of 3 but got 1 in function.
Revisa la parametrización ya que el nº de canales ha de ser múltiplo de 3 y tu le pastaste 1, no sé si eso te dice algo..

Saludos.

Muchas gracias por tu respuesta kub0x!, más exactamente tenía que ser 3, el problema era que al realizar las operaciones para eliminar el fondo de la imagen, etc, la matriz del color había quedado como un solo dígito por posición, en vez de un escalar estilo RGB que sería un vector con 3 dígitos!

Hemos conseguido encontrar una corrección y aparentemente todo funcionará perfectamente en Android.  ;D
Por si a alguien le interesa la corrección que hemos encontrado es usando
Código
  1. Mat image = fgMask.clone();
  2. Imgproc.cvtColor(image, image, Imgproc.COLOR_BGR2RGB, 3);
  3. image.convertTo(image,CV32FC1);
  4. Mat blob = blobFromImage(image,1 ,new Size(250,250));
  5. clasificador.setInput(blob);
  6.  
Donde el último parámetro de la función cvtColor indica el numero de canales para expresar el color, no alterara absolutamente nada puesto que la única diferencia es que el blanco y negro en vez de ser expresados por 0 o 1 será expresado como RGB
 ;-) ;-)
En línea

Ayudame en posicionamiento SEO en mi practica de la universidad : https://www.atorrijaoguachisnai.com/
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
OpenCv
Programación C/C++
hojanico19 0 2,512 Último mensaje 17 Julio 2012, 19:57 pm
por hojanico19
opencv en consola
Programación C/C++
williamfj 0 1,373 Último mensaje 19 Mayo 2015, 02:20 am
por williamfj
opencv
Java
HunterLuis 0 1,564 Último mensaje 23 Mayo 2015, 02:53 am
por HunterLuis
javaFX con opencv
Java
HunterLuis 1 1,857 Último mensaje 26 Mayo 2015, 03:34 am
por HunterLuis
Problemas con Matrices en C
Programación C/C++
M4RQUS 7 2,223 Último mensaje 13 Septiembre 2018, 19:25 pm
por M4RQUS
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines