Está en la página 1de 24
Universidad de Guadalajara Centro Universitario de Ciencias Exactas e Ingenierías Práctica: 1 Materia: Diseño de

Universidad de Guadalajara

Centro Universitario de Ciencias Exactas e Ingenierías

Práctica: 1

Materia:

Diseño de Interfaces

Profesor:

Rubén Estrada Marmolejo

Alumna:

Gómez Pelayo Lizbeth

Código:

212444184

Sección:

D02

Marmolejo Alumna: Gómez Pelayo Lizbeth Código: 212444184 Sección: D02 Fecha de entrega : 03 de Octubre

Fecha de entrega : 03 de Octubre del 2019

Resumen:

El objetivo de esta práctica, es mover un servomotor conectado a Arduino,

mediante la detección de un color con OpenCV en QT. Principalmente se creó

una interfaz de usuario en

QT con comunicación serial, dicha interfaz está diseñada para comunicarse con

arduino.

La placa de Arduino es la encargada de mover el servomotor,esto se logra,

gracias a la codificación de datos JSON.

El hardware que se utilizó para esta práctica fue solamente la placa de arduino y

el servomotor, con sus respectivos cables de conexión.

En la parte de software se compone de una interfaz desarrollada en Qt y OpenCV

en la cual se captura la imagen mediante la cámara web la computadora, para

después ajustarla y combinarla con nuestra imagen de fondo, que se compone de

un semicírculo que va de 0 a 180 grados y está dividido en 8 secciones, las cuales

serán en las que el servomotor se mueva. Posteriormente, se calcula el contorno

de mayor área para después encontrar cada momento de contorno mayor y así

poder hacer el seguimiento del objeto. Finalmente, se escribe en el arduino el

mensaje JSON codificado con los grados específicos que tiene girar para cada

detección de color.

2. Palabras clave

Detector de color, comunicación serial Arduino-Qt,Codificación JSON, detectar contornos imagen.

3. Marco Teórico

3.1 QT

Qt es una aplicación multiplataforma y un marco de interfaz gráfica de usuario (GUI), un kit de herramientas que se utiliza para desarrollar software que se puede ejecutar en diferentes plataformas de hardware y sistemas operativos. Qt facilita el desarrollo de software con GUI de aspecto nativo (para el sistema operativo en el que se ejecuta) utilizando C ++ estándar, por lo que también se clasifica como un kit de herramientas de widgets.

3.2 OpenCV

OpenCV (Open Source Computer Vision Library) es una biblioteca de software de aprendizaje por computadora y visión por computadora de código abierto. OpenCV se creó para proporcionar una infraestructura común para

aplicaciones de visión por computadora y para acelerar el uso de la percepción de máquinas en los productos comerciales.

4. Funciones de openCV utilizadas 4.1. GaussianBlur:Es una operación o función que permite aplicar un filtro de desenfoque a una imagen. Este tipo de filtro es muy útil para quitar ruido de alta frecuencia(pixeles cambiando muy rápido) para una imagen. Por ejemplo, se puede aplicar en el proceso de crear un filtro de color.

4.2. resize: Permite cambiar el tamaño de una variable de tipo Matriz de OpenCV. En otras palabras podemos cambiar la proporción y tamaño de una imagen.

4.3 inRange: Permite filtrar una ventana de valores para pixeles en una imagen.

4.4 cvtColor: Permite cambiar el espacio de color de una imagen. Por ejemplo, el

espacio de color se refiere a que representa cada capa de una imagen, por ejemplo RGB.

4.5 findContours: Permite encontrar los n contornos externos e internos de una

imagen binaria (blanco y negro).

4.6 imread: Permite leer una imagen ya sea en formato jpg,png,etc.

4.7 contourArea: Calcula el área del contorno.

4.8 bitwise_not: Invierte los bits de cada arreglo

4.9 circle: Dibuja un círculo

5.- Diagrama de Flujo QT

5.- Diagrama de Flujo QT

Figura 1. Diagrama de Flujo explicando brevemente el funcionamiento del código Qt.

6. Resultados

Para la creación de la práctica, mover el servomotor mediante la detección de algún color, se utilizó como plantilla el ejemplo 15 que se hizo en clase. Dicho ejemplo, consiste en conectar el arduino y Qt mediante el puerto serial y así mandar un mensaje JSON el cual será el encargado de mover el servomotor.

