Hola mundo .NET Core en Linux

Introducción

En este articulo explicaremos como instalar .NET Core en un sistema operativo Linux (Ubuntu 20.04 LTS) y poder ejecutar aplicaciones .NET Core, además el ejecutarlas y así como también poder correr por ejemplo ASP.NET Core y que se pueda ver del lado del cliente para probar su correcto funcionamiento.

¿Porque ejecutar aplicaciones Microsoft en Linux? Las respuestas pueden ser muchas, podríamos decir por ir más allá de los muros que existían desde mucho tiempo y la “rivalidad” que supuestamente hicieron ver entre estos dos entornos de SO, otra por atraer a toda esa comunidad Linuxera para que puedan trabajar de manera mas cómoda para ellos, aplicaciones C# o paginas web bien soportadas con todo el poder de .NET Core, también otra respuesta puede ser reducir costos en una empresa de desarrollo o para ti mismo como usuario programador, en fin existen muchas razones por las cuales .NET Core tiene soporte sobre sistemas operativos basados en Linux.

.NET Core es compatible con Ubuntu. Este artículo describe cómo instalar .NET Core en Ubuntu. Cuando una versión de Ubuntu deja de ser compatible, .NET Core ya no es compatible con esa versión. Sin embargo, existen instrucciones un poco más personalizadas donde se puede instalar .NET Core en esas versiones.

Distribuciones soportadas

