#Windows10 – Can’t remove a device ? Let’s try with “Show hidden devices”

Buy Me A Coffee

Hi !

Saturday off-topic post.

I’ve been a Windows user for a long time, and I consider myself smart enough to solve the most common issues. However, while I was installing a new Bluetooth 5.0 dongle in my brand new Windows 10 installation, I face an error:

I could not uninstall some devices. These devices where paired to my Windows 10 machine using an older Bluetooth 4.0 dongle.

And, even weirder, when I try to remove the device from the Control Panel, I got a cryptic message:

Can’t remove device.

No extra details, no details in the Event Viewer; just that simple message.

I was afraid that I will need to manually clean up entries in the Windows Registry, until I read that the non-used devices can also be accessed in the Device Manager. Just following these steps:

Press Windows key + X. and open Device Manager

device manager

Click on View // Hidden Devices.

show hidden devices

Search for desired device and click uninstall

uninstall a hidden device

And, that’s it ! 5 minutes later, I finally have all my devices connected using Bluetooth 5.0 and up and running in Windows 10 !

Windows 10 installed devices

Happy coding!

Greetings

El Bruno

#Coding4Fun – Sorting Arrays in #JavaScript, #Python and #CSharp … choose your own adventure

Buy Me A Coffee

Hi !

Not my usual set of posts, however this keep me thinking a lot. It all started with this tweet; an usual joke about JavaScript, and how it works with types.

array sorting in Javascript

I noticed that some responses focused on the “you need to know how the language works” before posting this. And it is correct, you need to know how JavaScript converts the elements into strings and then sort, to understand the crappy not so accurate output.

However, I am not a JavaScript expert, and I do not want to be one. And, when I use a tool or a programming language, I expect to have a nice learning curve; the previous example is not a nice “Welcome to JavaScript, where arrays and type conversions will make you think twice until you get it!”.

I’ve been doing a lot of Python programming, so I did the same exercise, and it worked as you may expect !

array and sort in python

I also did a similar in C#, and it also worked !

array and sort in C#

Do not get me wrong, this is not an Anti-JavaScript post. JavaScript is awesome and is almost everywhere. I know a lot of awesome JavaScript programmers, who I really admire.

However as a developer, I expect to avoid something simple like an array sort issue. I will always focus on “the code is clean and everyone will understand how it works, just read the code!”.

I am used to this as a C# developer; and I also found that Python is cool for this. But, sometimes, just sometimes, JavaScript looks like hell !

Bonus: An old post in my last JavaScript adventure.

Happy coding!

Greetings

El Bruno

#MLNet – AutoML for ranking scenarios

Buy Me A Coffee

Hi !

This is a cool one, Machine Learning .Net (ML.Net) now support ranking scenario in AutoML. As an Machine Learning aficionado, this is amazing. I can now process my problems with AutoML, and then learn the specifics of the best produced models.

Note: a couple of weeks ago, someone asked a question around ranking scenarios. My knowledge is low here, so I kindly shared a couple of starting points. With AutoML now supporting ranking scenarios, the response is completely different!

So I picked up the sample for the current version (1.5.1), the sample for standard ranking scenarios from ML.Net and a data source based on a public datasets provided by Microsoft originally provided Microsoft Bing (see references); and I created this sample