En la interfaz gráfica (mainwindow.iu) del Ejemplo 15 se tienen los siguientes elementos, para no borrarlos porque todos los objetos tienen memoria, lo que se hizo fue colocarlo en una pestaña:

2 etiquetas (Cabe mencionar que una de las etiquetas, la función era indicar si el arduino estaba conectado o no).

1 dial (La función de este elemento era mover el servomotor desde 0 a 180 grados).

1 pushButton (Encargado de llevar una serie de secuencia de movimiento del servomotor, esto mediante la codificación del mensaje JSON)

1 textBrowser (Su función era imprimir el mensaje JSON que estaba recibiendo el arduino.

función era imprimir el mensaje JSON que estaba recibiendo el arduino. Figura 3. Diseño de ventana

Figura 3. Diseño de ventana para la pestaña 1.

Para cumplir con el objetivo de la práctica se combinó el Ejemplo 15 encargado de la conexión mediante el puerto serial Qt con Arduino y capaz de mover el servomotor mediante codificación de mensaje JSON, así como también el Ejemplo 14, el cual tiene como fin, la detección de color, calibración y por último calcular los contornos de mayor área, así como el centro del momento de cada contorno, en la sección de Apéndice viene el código completo.

en la sección de Apéndice viene el código completo. Figura 4. Diseño Final de la ventana

Figura 4. Diseño Final de la ventana 2, encargada del funcionamiento de la práctica 1.

La práctica 1 está casi completa, lo que nos correspondió hacer, fue el combinar la imagen de la cámara web con una imagen de semicírculo, la cual marcaría los grados a los que tendría que girar el servo, si el objeto se encontrara dentro del contorno. A continuación, se muestra la figura a combinar:

Figura 5. Imagen a combinar con la imagen de la cámara web, y en la

Figura 5. Imagen a combinar con la imagen de la cámara web, y en la cual se trabajará para encontrar los contornos de mayor área, así como el centro de cada momento.

Basándose en el ejemplo 13, en la cual, se cargaba una imagen de fondo y otra

con un fondo verde. Mediante un clic y un filtro, se extraían los píxeles verdes y se dejaba pasar lo demás en la imagen. Se probó hacerlo de la misma manera, pero no se obtuvieron resultados favorables, ya que si no se cuenta con una Laptop potente, se comienza a trabar al querer cargar una imagen teniendo la cámara web activada. La solución a esto fue crear una variable de tipo Matriz, que en este caso se llamó fondo verde, e igualarla a la dirección en la cual se encontraba la imagen. Asi como tambien el proceso llevado a cabo para obtener

la combinación de la imagen con la dada de la cámara web

fondoVerde= imread("/home/liz/Downloads/original.png");

cv::resize(fondoVerde,fondoVerdeChica,Size(640,360),0,0,INTER_LINEA

R);

cvtColor(fondoVerdeChica, hsv, CV_BGR2HSV); Mat binaria; inRange(hsv, Scalar(40,235,216), Scalar(80,255,255), binaria); Mat binariaInvertida; cv::bitwise_not(binaria,binariaInvertida); Mat imagenChicaCopia; imagenChica.copyTo(imagenChicaCopia); fondoVerdeChica.copyTo(imagenChicaCopia,binariaInvertida); Mat combinada; imagenChicaCopia.copyTo(combinada);

Y se tiene como resultado lo siguiente:

Figura 6. Imagen procesada de la cámara web combinada con la imagen de los ángulos.

Figura 6. Imagen procesada de la cámara web combinada con la imagen de los ángulos.

Después se hace la detección de color, se realiza leyendo los canales de la imagen hsv en el punto en el cual se le da clic, pero para esto primero se tiene que activar el checkbox de guardar, para que la calibración se guarde y no esté cambiando constantemente. Por último, se des-selecciona el recuadro de guardar.

Figura 7. Objeto a detectar. Figura 8. Aplicación de filtro binario para la detección de

Figura 7. Objeto a detectar.

Figura 7. Objeto a detectar. Figura 8. Aplicación de filtro binario para la detección de color.

Figura 8. Aplicación de filtro binario para la detección de color.

Finalmente, después de tener detectado el color, se calcularon los contornos de mayor área de la Figura 5. pero a está primeramente se le aplicó un filtro de ventana para convertirla a binaria y así poder sacar los contornos de mayor área,

así como el centro de cada momento, tanto en el eje “x” como en el eje “y”, y se mostraban mediante un qDebug. Estos últimos datos, se metieron en una condicional, y dependiendo el cuadrante de la figura, eran los valores que se iban a tener en cada centro de cada momento, entonces para cada posición, se sobrescribirá la imagen “FondoVerde” por la imagen con el contorno sombreado que correspondía a la posición del objeto/color detectado.

que correspondía a la posición del objeto/color detectado. Figura 9. Imagen que se sobrescribe cuando el

Figura 9. Imagen que se sobrescribe cuando el objeto/color, se encontraba en el centro del momento del primer contorno.

se encontraba en el centro del momento del primer contorno. Figura 9. Resultado de la combinación

Figura 9. Resultado de la combinación de la Figura 8 con la imagen de la cámara.

Cabe mencionar que para mandarle la orden al servomotor dependiendo en la condicional del cuadrante en el que se encuentra el objeto/color, se manda con la siguiente línea:

arduino->write("{\"motor\":\"1\",\"grados\":\"20\"}");

Para esto, se cargó al arduino un programa encargado de mandar la codificación por mensaje JSON, el cual viene en la parte de Apéndice. Los grados, dependen de la posición en la que se encuentre el objeto/color.

6.2 Hardware

en la que se encuentre el objeto/color. 6.2 Hardware Figura 10. Arduino con servomotor conectado y

Figura 10. Arduino con servomotor conectado y los objetos utilizados para las pruebas.

7.Conclusión

El objetivo de la práctica, se cumplio. Aunque se tuvieron unos inconvenientes a la hora de la realización, para optimizarlo y hacer que a la hora del procesamiento la laptop no se hiciese lenta, se decidió, leer la imagen directamente del directorio con la función “imread”. Además, también es

importante que a la hora de la calibración del objeto/color, se tenga una luz adecuada, ya que no importará la calibración que se haga si al momento de probar la práctica, la iluminación cambia.

8 . Apéndice

8.1 Código Archivo de cabecera QT #ifndef MAINWINDOW_H #define MAINWINDOW_H

#include <QMainWindow> #include <QtSerialPort/QSerialPort>

namespace Ui { class MainWindow;

}

class MainWindow : public QMainWindow

{

Q_OBJECT

public:

explicit MainWindow(QWidget *parent = nullptr); ~MainWindow();

public slots:

void funcionCronometro(); void recepcionSerialAsincrona(); void conectarArduino(); void mousePressEvent(QMouseEvent *event); private slots:

void on_pushButton_clicked();

void on_pushButton_2_clicked(bool checked);

void on_dial_valueChanged(int value);

void on_pushButton_3_clicked();

void on_checkBox_clicked(bool checked);

private:

Ui::MainWindow *ui; int contador = 0; QSerialPort *arduino; bool arduino_esta_conectado = false;

};

#endif // MAINWINDOW_H

8.2 Archivo principal código QT MainWindow.h #include "mainwindow.h" #include "ui_mainwindow.h" #include<QTimer>

#include<opencv2/core/core.hpp>

#include<opencv2/ml/ml.hpp>

#include<opencv/cv.h>

#include<opencv2/imgproc/imgproc.hpp>

#include<opencv2/highgui/highgui.hpp>

#include<opencv2/video/background_segm.hpp>

#include<opencv2/videoio.hpp>

#include<opencv2/imgcodecs.hpp>

#include"mat2qimage.h"

#include<stdio.h>

#include<stdlib.h>

#include<QProcess>

#include<QFileDialog>

#include<QSerialPortInfo>

#include<QSerialPort>

#include<QDebug>

#include<QMouseEvent>

#define ArduinoUNO 67 #define ArduinoMEGA 66

using namespace cv; VideoCapture camara(0); Mat imagen; int contadorImagenes = 0; int estado = 0; int contador = 0;

Mat fondo; Mat fondoVerde;

int xGlobal = 0; int yGlobal = 0; int xLocal = 0; int yLocal = 0;

uchar pixelC0 = 0; uchar pixelC1 = 0; uchar pixelC2 = 0;

void MainWindow::mousePressEvent(QMouseEvent *event){ if(event->MouseButtonPress){ xGlobal = event->x()-30; yGlobal = event->y()-140;

//Reestringir, a que solo los clics dentro de la etiqueta, sean validos if(xGlobal >= 0 && xGlobal <= 639){ if(yGlobal >= 0 && yGlobal <= 359 && ui->radioButton_2->isChecked() && !ui->checkBox->isChecked()){ //El click ocurrio dentro la etiqueta xLocal = xGlobal; yLocal = yGlobal; // qDebug() << "X: " << xLocal << " Y: " << yLocal << endl;

}

if(yGlobal >=0 && yGlobal <= 359 && ui->checkBox->isChecked() && ui-

>checkBox_2->isChecked()){

xLocal = xGlobal; yLocal = yGlobal; //qDebug() << "X: " << xLocal << " Y: " << yLocal << endl;

}

}

}

}