En el siguiente grafico según la fuente (https://docs.microsoft.com/en-us/dotnet/core/install/linux-ubuntu) tenemos la tabla comparativa de versiones con soporte hasta el momento y unas que no lo poseen.

En el caso de este articulo vamos a utilizar Ubuntu 20.04 LTS (https://ubuntu.com/#download) junto con .NET Core 3.1 mas adelante iremos con .NET Core 5.0

Necesitaremos lo siguiente:

  1. Linux instalado en alguna instancia instalada y configurada (https://www.process.st/checklist/ubuntu-server-setup-process/) yo lo deje hasta el paso 14 de esta manera ya tienes una instalación bien configurada.
  2. Putty para acceder vía SSH al servidor de Linux. (https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html ).
  3. Muchas ganas de aprender.

Tabla de contenido:

  1. Instalación de .NET Core 3.1 SDK y Runtime en ambiente Linux.
  2. Creación y compilación de tu primera aplicación en .NET Core.
  3. Creación de una aplicación en ASP.NET Core.
  4. Prueba de nuestra aplicación ASP.NET Core desde un navegador web.

Ahora ejecutamos Putty y colocamos la dirección IP del equipo remoto donde esta nuestro Linux instalado.

A continuación, ya establecemos conexión vía SSH, si todo bien tiene que aparecer la ventana ya del Shell de Linux donde solicita acceso, lo cual son las credenciales previamente configuradas del usuario de Ubuntu (usuario / contraseña).

Hasta este punto ya estamos dentro de la maquina con Linux, ahora bien, como vamos a ejecutar instalaciones, es importante tratar de hacer switch hacia el usuario Root que viene siendo quien tiene mas privilegios a nivel UNIX, por lo tanto, debemos de ejecutar los primeros comandos para cambiar de nuestro usuario normal a Root.

hughfernandez@neptuno:~$ su -

Pedirá la contraseña para usuario Root y hasta este punto ya podemos proceder a instalar .NET Core, pero primero siempre se recomienda ejecutar actualizaciones recientes con los siguientes comandos.

sudo apt-get update        # Obtiene la lista de actualizaciones disponibles.
sudo apt-get upgrade       # Actualiza estrictamente los paquetes actuales
sudo apt-get dist-upgrade  # Instala actualizaciones (nuevas)
sudo reboot		   # Reinicia el sistema operativo

Ya reiniciado el sistema antes de instalar .NET, ejecute los siguientes comandos para agregar la clave de firma del paquete de Microsoft a su lista de claves confiables y agregue el repositorio del paquete.

wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb

Instalación del SDK

Para instalar .NET Core SDK, ejecute los siguientes comandos:

  sudo apt-get update; \
  sudo apt-get install -y apt-transport-https && \
  sudo apt-get update && \
  sudo apt-get install -y dotnet-sdk-3.1

Instalación del Runtime

Los siguientes comandos instalan ASP.NET Core Runtime, que es el tiempo de ejecución más compatible para .NET Core. En su terminal, ejecute los siguientes comandos.

Como alternativa al ASP.NET Core Runtime, puede instalar .NET Core Runtime que no incluye el soporte de ASP.NET Core: reemplace aspnetcore-runtime-3.1 en el comando anterior con dotnet-runtime-3.1.

sudo apt-get install -y dotnet-runtime-3.1

Creación y compilación de tu primera aplicación en .NET Core.

De esta manera ya podemos contar con .NET Core 3.1 ya instalado tanto su versión SDK como Runtime para ejecutar nuestras aplicaciones. Si quieres saber que proyectos puedes ejecutar que están incluidos en este framework donde puedes obtener un listado completo ejecutando el siguiente comando:

dotnet new --help

Vamos a empezar nuestro “hola mundo” primeramente llevando un orden donde vamos a tener nuestros proyectos en Linux, para dar avance vamos a la carpeta Home como usuario Root y veremos la carpeta de nuestro usuario de Ubuntu, en este caso mi usuario es “hughfernandez” y ahí dentro vamos a crear la carpeta donde vamos a ejecutar nuestra primera aplicación con el comando.

mkdir holamundoConsola

Accedemos a ella y vemos que no tenemos nada, pero ya estamos sobre la carpeta.

Ejecutamos el siguiente comando:

dotnet new console

Si hacemos una inspección de lo generado listando los archivos de nuestro proyecto de consola con el comando:

ls -1l

Si queremos ya revisar un archivo especifico como por ejemplo “Program.cs” tenemos que ejecutar el siguiente comando (es importante escribir el archivo exactamente como aparece de lo contrario el nano va a abrir un archivo nuevo):

sudo nano Program.cs

Como ven en la imagen anterior ya pude acceder al archivo .cs llamado “Program” y ya pude agregar “Hola mundo desde Linux!”, para guardar los cambios presionamos Control + X, pedirá sobrescribir los cambios y vuelven de nuevo al entorno de comandos de Linux.

Ya hasta este punto ya podemos compilar nuestra aplicación y ejecutarla con los siguientes comandos:

dotnet build
dotnet run

De esta manera ya creamos la solución de consola, ingresamos en el archivo “Program.cs”, modificamos la línea de codigo con nuestro hola mundo y finalmente la compilación y ejecución del programa, pero esta vez bajo un entorno Linux.

Creación de una aplicación en ASP.NET Core.

Para el tema de ASP.NET core debemos de crear la carpeta como en el ejemplo anterior en mi caso le di nombre de “demoAsp”, ingresamos en ella y ejecutamos el siguiente comando para crear un proyecto ASP.NET Core:

dotnet new razor
o
dotnet new mvc

Si se preguntan por el nombre del proyecto, el comando “dotnet new” toma por defecto el nombre de la carpeta que crearon donde están ejecutando el comando.

Para ejecutar nuestra app en ASP.NET Core primero se debe de compilar con el comando “dotnet build” para que genere la carpeta “/bin/Debug/netcoreapp3.1” posteriormente ejecutar el siguiente comando dentro de la última carpeta antes mencionada:

dotnet demoAsp.dll

O para hacer solo una prueba directa si todo bien solo no situamos en la carpeta raíz del proyecto y ejecutamos normalmente el “dotnet run”.

Prueba de nuestra aplicación ASP.NET Core desde un navegador web.

Ya de esta manera ya nuestra aplicación en ASP.NET Core se esta ejecutando en el servidor Kestrel de .NET Core, pero no tenemos aun salida para poder acceder desde un navegador, esto porque se ejecuta dentro de localhost y Linux asume que solo puede acceder desde el propio Linux por lo tanto se debe de ejecutar el siguiente comando:

dotnet run --urls "http://0.0.0.0:5000"

En este caso el argumento “urls” específica a Kestrel en bajo qué direcciones IP y puertos debe escuchar. Por defecto Kestrel solo escuchará a la dirección localhost por lo que debemos especificar de forma explícita que deseamos que escuche a cualquier dirección IP para realizar esta prueba.

Ahora bien para probar que podemos acceder desde cualquier cliente nos vamos al equipo Windows y abrimos cualquier navegador web e ingresamos la dirección ip de la maquina Linux y el puerto 5000 “http://la-ip-de-tu-servidor:5000” para verificar que la aplicación web está funcionando:

Si necesitas que se pueda acceder al sitio web de forma remota (externa) desde otros ordenadores de manera automática sin ejecutar el comando urls lo puedes programar directamente en el proyecto, deberás vincularlo de manera diferente.

Para hacer esto, se debe de acceder en los archivos del proyecto recién creado y abrir “Program.cs”. Aquí agrega una llamada al método “UseUrls” de la siguiente manera:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
  WebHost.CreateDefaultBuilder(args)
    .UseUrls("http://0.0.0.0:5000")
    .UseStartup<Startup>();

Esto vincula el sitio web ASP.NET Core a todas las direcciones IP del servidor, en lugar de solo a localhost, que es lo que hace de manera predeterminada.

Conclusión

Hasta este punto y si pudiste seguir con éxito todos los pasos en este artículo, ya estás en la capacidad de poder realizar lo siguiente.

  1. Configurar el instalar Linux Ubuntu.
  2. Saber acceder remotamente a una maquina Linux mediante protocolo SSH.
  3. Saber instalar tanto SDK como Runtime de .NET Core en la versión que quieras que este disponible.
  4. Saber moverte dentro de los directorios de Linux.
  5. Empezar a generar proyectos en .NET Core en ambiente Linux.
  6. Compilar y poder ejecutar aplicaciones .NET Core en Linux.
  7. Ejecutar una página en ASP.NET Core desde cualquier navegador web.

En una próxima entrega voy a explicarles como se publicar y desplegar una aplicación ASP.NET Core a manera de servicio dentro de Linux, configurar el servidor, aplicar seguridad mediante SSL y hostearlo en un servidor nginx a manera de proxy inverso.

Consultas elasticas en SQL Azure

No les pasa que tenemos todo listo en nuestro servidor Azure (servicio, servidor de base de datos, bases de datos, Certificado SSL, Dominio, etc…); ¡Todo perfecto para que nuestra aplicación ya salga a tope con todos los hierros y de repente surge una escalabilidad o una implementación adicional y tenemos que crear una base de datos o tomar los datos de otra base de datos para respetar la integridad de los datos y tomalaaaa!… donde queremos hacer algo asi?:

Use BaseDeDatos1

SELECT  *  FROM [BaseDeDatos2].dbo.Tabla1

“Msg 40515, Level 15, State 1, Line 16
Reference to database and/or server name in ‘BaseDeDatos2.dbo.Tabla1’ is not supported in this version of SQL Server.”

No sufras más y sigue este pequeño tutorial para poder realizar consultas entre bases de datos en distintos servidores de Azure o en el mismo servidor per se.

cross-search-tools

Consultas elásticas

La función de consulta elástica le permite ejecutar una consulta de Transact-SQL que abarca varias bases de datos en la base de datos SQL de Azure. Le permite realizar consultas entre bases de datos para acceder a tablas remotas y conectar herramientas de Microsoft y de terceros (Excel, PowerBI, Tableau, etc.) para consultar en niveles de datos con múltiples bases de datos. Con esta función, puede escalar consultas a grandes niveles de datos en la base de datos SQL y visualizar los resultados en informes de inteligencia empresarial (BI).

¿Por qué usar consultas elásticas?

Base de datos SQL Azure

Consulta en todas las bases de datos SQL de Azure en T-SQL. Esto permite la consulta de solo lectura de las bases de datos remotas. Esto proporciona una opción para que los clientes actuales de SQL Server local migren aplicaciones con nombres de tres y cuatro partes o un servidor vinculado a SQL DB.

Disponible en nivel estándar

La consulta elástica es compatible con el nivel de rendimiento estándar además del nivel de rendimiento Premium.

Enviar a bases de datos remotas

Las consultas elásticas ahora pueden enviar parámetros SQL a las bases de datos remotas para su ejecución.

Ejecución de procedimiento almacenado

Ejecute llamadas a procedimientos almacenados remotos o funciones remotas utilizando sp_execute _remote.

Flexibilidad

Las tablas externas con consulta elástica ahora pueden hacer referencia a tablas remotas con un esquema o nombre de tabla diferente.

Escenarios elásticos de consulta

El objetivo es facilitar la consulta de escenarios donde múltiples bases de datos aportan filas en un solo resultado global. La consulta puede ser compuesta por el usuario o la aplicación directamente, o indirectamente a través de herramientas que están conectadas a la base de datos. Esto es especialmente útil cuando se crean informes, se usan herramientas comerciales de BI o de integración de datos, o cualquier aplicación que no se puede cambiar. Con una consulta elástica, puede realizar consultas en varias bases de datos utilizando la experiencia de conectividad conocida de SQL Server en herramientas como Excel, PowerBI, Tableau o Cognos. Una consulta elástica permite un acceso fácil a una colección completa de bases de datos a través de consultas emitidas por SQL Server Management Studio o Visual Studio, y facilita la consulta entre bases de datos desde Entity Framework u otros entornos ORM. La Figura 1 muestra un escenario en el que una aplicación en la nube existente (que utiliza la biblioteca del cliente de base de datos elástica) se basa en un nivel de datos escalado, y una consulta elástica para informes entre bases de datos.

Ya leida la teoria vamos a la practica.

1 – Crear las bases de datos de muestra.

Para empezar, necesitamos crear dos bases de datos, Customers y Orders (Clientes y Ordenes ESP), ya sea en el mismo o en diferentes servidores lógicos.

Ejecute las siguientes consultas en la base de datos Orders para crear la tabla OrderInformation e ingresar los datos de muestra.


CREATE TABLE [dbo].[OrderInformation](
[OrderID] [int] NOT NULL,
[CustomerID] [int] NOT NULL
)
INSERT INTO [dbo].[OrderInformation] ([OrderID], [CustomerID]) VALUES (123, 1)
INSERT INTO [dbo].[OrderInformation] ([OrderID], [CustomerID]) VALUES (149, 2)
INSERT INTO [dbo].[OrderInformation] ([OrderID], [CustomerID]) VALUES (857, 2)
INSERT INTO [dbo].[OrderInformation] ([OrderID], [CustomerID]) VALUES (321, 1)
INSERT INTO [dbo].[OrderInformation] ([OrderID], [CustomerID]) VALUES (564, 8)

Ahora, ejecute la consulta siguiente en la base de datos de Customers para crear la tabla CustomerInformation e ingrese los datos de muestra.


CREATE TABLE [dbo].[CustomerInformation](
[CustomerID] [int] NOT NULL,
[CustomerName] [varchar](50) NULL,
[Company] [varchar](50) NULL
CONSTRAINT [CustID] PRIMARY KEY CLUSTERED ([CustomerID] ASC)
)
INSERT INTO [dbo].[CustomerInformation] ([CustomerID], [CustomerName], [Company]) VALUES (1, 'Jack', 'ABC')
INSERT INTO [dbo].[CustomerInformation] ([CustomerID], [CustomerName], [Company]) VALUES (2, 'Steve', 'XYZ')
INSERT INTO [dbo].[CustomerInformation] ([CustomerID], [CustomerName], [Company]) VALUES (3, 'Lylla', 'MNO')

2 – Crear objetos de base de datos.

Base de datos de clave maestra y credenciales

  1. Abra SQL Server Management Studio o SQL Server Data Tools en Visual Studio.
  2. Conéctese a la base de datos Pedidos y ejecute los siguientes comandos T-SQL:

    CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'password';
    CREATE DATABASE SCOPED CREDENTIAL ElasticDBQueryCred
    WITH IDENTITY = 'username',
    SECRET = 'password';

    El “username” y el “password” deben ser el nombre de usuario y la contraseña utilizados para iniciar sesión en la base de datos de Customers. La autenticación con Azure Active Directory con consultas elásticas no es actualmente compatible.

Fuentes de datos externas

Para crear una fuente de datos externa, ejecute el siguiente comando en la base de datos Orders


CREATE EXTERNAL DATA SOURCE MyElasticDBQueryDataSrc WITH
(TYPE = RDBMS,
LOCATION = 'server_name.database.windows.net',
DATABASE_NAME = 'Customers',
CREDENTIAL = ElasticDBQueryCred,
) ;

Tablas externas

Cree una tabla externa en la base de datos Orders, que coincida con la definición de la tabla CustomerInformation:


CREATE EXTERNAL TABLE [dbo].[CustomerInformation]
( [CustomerID] [int] NOT NULL,
[CustomerName] [varchar](50) NOT NULL,
[Company] [varchar](50) NOT NULL)
WITH
( DATA_SOURCE = MyElasticDBQueryDataSrc)

3 – Ejecute una consulta de muestra T-SQL de base de datos elástica.

Una vez que haya definido su fuente de datos externa y sus tablas externas, ahora puede usar T-SQL para consultar sus tablas externas. Ejecute esta consulta en la base de datos de pedidos:


SELECT OrderInformation.CustomerID, OrderInformation.OrderId, CustomerInformation.CustomerName, CustomerInformation.Company
FROM OrderInformation
INNER JOIN CustomerInformation
ON CustomerInformation.CustomerID = OrderInformation.CustomerID

4 – Costo

Actualmente, la función de consulta de base de datos elástica está incluida en el costo de su base de datos SQL de Azure.

 


De esta manera no tienes excusa para poder enlazar una o más bases de datos en una consulta de TSQL y lo mejor que desde Azure.

Espero les sea de utilidad la información y que la puedan implementar en sus trabajos o en algún caso poco común que les pueda ocurrir.

Nos vemos en un próximo articulo 🙂

 

Como enviar un objeto con imagen por POST hacia un WebAPI en formato JSON

Sabemos que Json está revolucionando la programación hoy en día. XML ya empieza a irse desplazando de un tiempo para acá, mucho auge de tecnologías basadas en motores de JavaScript pero bueee la tecnología es así….

Este código es bien sencillo, por lo tanto en este artículo solo voy a hacer énfasis en ese fragmento de código, por lo que no voy a explicar otras cosas alrededor, la idea es poder tener la lógica en nuestras apps y que puedas incorporar esta funcionalidad tan vital para aplicaciones que interactúan mucho con imágenes o alguna captura de multimedios.

Previo a realizar esta subida de data hacia un servidor se debe de tener una WebApi, las WebAPIs son lo más sencillo y dinámico para exponer información, ya sea de un repositorio de data, así como la misma establece una capa de datos muy dinámica y portable por ser multiplataforma.

Ya teniendo tu propia WebAPI arriba en algún servidor (Azure, IIS, etc), se debe de crear una aplicación cliente que consumirá información y podrá hacer peticiones, sencillamente estamos trabajando en C#, ya sea un app Winform, WPF, Xamarin, UWP . También necesitamos la librería Json.Net que la puedes conseguir en Nuget

Volviendo al código tenemos:

public void UploadData(byte[] imagen) //recibimos la imagen como parametro en el metodo
{
  using (var client = new HttpClient())
  {
    var objetoClase1 = new ObjetoClase()
    {
      ID = Guid.NewGuid(),
      MediaStream = imagen, //esta es la imagen representada en Byte[]
      Description = "dummy";
    };
//La magia esta aqui
    var response = await client.PostAsync(new Uri("URL del WebAPI"), new HttpStringContent(JsonConvert.SerializeObject(objetoClase1), UnicodeEncoding.Utf8, "application/json"));

    if (response.IsSuccessStatusCode)
    {
    //Al entrar aqui es porque el POST hacia el webAPI fue exitoso (Codigo 200:OK)
    }
}
}

Espero les sea de utilidad.
Enjoy….

Captura de movimiento para animación usando Kinect

Imagen

En lugar de complejos trajes y estudios, un equipo de animadores está usando Kinect para recrear movimientos.

La captura de movimiento es una técnica compleja, que se utiliza para crear personajes digitales – como Gollum en el Señor de los Anillos, por ejemplo. Sin embargo, hay formas más económicas de lograr casi lo mismo, y eso es lo que intentaron probar Tomás Vergara y su empresa, Primitiva.

La tarea era animar a los personajes del comercial televisivo de la empresa La Araucana en Chile. En lugar de hacer animación tradicional, Primitiva trabajó con un par de Kintect para capturar el movimiento de los personajes. 

“Animar 10 segundos tradicionalmente nos toma más o menos cinco días. En este caso fueron 21 animaciones de 10 segundos aproximadamente cada una, o sea nos podría haber tomado tranquilamente cinco meses la producción. Pero con esta técnica nos demoramos sólo mes y medio”, explica Vergara.

¿Qué usaron además de Kinect?

Tomás Vergara – Usamos dos Kinect para Windows, un programa que se llama iPisoft (que hace de puente el Kinect con el computador). El resultado que nos entregó el software, lo metimos a Maya y con un poco de programación inhouse logramos hacer andar el sistema en nuestros personajes de manera muy rápida. El hecho de que fueran siete personajes con estructuras diferentes hace mucho más complicado el tema, y por lo mismo se logró optimizar para que se pudiese traspasar la información de manera rápida.

¿Qué ventajas tiene respecto a otras formas de animar?

Un poco la gracia de este sistema es que no hay que ponerle traje a los actores, y no hay que arrendar un lugar super caro. Con esta técnica tenemos los resultados al día siguiente, y si no nos gusta como quedó (que pasa mucho), por último lo grabamos de nuevo.

Diferencias en Kinect for windows y Kinect for xbox 360

Aca les dare unas diferencias entre el Kinect normal que viene con nuestro Xbox 360 y el Kinect para windows, esto es para despejar las dudas que siempre me comentan en los foros y en los grupos de debate…

Imagen

 

Imagen

 

Hay mas caracteristicas y como veran KINECT FOR WINDOWS tiene mas capacidades que el Kinect para Xbox 360 una de las cosas que a veces me preguntan es el licenciamiento, ya lo acabo de colocar en la tabla.

Claro a estos cada dia se le agregan mas cosas para tener muchas mas herramientas y funcionalidades de este dispositivo tanto para Windows como para xbox los 2 se pueden conectar al PC y trabajar con ellos…

Que no vayan quedando mas dudas … 😉

Libros de desarrollo para KINECT

A continuacion les dare algunos enlaces de libros para desarrollo en Kinect por varios autores:

1 – Beginning Kinect Programming with the Microsoft Kinect SDK

Imagen

 

 

 

 

 

 

 

  • Paperback: 324 pages
  • Publisher: Apress; 1st edition (February 23, 2012)
  • Language: English
  • ISBN-10: 1430241047
  • ISBN-13: 978-1430241041

 

2 – Arduino and Kinect Projects: Design, Build, Blow Their Minds

Imagen

  • Paperback: 416 pages
  • Publisher: Apress; 1st edition (April 18, 2012)
  • Language: English
  • ISBN-10: 1430241675
  • ISBN-13: 978-1430241676

 

3 – Start Here! Learn the Kinect API

Imagen

  • Paperback: 272 pages
  • Publisher: Microsoft Press (July 6, 2012)
  • Language: English
  • ISBN-10: 0735663963
  • ISBN-13: 978-0735663961

 

4 – Kinect for Windows SDK Programming Guide

Imagen

  • Paperback: 392 pages
  • Publisher: Packt Publishing (December 26, 2012)
  • Language: English
  • ISBN-10: 1849692386
  • ISBN-13: 978-1849692380

 

5 – Meet the Kinect: An Introduction to Programming Natural User Interfaces

Imagen

  • Paperback: 220 pages
  • Publisher: Apress; 1st edition (December 23, 2011)
  • Language: English
  • ISBN-10: 1430238887
  • ISBN-13: 978-1430238881

 

Ahora si no hay excusas para programar en Kinect 😉

Enjoy y salu2…

Kinect for Windows SDK 1.7! Novedades

Pues si volvieron a sacar otra version, esta vino con muy buenos ajustes y cosas interesantes para trabajar con nuestro Kinect, ya la version esta disponible para ser descargada, he incluido en este post como los otros, algunos nuevos avances como el Kinect Interactions y Kinect Fusion (Muy interesantes de por si)…

Imagen

Kinect Interaction.
Una combinación de nuevos controles hace que sea más fácil para que los usuarios interactúan a través de la tecnología de la computación natural. Estos incluyen “push” para seleccionar objetos virtuales, “agarre” para mover y reconocimiento de desplazamiento, de hasta cuatro manos simultáneamente, y actualizadas las guidelines de interfaz humana. Kinect Interaction ayudar a asegurar una experiencia de usuario altamente consistente de una aplicación a otra, guardar los desarrolladores y las empresas tiempo y dinero, y le permiten centrarse en los problemas únicos que están trabajando para solucionarlo.

Controles Kinect Windows Presentation Foundation WPF
Nuevo Windows Presentation Foundation (WPF) hacen que sea fácil para los desarrolladores crear de alta calidad, Kinect interactiva para aplicaciones Windows.

    “Push” de control para seleccionar los objetos virtuales
    “Grip” de control para selección mover y desplazarse
    Kinect cursor
    Usuario espectador

Interacción Stream

Interacción Stream permite nuevas funcionalidades en el diseño de Kinect para aplicaciones Windows, incluyendo:

    Reconocimiento Grip, incluyendo la capacidad de mapear gestos con las manos para cursores en pantalla. El sensor Kinect para Windows puede reconocer hasta cuatro punteros de la mano. Esto permite que dos personas interactúan con las dos manos al mismo tiempo y permite a los desarrolladores crear interacciones más complejas, como la capacidad de “zoom”.
    Zona de interacción física, una zona definida dentro de la cual un usuario puede contener sus movimientos para interactuar con el sensor Kinect para Windows más eficaz, similar a la zona física en la que se realice el lenguaje de signos.

Actualizado Human Interface Guidelines

Las Directrices de interfaz humana proporcionar las mejores prácticas para Kinect para el desarrollo de Windows y el diseño. El documento comparte diseños fuertes que se han probado y probado, así como orientación sobre la manera de evitar las dificultades que puedan impedir su éxito. Las directrices se han actualizado para reflejar las mejores prácticas para las nuevas interacciones y controles. Echa un vistazo a la muestra InteractionGallery-WPF para ver algunas de estas directrices en la práctica.

Imagen

Kinect Fusion
La última versión ahora permite a los desarrolladores a Kinect programa para aplicaciones Windows que reconstruyen las representaciones de alta calidad en tres dimensiones (3-D) de las personas y objetos en tiempo real.

  • En tiempo real, GPU asistida por objeto 3-D y la reconstrucción de la escena usando el sensor Kinect para Windows
  • Capacidad de inferir el sensor de posición relativa y la orientación de una escena 3-D para la aplicación de realidad aumentada
  • Los avanzados algoritmos que son lo suficientemente potente como para los movimientos de sensor grande y cambios de escena durante la exploración
  • DirectX11 tarjetas gráficas compatibles con apoyo
  • AMD Radeon 7950 y GTX560 NVIDIA han sido validados para funcionar a velocidades interactivas
  • Kinect Studio Fusion y ejemplos se muestran en 3-D capacidades de escaneo
  • No en tiempo real de la CPU para el modo de escenarios de tipos no interactivos

Imagen

Kinect Fusion, una herramienta incluye también en Kinect para Windows SDK 1.7, puede crear de alta precisión
3-D representaciones de personas y objetos en tiempo real.

Imagen

Kinect Fusion abre una variedad de nuevos escenarios para los negocios y desarrolladores, incluyendo la realidad aumentada,
3-D de impresión, diseño de interiores e industrial, y el cuerpo de escaneo para cosas como guarnición de encargo y comprar ropa mejorada.

Puedes descargar la ultima version de Kinect for Windows SDK aqui

Demo Kinect Comandos por voz en ESPAÑOL

En este post explicare sobre el uso de el arreglo de microfonos del Kinect con un ejemplo donde a travez de las librerias Microsoft Speech SDK y el SDK de KINECT podremos a travez de comandos de voz dar alguna instruccion al computador para mostrar algo en una aplicacion C# natural en WPF…

Se me ocurrio un ejemplo similar al que nos trae la SDK Toolkit de Kinect donde al hablar se muestra el espectro de voz de la persona que habla, pero en este caso, utilizare para explicarles sencillamente como ejemplo una aplicacion que al decir un color de los que muestre en la aplicacion esta sea capaz de identificarlo y de pintarlo en la aplicación, dando un rango de exito o de fracaso…

Pensaran que es algo complejo de analizar y de sintetizar la voz y esas cosas pero realmente no nos complicaremos la vida y por suerte ya existen herramientas a la mano para hacer estas cosas como

Bien para esto es necesario previamente tener el Microsoft Speech SDK en este caso la version mas actual que es la 11.0 que la podemos descargar en el siguiente enlace: Microsoft Speech SDK v11.0

Tambien necesitaremos de una libreria de idioma en nuestro caso Español que debemos de desacargar de la pagina Oficial de Kinect en nuestro caso ES-mx (Español-Mexico) o ES-es (Español-España): Kinect for Windows Language Packs v11.0

Una vez instalado estas, procedemos ahora a crear un nuevo proyecto WPF en C# en Visual Studio 2012 o 2010 como lo vayan preferiendo.

blogaudiokinet1

Una vez creada la solucion del proyecto nos vamos al archivo MainWindow.xaml donde escribiremos el siguiente codigo..


<Window x:Class="WpfAudioKinectPruebaHablar.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        
        Title="Kinect Audio Demo" Height="364" Width="680">
    <Grid Background="white">
        <TextBlock Text="KINECT Demo Audio Prueba" FontSize="36" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,5,0,0" FontWeight="Light" />
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Bottom" >
            <TextBlock x:Name="tbColor" Height="100" Width="500"/>            
            <TextBlock x:Name="tbInfo" Text="" Foreground="Black" Height="50" FontSize="20" TextAlignment="Center" Padding="0,10,0,0"/>
            <TextBlock x:Name="tbSpeech" Text="" Foreground="Black" Height="60" FontSize="16" TextAlignment="Left" Padding="0,10,0,10"/>
        </StackPanel>
        <TextBlock FontSize="16" HorizontalAlignment="Left" Margin="80,93,0,0" Text="diga algo para activar el reconocimiento" VerticalAlignment="Top" Width="379" FontWeight="Light" />
        
    </Grid>
</Window>

En el codigo aparecen tres TextBlock de nombre tbColor, tbInfo, tbSpeech estos son para mostrar una breve leyenda, el color procesado y el indice de acierto…

Antes de iniciar el codigo y la logica de la aplicacion debemos de agregar las referencias o DLLs que ya habiamos mencionado que son la Microsoft.Speech y Microsoft.Kinect

addreference

ahora bien, vamos con la parte mas interesante que es la de trabajar con las librerias de Microsoft Speech y por supuesto la libreria de KINECT sdk, procedemos a abrir el code-behind de MainWindow.xaml que es MainWindow.cs; donde ya abierto, agregamos la libreria Microsoft.Kinect, las siguientes Microsoft.Speech.AudioFormat y Microsoft.Speech.Recognition


using Microsoft.Kinect;

using Microsoft.Speech.AudioFormat;
using Microsoft.Speech.Recognition;

siguiendo con el codigo creamos 5 variables de tipo SolidColorBrush y le di a cada una un color y creamos la variable kinect de tipo KinectSensor, un DispatcherTimer que le llame readyTimer y dos variables muy interesantes que vienen de la libreria Speech que son EnergyCalculatingPassThroughStream que es la variable que contendra el espectro de la energia y la forma de la voz sintetizada para a travez de la segunda variable que es la que crea una especie de gramatica dependiendo de la cultura y el enfasis de la voz la como se muestra en el siguiente codigo.


 private readonly SolidColorBrush redBrush = new SolidColorBrush(Colors.Red);
 private readonly SolidColorBrush greenBrush = new SolidColorBrush(Colors.Green);
 private readonly SolidColorBrush yellowBrush = new SolidColorBrush(Colors.Yellow);
 private readonly SolidColorBrush blueBrush = new SolidColorBrush(Colors.Blue);
 private readonly SolidColorBrush WhiteBrush = new SolidColorBrush(Colors.White);

 KinectSensor kinect;

 private DispatcherTimer readyTimer;
 private EnergyCalculatingPassThroughStream stream;
 private SpeechRecognitionEngine speechRecognizer;

“Suena dificil y complejo pero son solo sencillas primitivas para trabajar el reconocimiento de voz en nuestras aplicaciones”.. aca les dejo unas rutinas establecidas para el control de la voz, sintetizarla y despues tomarla en la variable para asi ahora poder trabajar con ella a travez del Kinect, por ahora solo les dejo el siguiente codigo:

 private class EnergyCalculatingPassThroughStream : Stream
 {
   private const int SamplesPerPixel = 10;

   private readonly double[] energy = new double[500];
   private readonly object syncRoot = new object();
   private readonly Stream baseStream;

   private int index;
   private int sampleCount;
   private double avgSample;

 public EnergyCalculatingPassThroughStream(Stream stream)
 {
   this.baseStream = stream;
 }

 public override long Length
 {
   get { return this.baseStream.Length; }
 }

 public override long Position
 {
   get { return this.baseStream.Position; }
   set { this.baseStream.Position = value; }
 }

 public override bool CanRead
 {
   get { return this.baseStream.CanRead; }
 }

 public override bool CanSeek
 {
   get { return this.baseStream.CanSeek; }
 }

 public override bool CanWrite
 {
   get { return this.baseStream.CanWrite; }
 }

 public override void Flush()
 {
   this.baseStream.Flush();
 }

 public void GetEnergy(double[] energyBuffer)
 {
   lock (this.syncRoot)
   {
     int energyIndex = this.index;
     for (int i = 0; i < this.energy.Length; i++)       {       energyBuffer[i] = this.energy[energyIndex];       energyIndex++;       if (energyIndex >= this.energy.Length)
     {
       energyIndex = 0;
     }
   }
  }
 }

  public override int Read(byte[] buffer, int offset, int count)
  {
    int retVal = this.baseStream.Read(buffer, offset, count);
    const double A = 0.3;
    lock (this.syncRoot)
    {
    for (int i = 0; i < retVal; i += 2)      {        short sample = BitConverter.ToInt16(buffer, i + offset);        this.avgSample += sample * sample;        this.sampleCount++;        if (this.sampleCount == SamplesPerPixel)        {          this.avgSample /= SamplesPerPixel;          this.energy[this.index] = .2 + ((this.avgSample * 11) / (int.MaxValue / 2));          this.energy[this.index] = this.energy[this.index] > 10 ? 10 : this.energy[this.index];

        if (this.index > 0)
        {
          this.energy[this.index] = (this.energy[this.index] * A) + ((1 - A) * this.energy[this.index - 1]);
        }

     this.index++;

     if (this.index >= this.energy.Length)
     {
       this.index = 0;
     }

       this.avgSample = 0;
       this.sampleCount = 0;
    }
   }
  }

  return retVal;
 }

  public override long Seek(long offset, SeekOrigin origin)
  {
    return this.baseStream.Seek(offset, origin);
  }

  public override void SetLength(long value)
  {
    this.baseStream.SetLength(value);
  }

  public override void Write(byte[] buffer, int offset, int count)
  {
    this.baseStream.Write(buffer, offset, count);
  }
 }

Y aca les dejo todo codigo fuente para poner a andar nuestro Kinect por voz y en español!…. despues les seguire mostrando detalladamente cada una de las funcionalidades de este demo para que lo apliquen a un sin fin de cosas.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

using Microsoft.Kinect;

using Microsoft.Speech.AudioFormat;
using Microsoft.Speech.Recognition;
namespace WpfAudioKinectPruebaHablar
{
 ///
 /// Interaction logic for MainWindow.xaml
 ///
 public partial class MainWindow : Window
 {
 private readonly SolidColorBrush redBrush = new SolidColorBrush(Colors.Red);
 private readonly SolidColorBrush greenBrush = new SolidColorBrush(Colors.Green);
 private readonly SolidColorBrush yellowBrush = new SolidColorBrush(Colors.Yellow);
 private readonly SolidColorBrush blueBrush = new SolidColorBrush(Colors.Blue);
 private readonly SolidColorBrush WhiteBrush = new SolidColorBrush(Colors.White);

 KinectSensor kinect;

 private DispatcherTimer readyTimer;
 private EnergyCalculatingPassThroughStream stream;
 private SpeechRecognitionEngine speechRecognizer;

 #region class EnergyCalculatingPassThroughStream

 private class EnergyCalculatingPassThroughStream : Stream
 {
 private const int SamplesPerPixel = 10;

 private readonly double[] energy = new double[500];
 private readonly object syncRoot = new object();
 private readonly Stream baseStream;

 private int index;
 private int sampleCount;
 private double avgSample;

 public EnergyCalculatingPassThroughStream(Stream stream)
 {
 this.baseStream = stream;
 }

 public override long Length
 {
 get { return this.baseStream.Length; }
 }

 public override long Position
 {
 get { return this.baseStream.Position; }
 set { this.baseStream.Position = value; }
 }

 public override bool CanRead
 {
 get { return this.baseStream.CanRead; }
 }

 public override bool CanSeek
 {
 get { return this.baseStream.CanSeek; }
 }

 public override bool CanWrite
 {
 get { return this.baseStream.CanWrite; }
 }

 public override void Flush()
 {
 this.baseStream.Flush();
 }

 public void GetEnergy(double[] energyBuffer)
 {
 lock (this.syncRoot)
 {
 int energyIndex = this.index;
 for (int i = 0; i < this.energy.Length; i++) { energyBuffer[i] = this.energy[energyIndex]; energyIndex++; if (energyIndex >= this.energy.Length)
 {
 energyIndex = 0;
 }
 }
 }
 }

 public override int Read(byte[] buffer, int offset, int count)
 {
 int retVal = this.baseStream.Read(buffer, offset, count);
 const double A = 0.3;
 lock (this.syncRoot)
 {
 for (int i = 0; i < retVal; i += 2) { short sample = BitConverter.ToInt16(buffer, i + offset); this.avgSample += sample * sample; this.sampleCount++; if (this.sampleCount == SamplesPerPixel) { this.avgSample /= SamplesPerPixel; this.energy[this.index] = .2 + ((this.avgSample * 11) / (int.MaxValue / 2)); this.energy[this.index] = this.energy[this.index] > 10 ? 10 : this.energy[this.index];

 if (this.index > 0)
 {
 this.energy[this.index] = (this.energy[this.index] * A) + ((1 - A) * this.energy[this.index - 1]);
 }

 this.index++;

 if (this.index >= this.energy.Length)
 {
 this.index = 0;
 }

 this.avgSample = 0;
 this.sampleCount = 0;
 }
 }
 }

 return retVal;
 }

 public override long Seek(long offset, SeekOrigin origin)
 {
 return this.baseStream.Seek(offset, origin);
 }

 public override void SetLength(long value)
 {
 this.baseStream.SetLength(value);
 }

 public override void Write(byte[] buffer, int offset, int count)
 {
 this.baseStream.Write(buffer, offset, count);
 }
 }
 #endregion

public MainWindow()
{
 InitializeComponent();

 kinect = KinectSensor.KinectSensors[0];

 if (this.kinect != null)
 {
 this.InitializeKinect();
 }
}

 private void Start()
 {
 var audioSource = this.kinect.AudioSource;
 audioSource.BeamAngleMode = BeamAngleMode.Adaptive;

 audioSource.EchoCancellationMode = EchoCancellationMode.CancellationAndSuppression;
 var kinectStream = audioSource.Start();

 this.stream = new EnergyCalculatingPassThroughStream(kinectStream);
 this.speechRecognizer.SetInputToAudioStream(this.stream, new SpeechAudioFormatInfo
 (EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, null));
 this.speechRecognizer.RecognizeAsync(RecognizeMode.Multiple);
 }

 private static RecognizerInfo GetKinectRecognizer()
 {
 Func<RecognizerInfo, bool> matchingFunc = r =>
 {
 string value;
 r.AdditionalInfo.TryGetValue("Kinect", out value);
 return "True".Equals(value, StringComparison.InvariantCultureIgnoreCase) &&
 "es-ES".Equals(r.Culture.Name,StringComparison.InvariantCultureIgnoreCase);
 };
 return SpeechRecognitionEngine.InstalledRecognizers().Where(matchingFunc).FirstOrDefault();
 }

 private SpeechRecognitionEngine CreateSpeechRecognizer()
 {
 RecognizerInfo ri = GetKinectRecognizer();
 if (ri == null)
 {
 MessageBox.Show(@"Hay un problema al inicializar el dispositivo de reconocimiento de voz.
 asegurese de tener Microsoft Speech SDK instalado y configurado.",
 "Falla al cargar Speech SDK", MessageBoxButton.OK, MessageBoxImage.Error);

 this.Close();
 return null;
 }

 SpeechRecognitionEngine sre;
 try
 {
 sre = new SpeechRecognitionEngine(ri.Id);
 }
 catch
 {
 MessageBox.Show(@"Hay un problema al inicializar el dispositivo de reconocimiento de voz.
 asegurese de tener Microsoft Speech SDK instalado y configurado.", "Falla al cargar Speech SDK",
 MessageBoxButton.OK, MessageBoxImage.Error);
 this.Close();
 return null;
 }

 var colors = new Choices();
 colors.Add("rojo");
 colors.Add("verde");
 colors.Add("azul");
 colors.Add("amarillo");

 var gb = new GrammarBuilder { Culture = ri.Culture };
 gb.Append(colors);

 // Create the actual Grammar instance, and then load it into the speech recognizer.
 var g = new Grammar(gb);

 sre.LoadGrammar(g);
 sre.SpeechRecognized += this.SreSpeechRecognized;
 sre.SpeechHypothesized += this.SreSpeechHypothesized;
 sre.SpeechRecognitionRejected += this.SreSpeechRecognitionRejected;

 return sre;
 }

 private void RejectSpeech(RecognitionResult result)
 {
 string status = "Rechazado: " + (result == null ? string.Empty : result.Text + " " + result.Confidence);
 this.ReportSpeechStatus(status);

 Dispatcher.BeginInvoke(new Action(() => { tbColor.Background = WhiteBrush; }), DispatcherPriority.Normal);
 }

 private void SreSpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e)
 {
 this.RejectSpeech(e.Result);
 }

 private void SreSpeechHypothesized(object sender, SpeechHypothesizedEventArgs e)
 {
 this.ReportSpeechStatus("Hipotetico: " + e.Result.Text + " " + e.Result.Confidence);
 }

 private void SreSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
 {
 SolidColorBrush brush;

 if (e.Result.Confidence < 0.7) { this.RejectSpeech(e.Result); return; } switch (e.Result.Text.ToUpperInvariant()) { case "ROJO": brush = this.redBrush; break; case "VERDE": brush = this.greenBrush; break; case "AZUL": brush = this.blueBrush; break; case "AMARILLO": brush = this.yellowBrush; break; default: brush = this.WhiteBrush; break; } string status = "Reconocido: " + e.Result.Text + " " + e.Result.Confidence; this.ReportSpeechStatus(status); Dispatcher.BeginInvoke(new Action(() => { tbColor.Background = brush; }), DispatcherPriority.Normal);
 }

 private void ReportSpeechStatus(string status)
 {
 Dispatcher.BeginInvoke(new Action(() => { tbSpeech.Text = status; }), DispatcherPriority.Normal);
 }

 private void UpdateInstructionsText(string instructions)
 {
 Dispatcher.BeginInvoke(new Action(() => { tbInfo.Text = instructions; }), DispatcherPriority.Normal);
 }

 private void MainWindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
 {
 this.UninitializeKinect();
 }

 private void ReadyTimerTick(object sender, EventArgs e)
 {
 this.Start();
 this.ReportSpeechStatus("Listo para reconocer voz!");
 this.UpdateInstructionsText("Diga: 'rojo', 'verde', 'amarillo' o 'azul'");
 this.readyTimer.Stop();
 this.readyTimer = null;
 }

 private void InitializeKinect()
 {
 var sensor = this.kinect;
 this.speechRecognizer = this.CreateSpeechRecognizer();
 try
 {
 sensor.Start();
 }
 catch (Exception)
 {

 }

 if (this.speechRecognizer != null && sensor != null)
 {
 // NOTE: Need to wait 4 seconds for device to be ready to stream audio right after initialization
 this.readyTimer = new DispatcherTimer();
 this.readyTimer.Tick += this.ReadyTimerTick;
 this.readyTimer.Interval = new TimeSpan(0, 0, 4);
 this.readyTimer.Start();

 this.ReportSpeechStatus("Inicializando el dispositivo de audio Kinect...");
 this.UpdateInstructionsText(string.Empty);

 this.Closing += this.MainWindowClosing;
 }
 }

 private void UninitializeKinect()
 {
 var sensor = this.kinect;

 if (this.speechRecognizer != null && sensor != null)
 {
 sensor.AudioSource.Stop();
 sensor.Stop();
 this.speechRecognizer.RecognizeAsyncCancel();
 this.speechRecognizer.RecognizeAsyncStop();
 }

 if (this.readyTimer != null)
 {
 this.readyTimer.Stop();
 this.readyTimer = null;
 }
 }

 }
}

nota: esta entrada esta sujeta a cambios por la actualizacion de la libreria KINECT, luego les seguire comentando acerca de esto, por ahora solo les adelanto este post!…

Nuevos Tutoriales de KINECT en Español

Hola, como veran y por falta de tiempo no he podido actualizar este sitio, pero es cuestion de horas para aclarar las dudas en español en cuanto a lo que tiene y nos ofrece esta nueva SDK de KINECT en su version 1.5, claro previo estaba la 1.0 pero vayamos a lo ultimo que de todos modos cambiaron ligeros detalles en su API pero no habra problemas a la hora de entender las funciones nuevas porque en lo que respecta la forma de trabajar ahora desarrollando aplicaciones de este tipo esta siendo cada vez mas sencilla y dinamica, el resto seria solamente de creatividad por parte del o los desarrolladores de un proyecto o cualquier Aplicacion que queramos crear con esta potente Herramienta NUI

Explicar entre las nuevas capacidades el uso del reconocimiento de voz, una demo de prueba para iniciar rapidamente las 2 camaras, la de profundidad y la de RGB, uso de las librerias Skeletons para el reconocimiento de personas e interaccion con las aplicaciones!..