using System;
using System.Linq;
using System.Net.Http.Headers;
using Microsoft.ML;
using Microsoft.ML.AutoML;
using Microsoft.ML.Data;
namespace ConsoleApp1
{
public class Program
{
static void Main(string[] args)
{
Console.WriteLine("Start …");
Run();
Console.WriteLine("End");
}
private static string TrainDataPath = @"data\train.txt";
private static string TestDataPath = @"data\test.txt";
private static string ModelPath = @"Model.zip";
private static string LabelColumnName = "Label";
private static string GroupColumnName = "GroupId";
private static uint ExperimentTime = 600;
public static void Run()
{
var mlContext = new MLContext();
// STEP 1: Load data
var trainDataView = mlContext.Data.LoadFromTextFile<SearchData>(TrainDataPath, hasHeader: false, separatorChar: '\t');
var testDataView = mlContext.Data.LoadFromTextFile<SearchData>(TestDataPath, hasHeader: false, separatorChar: '\t');
// STEP 2: Run AutoML experiment
Console.WriteLine($"Running AutoML recommendation experiment for {ExperimentTime} seconds…");
var experimentResult = mlContext.Auto()
.CreateRankingExperiment(new RankingExperimentSettings() { MaxExperimentTimeInSeconds = ExperimentTime })
.Execute(trainDataView, testDataView,
new ColumnInformation()
{
LabelColumnName = LabelColumnName,
GroupIdColumnName = GroupColumnName
});
// STEP 3: Print metric from best model
var bestRun = experimentResult.BestRun;
Console.WriteLine($"=====================================================");
Console.WriteLine($"Total models produced: {experimentResult.RunDetails.Count()}");
var i = 0;
foreach (var experimentResultRunDetail in experimentResult.RunDetails)
{
i++;
Console.WriteLine($" {i} – TrainerName: {experimentResultRunDetail.TrainerName}");
Console.WriteLine($" Runtime In Seconds: {experimentResultRunDetail.RuntimeInSeconds}");
Console.WriteLine($"");
//PrintMetrics(experimentResultRunDetail.ValidationMetrics);
}
Console.WriteLine($"");
Console.WriteLine($"=====================================================");
Console.WriteLine($"Best model's trainer: {bestRun.TrainerName}");
// STEP 5: Evaluate test data
var testDataViewWithBestScore = bestRun.Model.Transform(testDataView);
var testMetrics = mlContext.Ranking.Evaluate(testDataViewWithBestScore, labelColumnName: LabelColumnName);
Console.WriteLine($"Metrics of best model on test data —");
PrintMetrics(testMetrics);
// STEP 6: Save the best model for later deployment and inferencing
mlContext.Model.Save(bestRun.Model, trainDataView.Schema, ModelPath);
// STEP 7: Create prediction engine from the best trained model
var predictionEngine = mlContext.Model.CreatePredictionEngine<SearchData, SearchDataPrediction>(bestRun.Model);
// STEP 8: Initialize a new test, and get the prediction
var testPage = new SearchData
{
GroupId = "1",
Features = 9,
Label = 1
};
var prediction = predictionEngine.Predict(testPage);
Console.WriteLine($"Predicted rating for: {prediction.Prediction}");
// New Page
testPage = new SearchData
{
GroupId = "2",
Features = 2,
Label = 9
};
prediction = predictionEngine.Predict(testPage);
Console.WriteLine($"Predicted: {prediction.Prediction}");
Console.WriteLine("Press any key to continue…");
Console.ReadKey();
}
private static void PrintMetrics(RankingMetrics metrics)
{
if (metrics is null)
{
Console.WriteLine($" No metrics");
return;
}
var ndcg = metrics.NormalizedDiscountedCumulativeGains.Aggregate("", (current, p) => current + p + "");
var dcg = metrics.DiscountedCumulativeGains.Aggregate("", (current, p) => current + p + "");
Console.WriteLine($" Normalized Discounted Cumulative Gains: {ndcg}");
Console.WriteLine($" Discounted Cumulative Gains: {dcg}");
}
}
class SearchData
{
[LoadColumn(0)]
public string GroupId;
[LoadColumn(1)]
public float Features;
[LoadColumn(2)]
public float Label;
}
class SearchDataPrediction
{
[ColumnName("PredictedLabel")]
public float Prediction;
public float Score { get; set; }
}
}

The sample run for 10 minutes and evaluates 33 models.

The test file is 266MB and the train data file is 799 MBs.

At the end, the best trainer is [FastTreeRanking].

The output is also very clear about the tested models and the best one. (I trimmed this to make it clearer).

Start ...
Running AutoML recommendation experiment for 600 seconds...
=====================================================
Total models produced: 33
  1 - TrainerName: LightGbmRanking
      Runtime In Seconds: 10.6167636

  2 - TrainerName: FastTreeRanking
      Runtime In Seconds: 11.1055165

  3 - TrainerName: FastTreeRanking
      Runtime In Seconds: 35.0196598

  4 - TrainerName: FastTreeRanking
      Runtime In Seconds: 6.0401781
  ...