void MainWindow::recepcionSerialAsincrona(){

}

void MainWindow::conectarArduino(){ //Declaracion de las variables arduino = new QSerialPort(this); connect(arduino, &MainWindow::recepcionSerialAsincrona); QString nombreDispositivoSerial = ""; int productoID = 0; int fabricanteID = 0;

&QSerialPort::readyRead,

this,

//Imprimir en la terminal, la cantidad de dispositivos seriales virtuales, conectados a la computadora qDebug() << "Esto es un mensaje de terminal" << endl;

<<

QSerialPortInfo::availablePorts().length();

qDebug()

<<

"Puertos

disponibles:

"

foreach

(const

QSerialPortInfo

&serialPortInfo,

QSerialPortInfo::availablePorts()){ if(serialPortInfo.hasVendorIdentifier()){ fabricanteID = serialPortInfo.vendorIdentifier(); productoID = serialPortInfo.productIdentifier(); nombreDispositivoSerial = serialPortInfo.portName();

}

}

qDebug() << "Fabricante: " << fabricanteID << endl;

qDebug() << "Producto:

" << productoID << endl;

//Conexion con Arduino if(productoID == ArduinoUNO || productoID == ArduinoMEGA){ //Establece TTYACMX como nombre del dispositivo arduino->setPortName(nombreDispositivoSerial); arduino->open(QIODevice::ReadWrite);

arduino->setDataBits(QSerialPort::Data8);

arduino->setBaudRate(QSerialPort::Baud115200);

arduino->setParity(QSerialPort::NoParity); arduino->setStopBits(QSerialPort::OneStop); arduino->setFlowControl(QSerialPort::NoFlowControl); arduino_esta_conectado = true; ui->label_6->setText("Arduino esta conectado");

}