=====================================================
Best model's trainer: FastTreeRanking

Press any key to continue...

Super cool feature !

Happy coding!

Greetings

El Bruno

References

#Podcast – NTN 62 – Especial Verano sobre WebAssembly y Blazor. Bonus: Herramientas para la Gestión de Proyectos

Buy Me A Coffee

Buenas!

Hoy tenemos la suerte de hablar con Miguel Teheran, sobre WebAssembly y Blazor. Ambos coincidimos que es una plataforma que crecerá mucho en el futuro cercano, así que decidimos hacer una introducción rápida a la misma. Si eres un programador C#, esto seguro que es de tu interés!

Además, hay una sección especial dedicada a la Gestión de Proyectos, en la que repasamos las diferentes herramientas que tenemos en el mundo Microsoft, como por ejemplo, Planner, Project, Project Online, y mucho más!

Speakers

  • Miguel Teheran, Developer and Software Consultant (LinkedIn)
  • Bruno Capuano es Canada Innovation Lead at Avanade and Microsoft AI MVP (LinkedIn)

Happy coding!

Greetings

El Bruno

#Anaconda – How to List and Remove Virtual Environments (get back some disk space!)

Buy Me A Coffee

Hi !

I already shared how to create Virtual Environments using Anaconda, and also how to create shortcuts to use them directly in Windows Terminal (see references). This task is easy an amazing, however, at some point you may want to clean your environment.

That’s an easy task. I’m currently using Anaconda version 4.8.3. You can check your version with the command

conda -V

To show your virtual environments, you must use the command

conda info --envs
anaconda display version and virtual environments
Anaconda PowerShell display conda version and virtual environments

Before deleting any of this, I checked them and … they use some space.

anaconda virtual environments disk size

As you can see in the previous image

  • drone02, disk size is 2GB
  • p38, disk size is 1.4 GB
  • telloOpenCV, disk size is 2.6 GB
  • tfenv, disk size is 1.76 GB

I didn’t even check the other virtual environments. Right now I’m only using 2 from the total of 6 on the list, so I’ll delete the non used ones.

To delete a virtual environment we must use the command

conda env remove --name ENVIRONMENT

And with a simple command like this, I can remove the unused ones

conda env remove --name drone02
conda env remove --name telloOpenCV
conda env remove --name tfenv

And, after this I get some space back to my disk!

Happy coding!

Greetings

El Bruno

References

#Python – Context Meny and Key Press with #PySimpleGUI

Buy Me A Coffee

Hi !

After my base sample code for a GUI app, now it’s time to add some interaction features:

  • Context Menu
  • Capture Key Press

In the following example, I’m adding a context menu with the following elements:

python pysimplegui context menu

This can be done as part of the window definition, in example

right_click_menu = ['Unused', ['&FPS', '---', 'Menu A', 'Menu B', 'Menu C', ['Menu C1', 'Menu C2'], '---', 'Exit']]

window    = sg.Window("El Bruno - Webcams and GrayScale with PySimpleGUI", layout, 
                    right_click_menu=right_click_menu,
                    no_titlebar=False, alpha_channel=1, grab_anywhere=False, 
                    return_keyboard_events=True, location=(100, 100))      

The menu definition and how to create submenus, separators, quick access keys and more are part of the PySimpleGUI documentation.

And then, in order to capture events in the window, we need to check the events read in each loop of the while. The following sample, check the window events

  • Close the Window is the user press the [X] to close the window, or click the [Exit] element on the context menu
  • Change the value of a boolean var if the user press the key [F] , or click the [FPS] element on the context menu
    # process windows events
    event, values = window.read(timeout=20)
    if event == sg.WIN_CLOSED or event == "Exit":
        break
    if event == "f" or event == "F" or event == "FPS":
        display_fps = not display_fps

The full code:

# Bruno Capuano 2020
# display the camera feed using OpenCV
# display FPS
import time
import cv2
import PySimpleGUI as sg
# init Windows Manager
sg.theme("DarkBlue")
# def webcam col
colwebcam1_layout = [[sg.Text("Camera View", size=(60, 1), justification="center")],
[sg.Image(filename="", key="cam1")]]
colwebcam1 = sg.Column(colwebcam1_layout, element_justification='center')
colwebcam2_layout = [[sg.Text("Camera View GrayScale", size=(60, 1), justification="center")],
[sg.Image(filename="", key="cam1gray")]]
colwebcam2 = sg.Column(colwebcam2_layout, element_justification='center')
colslayout = [colwebcam1, colwebcam2]
rowfooter = [sg.Image(filename="avabottom.png", key="-IMAGEBOTTOM-")]
layout = [colslayout, rowfooter]
right_click_menu = ['Unused', ['&FPS', '—', 'Menu A', 'Menu B', 'Menu C', ['Menu C1', 'Menu C2'], '—', 'Exit']]
window = sg.Window("El Bruno – Webcams and GrayScale with PySimpleGUI", layout,
right_click_menu=right_click_menu,
no_titlebar=False, alpha_channel=1, grab_anywhere=False,
return_keyboard_events=True, location=(100, 100))
# Camera Settings
camera_Width = 480 # 640 # 1024 # 1280
camera_Heigth = 320 # 480 # 780 # 960
frameSize = (camera_Width, camera_Heigth)
video_capture = cv2.VideoCapture(0)
time.sleep(2.0)
display_fps = False
while True:
start_time = time.time()
# process windows events
event, values = window.read(timeout=20)
if event == sg.WIN_CLOSED or event == "Exit":
break
if event == "f" or event == "F" or event == "FPS":
display_fps = not display_fps
# get camera frame
ret, frameOrig = video_capture.read()
frame = cv2.resize(frameOrig, frameSize)
if (display_fps == True) and (time.time() start_time ) > 0:
fpsInfo = "FPS: " + str(1.0 / (time.time() start_time)) # FPS = 1 / time to process loop
font = cv2.FONT_HERSHEY_DUPLEX
cv2.putText(frame, fpsInfo, (10, 20), font, 0.4, (255, 255, 255), 1)
# update webcam1
imgbytes = cv2.imencode(".png", frame)[1].tobytes()
window["cam1"].update(data=imgbytes)
# transform frame to grayscale
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# update webcam2
imgbytes = cv2.imencode(".png", gray)[1].tobytes()
window["cam1gray"].update(data=imgbytes)
video_capture.release()
cv2.destroyAllWindows()

Happy coding!

Greetings

El Bruno

Resources

#Python – Creating GUIs with #PySimpleGUI. 2 webcams view with 50 lines of code

Buy Me A Coffee

Hi !

Working with Computer Vision is super fun. And there are some scenarios where display the step by step of the processing of an image is the best way to present this.

In most of my scenarios I use OpenCV, however for a more detailed presentation I needed to search and learn a GUI framework in Python. That’s how I get to PySimpleGUI (see references).

Note: As a long time C# dev, I’m missing XAML a lot !

PySimpleGUI is very simple (as you can expect!), and with a few lines of code we can create an UI like this one:

Let’s display the camera feed and a gray scale view of the camera feed

2 cameras in python, using PySimpleGUI to create a windows to display this

Super easy !

Let’s take a look at the code

  • Lines 16-34. This is the main window definition. The Window have 2 rows.
    • 1st row have 2 columns with the 2 cameras, each camera have their own element key
    • 2nd row have an image to display a bottom
  • Line 30. This is the final merge of the 2 rows
  • Lines 32-34. This is the window definition. We can define title, transparency, etc.
  • Lines 37-40. Window Event management, I’ll write more about this for sure. Right now, I’m only checking for window close to exit the loop.
  • Lines 51-53. Transform the camera frame to a byte array, based on the PNG format and assign the array to the 1st camera viewer.
  • Lines 55-60. Transform the camera frame to Gray Scale frame. Then transform the gray scale frame to a byte array, based on the PNG format and assign the array to the 2nd camera viewer.

Done !

# Bruno Capuano 2020
# display the camera feed using OpenCV
# display the camera feed with grayscale using OpenCV
import time
import cv2
import PySimpleGUI as sg
# Camera Settings
camera_Width = 320 # 480 # 640 # 1024 # 1280
camera_Heigth = 240 # 320 # 480 # 780 # 960
frameSize = (camera_Width, camera_Heigth)
video_capture = cv2.VideoCapture(0)
time.sleep(2.0)
# init Windows Manager
sg.theme("DarkBlue")
# def webcam col
colwebcam1_layout = [[sg.Text("Camera View", size=(60, 1), justification="center")],
[sg.Image(filename="", key="cam1")]]
colwebcam1 = sg.Column(colwebcam1_layout, element_justification='center')
colwebcam2_layout = [[sg.Text("Camera View GrayScale", size=(60, 1), justification="center")],
[sg.Image(filename="", key="cam1gray")]]
colwebcam2 = sg.Column(colwebcam2_layout, element_justification='center')
colslayout = [colwebcam1, colwebcam2]
rowfooter = [sg.Image(filename="avabottom.png", key="-IMAGEBOTTOM-")]
layout = [colslayout, rowfooter]
window = sg.Window("El Bruno – Webcams and GrayScale with PySimpleGUI", layout,
no_titlebar=False, alpha_channel=1, grab_anywhere=False,
return_keyboard_events=True, location=(100, 100))
while True:
start_time = time.time()
event, values = window.read(timeout=20)
if event == sg.WIN_CLOSED:
break
# get camera frame
ret, frameOrig = video_capture.read()
frame = cv2.resize(frameOrig, frameSize)
# if (time.time() – start_time ) > 0:
# fpsInfo = "FPS: " + str(1.0 / (time.time() – start_time)) # FPS = 1 / time to process loop
# font = cv2.FONT_HERSHEY_DUPLEX
# cv2.putText(frame, fpsInfo, (10, 20), font, 0.4, (255, 255, 255), 1)
# # update webcam1
imgbytes = cv2.imencode(".png", frame)[1].tobytes()
window["cam1"].update(data=imgbytes)
# # transform frame to grayscale
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# # update webcam2
imgbytes = cv2.imencode(".png", gray)[1].tobytes()
window["cam1gray"].update(data=imgbytes)
video_capture.release()
cv2.destroyAllWindows()

Happy coding!

Greetings

El Bruno

Resources

#Podcast – NTN 61 – Todo lo que pasa cuando haces tap con una tarjeta electrónica: millones de transacciones, programacion de bajo nivel, hardware mucho hardware, seguridad en menos de un segundo y mucho más!

Buy Me A Coffee

Buenas!

Hoy tenemos la suerte de hablar con Ariel Perassi, Germán Pagliaroli y Juan Quijano sobre todo lo que pasa en ese segundo mágico que hay cuando haces Tap con una tarjeta electrónica. Empezamos con el hardware de bajo nivel que existe para soportar esto y la novedosa solución que han implementado para soportar diversos dispositivos. Este proceso les ha permitido cubrir +40 ciudades, +80 millones de transacciones diarias que cubren desde viajes en tren, autobuses o botes, y mucho más.

Por cierto, este proceso son más de 10 años de experiencia trabajando con tarjetas de pago; han levantado el nivel de negocio y técnico de la conversación hasta un punto impresionante !!

Speakers

  • Ariel Perassi es Sub Gerente de Producto SUBE en Nación Servicios (LinkedIn)
  • Germán Pagliaroli es Jefe Arquitectura de Software SUBE en Nación Servicios (LinkedIn)
  • Juan Carlos Quijano Abad es Microsoft Certified Trainer, Arquitecto de Soluciones en Azure, Consultor independiente en implantación de DevOps (LinkedIn)
  • Bruno Capuano es Canada Innovation Lead at Avanade and Microsoft AI MVP (LinkedIn)

Happy coding!

Greetings

El Bruno