else{ ui->label_6->setText("Arduino desconectado");

}

}

void MainWindow::funcionCronometro(){

//BGR Mat imagenChica; Mat imagenProcesada; Mat error(360,640, CV_8UC3, Scalar(0,0,255)); Mat imagenChicaBorrosa; Mat imagenHSV;

if(ui->checkBox->isChecked()){ //Mostrar la imagen original de la camara

camara >> imagen;

cv::resize(imagen,imagenChica,Size(640,360),0,0,INTER_LINEAR);

Mat hsv; Mat fondoVerdeChica; fondoVerde= imread("/home/liz/Downloads/original2.png");

cv::resize(fondoVerde,fondoVerdeChica,Size(640,360),0,0,INTER_LINEAR);

cvtColor(fondoVerdeChica, hsv, CV_BGR2HSV); Mat binaria; inRange(hsv, Scalar(40,235,216), Scalar(80,255,255), binaria); Mat binariaInvertida; cv::bitwise_not(binaria,binariaInvertida);

Mat imagenChicaCopia; imagenChica.copyTo(imagenChicaCopia); fondoVerdeChica.copyTo(imagenChicaCopia,binariaInvertida); Mat combinada; imagenChicaCopia.copyTo(combinada);

//Inicio de la deteccion de color

GaussianBlur(imagenChica,imagenChicaBorrosa, Size(15,15),0,0,0); cvtColor(imagenChicaBorrosa, imagenHSV, CV_BGR2HSV);

//Leer los 3 canales de imagen HSV en el punto del clic Point puntoClic; puntoClic.x= xLocal; puntoClic.y=yLocal;

//Vector de 3 puntos

Vec3b intensidad = imagenHSV.at<Vec3b>(puntoClic.y,puntoClic.x);

if(ui->checkBox_2->isChecked()){

pixelC0 = intensidad.val[0]; pixelC1 = intensidad.val[1]; pixelC2 = intensidad.val[2];

}

qDebug() <<"X: " << puntoClic.x << " Y: " << puntoClic.y << "C0: " << pixelC0 << "C1: " << pixelC1 << "C2: "<< pixelC2<<endl;

int C0min = pixelC0 - 30; int C0max = pixelC0 + 30;

int C1min = pixelC1 - 30; int C1max = pixelC1 + 30; int C2min = pixelC2 - 30; int C2max = pixelC2 + 30;

if(C0min < 0) C0min = 0; if(C0max > 255) C0max = 255; if(C1min < 0) C1min = 0; if(C1max > 255) C1max = 255; if(C2min < 0) C2min = 0; if(C2max > 255) C2max = 255;

Mat binaria14; Mat copiaColor;

inRange(imagenHSV, Scalar(C0max,C1max,C2max), binaria14);

Scalar(C0min,

//Contorno de mayor area std::vector<std::vector<Point>> contornos; std::vector<Vec4i> jerarquia; Mat binariaCopia;

binaria14.copyTo(binariaCopia);

C1min,

C2min),

findContours(binariaCopia,contornos,jerarquia,CV_RETR_EXTERNAL,CV_

CHAIN_APPROX_SIMPLE,Point(0,0));

int areaMaxima = 0; int area = 0; int iMax = 0; for (int i=0;i<contornos.size();i++){ area=contourArea(contornos[i]); if(area > areaMaxima){ areaMaxima = area; iMax = i;

}

}

if(contornos.size()>0)

{

//Encontrar los momentos del contorno de mayor area //Encontrar el centro del contorno de mayor area

//Declaracion del momento Moments momentoObjeto1;

//Encontrar el momento del contorno mayor momentoObjeto1 = moments(contornos[iMax]);

//Encontrar el centro del momento

Point centro; centro.x = momentoObjeto1.m10/momentoObjeto1.m00; centro.y = momentoObjeto1.m01/momentoObjeto1.m00;

//Dibujar un circulo en la imagen original, del objeto encontrado. imagenChicaCopia.copyTo(copiaColor);

circle(copiaColor,centro,15,Scalar(0,0,255),-1,8,0);

qDebug() << "Centro X: " << centro.x << "Centro Y: " << centro.y <<endl;

if(540 <= centro.x && 600 >= centro.x && 257<=centro.y &&

317>=centro.y){

fondoVerde= imread("/home/liz/Downloads/imagenes/1.png");

cv::resize(fondoVerde,fondoVerdeChica,Size(640,360),0,0,INTER_LINE

AR);

cvtColor(fondoVerdeChica, hsv, CV_BGR2HSV); inRange(hsv, Scalar(40,235,216), Scalar(80,255,255), binaria); cv::bitwise_not(binaria,binariaInvertida); imagenChica.copyTo(imagenChicaCopia); fondoVerdeChica.copyTo(copiaColor,binariaInvertida); imagenChicaCopia.copyTo(combinada);

arduino->write("{\"motor\":\"1\",\"grados\":\"20\"}");

}

if(500 <= centro.x && 560 >= centro.x && 162<=centro.y &&

222>=centro.y){

fondoVerde= imread("/home/liz/Downloads/imagenes/2.png");

cv::resize(fondoVerde,fondoVerdeChica,Size(640,360),0,0,INTER_LINE

AR);

cvtColor(fondoVerdeChica, hsv, CV_BGR2HSV); inRange(hsv, Scalar(40,235,216), Scalar(80,255,255), binaria); cv::bitwise_not(binaria,binariaInvertida); imagenChica.copyTo(imagenChicaCopia); fondoVerdeChica.copyTo(copiaColor,binariaInvertida); imagenChicaCopia.copyTo(combinada);

arduino->write("{\"motor\":\"1\",\"grados\":\"45\"}");

}

if(440 <= centro.x && 500 >= centro.x && 80<=centro.y &&

140>=centro.y){

fondoVerde= imread("/home/liz/Downloads/imagenes/3.png");

cv::resize(fondoVerde,fondoVerdeChica,Size(640,360),0,0,INTER_LINE

AR);

cvtColor(fondoVerdeChica, hsv, CV_BGR2HSV); inRange(hsv, Scalar(40,235,216), Scalar(80,255,255), binaria); cv::bitwise_not(binaria,binariaInvertida); imagenChica.copyTo(imagenChicaCopia);

fondoVerdeChica.copyTo(copiaColor,binariaInvertida); imagenChicaCopia.copyTo(combinada);

arduino->write("{\"motor\":\"1\",\"grados\":\"70\"}");

}

if(350 <= centro.x && 410>= centro.x && 37<=centro.y && 97>=centro.y)

{

fondoVerde= imread("/home/liz/Downloads/imagenes/4.png");

cv::resize(fondoVerde,fondoVerdeChica,Size(640,360),0,0,INTER_LINE

AR);

cvtColor(fondoVerdeChica, hsv, CV_BGR2HSV); inRange(hsv, Scalar(40,235,216), Scalar(80,255,255), binaria); cv::bitwise_not(binaria,binariaInvertida); imagenChica.copyTo(imagenChicaCopia); fondoVerdeChica.copyTo(copiaColor,binariaInvertida); imagenChicaCopia.copyTo(combinada);

arduino->write("{\"motor\":\"1\",\"grados\":\"90\"}");

}

if(257 <= centro.x && 317 >= centro.x && 43<=centro.y &&

103>=centro.y){

fondoVerde= imread("/home/liz/Downloads/imagenes/5.png");

cv::resize(fondoVerde,fondoVerdeChica,Size(640,360),0,0,INTER_LINE

AR);

cvtColor(fondoVerdeChica, hsv, CV_BGR2HSV); inRange(hsv, Scalar(40,235,216), Scalar(80,255,255), binaria); cv::bitwise_not(binaria,binariaInvertida); imagenChica.copyTo(imagenChicaCopia); fondoVerdeChica.copyTo(copiaColor,binariaInvertida); imagenChicaCopia.copyTo(combinada);

arduino->write("{\"motor\":\"1\",\"grados\":\"110\"}");

}

if(143 <= centro.x && 203>= centro.x && 80<=centro.y &&

140>=centro.y){

fondoVerde= imread("/home/liz/Downloads/imagenes/6.png");

cv::resize(fondoVerde,fondoVerdeChica,Size(640,360),0,0,INTER_LINE

AR);

cvtColor(fondoVerdeChica, hsv, CV_BGR2HSV); inRange(hsv, Scalar(40,235,216), Scalar(80,255,255), binaria); cv::bitwise_not(binaria,binariaInvertida); imagenChica.copyTo(imagenChicaCopia); fondoVerdeChica.copyTo(copiaColor,binariaInvertida); imagenChicaCopia.copyTo(combinada);

arduino->write("{\"motor\":\"1\",\"grados\":\"135\"}");

}

if(85 <= centro.x && 145>= centro.x && 163<=centro.y &&

223>=centro.y){

fondoVerde= imread("/home/liz/Downloads/imagenes/7.png");

cv::resize(fondoVerde,fondoVerdeChica,Size(640,360),0,0,INTER_LINE

AR);

 

cvtColor(fondoVerdeChica, hsv, CV_BGR2HSV); inRange(hsv, Scalar(40,235,216), Scalar(80,255,255), binaria); cv::bitwise_not(binaria,binariaInvertida); imagenChica.copyTo(imagenChicaCopia); fondoVerdeChica.copyTo(copiaColor,binariaInvertida); imagenChicaCopia.copyTo(combinada);

arduino->write("{\"motor\":\"1\",\"grados\":\"160\"}");

}

if(40<= centro.x && 100>= centro.x && 255<=centro.y && 315>=centro.y)

{

 

fondoVerde= imread("/home/liz/Downloads/imagenes/8.png");

cv::resize(fondoVerde,fondoVerdeChica,Size(640,360),0,0,INTER_LINE

AR);

cvtColor(fondoVerdeChica, hsv, CV_BGR2HSV); inRange(hsv, Scalar(40,235,216), Scalar(80,255,255), binaria); cv::bitwise_not(binaria,binariaInvertida); imagenChica.copyTo(imagenChicaCopia); fondoVerdeChica.copyTo(copiaColor,binariaInvertida); imagenChicaCopia.copyTo(combinada);

arduino->write("{\"motor\":\"1\",\"grados\":\"180\"}");

}

}

if(ui->radioButton->isChecked()){ //Mostrar imagenChica combinada.copyTo(imagenProcesada);

}

else if (ui->radioButton_2->isChecked()) {

//Mostrar imagen binaria

binaria14.copyTo(imagenProcesada);

}

else if (ui->radioButton_3->isChecked()) {

//Mostrar el rastreo del objeto copiaColor.copyTo(imagenProcesada);

}

else { //Mostrar la imagen error error.copyTo(imagenProcesada);

}

}

//Mostrar imagen en una etiqueta *label

//Paso # 1. Crear una Imagen de qt QImage img1 = Mat2QImage(imagenProcesada);

//Paso # 2. Convertir la img1 a mapaPixeles QPixmap img2 = QPixmap::fromImage(img1);

//Paso # 3. Limpiar los pixeles anteriores de la etiquetal ui->label->clear();

//Paso # 4. Mostar en la etiqueta, el mapa de pxls.

ui->label->setPixmap(img2);

contador++;

ui->lcdNumber->display(contador);

}

MainWindow::MainWindow(QWidget *parent) :

QMainWindow(parent), ui(new Ui::MainWindow)

{

 

ui->setupUi(this); conectarArduino(); ui->radioButton->setChecked(true); QTimer *cronometro = new QTimer(this); connect(cronometro,SIGNAL(timeout()),this, SLOT(funcionCronometro()));

cronometro->start(50);

camara.set(CV_CAP_PROP_FRAME_WIDTH,1920);

camara.set(CV_CAP_PROP_FRAME_HEIGHT,1080);

}

MainWindow::~MainWindow()

{

if(arduino->isOpen()){

arduino->close();

}

delete ui;

}

void MainWindow::on_pushButton_clicked()

{

QString correo = ui->lineEdit->text(); QString nombreImagen = ui->lineEdit_2->text(); QString asunto = ui->lineEdit_3->text();

QString comando = "mpack -s " + asunto + " " + nombreImagen + " " + correo;

}

void MainWindow::on_pushButton_2_clicked(bool checked)

{

}

void MainWindow::on_pushButton_3_clicked()

{

}

void MainWindow::on_dial_valueChanged(int value)

{

QString mensajeJSON = "{\"motor\":\"1\","; mensajeJSON += "\"grados\":\""; mensajeJSON += QString::number(value); mensajeJSON += "\"}";

ui->textBrowser->clear();

ui->textBrowser->setText(mensajeJSON);

ui->lcdNumber_2->display(value);

if(arduino_esta_conectado && arduino->isWritable()){

arduino->write(mensajeJSON.toUtf8().constData());

}

}

void MainWindow::on_checkBox_clicked(bool checked)

{

 

if(checked){ ui->radioButton->setText("Fondo");

ui->radioButton_2->setText("Binaria");

ui->radioButton_3->setText("Seguimiento");

}

}

8.3 Código Arduino #include<ArduinoJson.h> #include<Servo.h>

Servo motor1;

String mensajeJSON = ""; bool finMensaje = false;

void decodificarMensajeJSON(){ StaticJsonBuffer<100> bufferJSON; //mensajeJSON es una variable String //bufferJSON es una variable string para la biblioteca ArduinoJSON //objetoJSON es una variable que si es valida, tiene el formato JSON

JsonObject& objetoJSON = bufferJSON.parseObject(mensajeJSON);

//Averiguar si el objeto JSON es valido if(objetoJSON.success()){ //Si la cadena de caracteres si es un mensajeJSON, se decodifica. int numeroMotor = objetoJSON["motor"]; int grados = objetoJSON["grados"];

if(numeroMotor == 1){ if(grados >=0 && grados <= 180){

motor1.write(grados);

}

}

}

else{ Serial.println("El mensaje recibido, no tiene el formato apropiado");

}

}

void setup() { // put your setup code here, to run once:

Serial.begin(115200);

pinMode(13, OUTPUT);

mensajeJSON.reserve(100);

motor1.attach(9);

}

void loop() { // put your main code here, to run repeatedly:

if(finMensaje){ finMensaje = false; //Decodificar el mensaje decodificarMensajeJSON();

//Imprimir el mensaje recibido

//Serial.println(mensajeJSON);

mensajeJSON = "";

}

}

void serialEvent(){ while(Serial.available()){ char byteRecibido = Serial.read(); mensajeJSON += byteRecibido; if(byteRecibido == '}'){ finMensaje = true;

}

}

}