# Bienvenue

Bienvenue sur mon GitBook !

Je partage ici des informations et ressources que je trouve difficiles d'accès ou insuffisamment expliquées sur internet quand elles ne sont pas carrément inexistantes,

Si quelque chose n'est pas clair et que tu as des questions, ou que tu remarques une erreur, n'hésite pas à me contacter via l'un des canaux disponibles sur [mon site](https://www.jonathan-about.com/), ceci contribuera à améliorer le contenu pour tous,

Bonne visite et à bientôt !


# \[OCR] Détection et extraction de texte d'une image à l'aide de Tesseract OCR et OpenCV

On installe Tesseract OCR :

```bash
sudo apt install tesseract-ocr
sudo apt install libtesseract-dev
```

On installe les bibliothèques **Python OpenCV** et **Python Tesseract** :

```bash
pip install opencv-python pytesseract
```

***

```python
# On importe les bibliothèques Python
import numpy as np
import cv2
import pytesseract

# On charge l'image
img = cv2.imread("image.jpg")

# On convertit l'image en niveaux de gris
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# On applique un seuillage automatique à l'image en niveaux de gris afin de séparer le texte du fond, on récupère respectivement la valeur optimale du seuil et l'image.
ret, thresh = cv2.threshold(gray_img, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY_INV)

# On analyse la résolution et la densité de texte de l'image afin de déterminer la taille du noyau

# - On récupère les dimensions de l'image
img_height, img_width = img.shape[:2]

# - On détecte le nombre total d'objets trouvés dans l'image (arrière-plan compris), à quel objet appartient chaque pixel, les dimensions et positions de chaque objet, et les centres de chaque objet
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh)

# - On filtre les objets trop petits en excluant l'arrière-plan (qui est toujours à l'index 0)
characters_stats = [stat for stat in stats[1:] if stat[4] > 10]

if not characters_stats:
    return None

# - On calcule la largeur et la hauteur moyenne des caractères
mean_character_width = np.mean([stat[2] for stat in characters_stats])
mean_character_height = np.mean([stat[3] for stat in characters_stats])

# - On estime l'espacement moyen entre les caractères
mean_area = np.mean([stat[4] for stat in characters_stats])

# - On calcule la densité de texte
density = len(characters_stats) * mean_area / (img_height * img_width)

# - On ajuste la taille du noyau en fonction de la taille moyenne des caractères et de la densité de texte
kernel_width = int(mean_character_width * 3.5 * (1 - 0.5 * density))
kernel_height = int(mean_character_height * 2.5 * (1 - 0.5 * density))

# - On assure une taille minimale du noyau et un nombre impair (meilleur pour les opérations morphologiques)
kernel_width = max(3, kernel_width if kernel_width % 2 == 1 else kernel_width + 1)
kernel_height = max(3, kernel_height if kernel_height % 2 == 1 else kernel_height + 1)

# - On crée un noyau rectangulaire qui sera utilisé pour la dilatation de l'image seuillée
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernel_width, kernel_height))

# On dilate les zones blanches de l'image seuillée afin de grouper les caractères par zone de texte
dilated_img = cv2.dilate(thresh, kernel, iterations = 1)

# On détermine les countours des zones de texte et leurs hiérarchies (relations parent-enfant)
contours, hierarchy = cv2.findContours(dilated_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# On parcourt les zones de texte selon leurs contours
for contour in contours:
    # On récupère les coordonnées du contour
    x, y, w, h = cv2.boundingRect(contour)

    # On récupère la zone de l'image correspondant au contour
    cropped = img[y:y + h, x:x + w]

    # On applique la reconnaissance optique de caractères (OCR) à la zone de texte
    text = pytesseract.image_to_string(cropped)

    # On affiche le texte
    print(text)
```


# Windows Subsystem for Linux


# Accéder à un port de sa distribution WSL 2 depuis le réseau local

{% hint style="info" %}
WSL 2 dispose de son propre réseau, les distributions sont donc uniquement disponibles depuis la machine hôte par défaut, afin qu'elles le soient également depuis d'autres machines du réseau local il faut configurer un proxy de port.
{% endhint %}

On ouvre Windows PowerShell en mode administrateur.

On récupère l'IP de la distribution à laquelle on souhaite se connecter :

```powershell
wsl -d <NOM DE LA DISTRIBUTION> hostname -I
```

On configure un proxy de port :

```powershell
netsh interface portproxy add v4tov4 listenport=<PORT D'ÉCOUTE> listenaddress=0.0.0.0 connectport=<PORT DE CONNEXION À LA DISTRIBUTION> connectaddress=<IP DE LA DISTRIBUTION>
```

On rajoute dans le firewall utilisé par Windows une règle afin d'ouvrir le trafic entrant sur le port d'écoute choisi.

***

## Commandes utiles

Lister les proxys de ports existants :

```powershell
netsh interface portproxy show all
```

Supprimer un proxy de port :

```powershell
netsh interface portproxy delete v4tov4 listenport=<PORT D'ÉCOUTE> listenaddress=0.0.0.0
```

Supprimer tous les proxys de ports existants :

```powershell
netsh interface portproxy reset
```


# Attacher un périphérique USB aux distributions installées sur WSL 2

On ouvre l'**Invite de commandes** tant qu'administrateur et l'on installe **usbipd** :

```batch
winget install usbipd
```

On le ferme et on l'ouvre de nouveau en tant qu'administrateur puis on répertorie tous les appareils USB connectés à Windows, on sélectionne et copie le BUSID l'appareil que l'on souhaite attacher :

```batch
usbipd list
```

On partage l'appareil USB :

```batch
usbipd bind --busid <BUSID>
```

On attache l'appareil USB à nos distributions :

```batch
usbipd attach --wsl --busid <BUSID>
```

Quan on a terminé d'utiliser le périphérique USB dans WSL, on peut le déconnecter physiquement ou exécuter cette commande à partir de l'**Invite de commande** :

```batch
usbipd detach --busid <BUSID>
```


# Utiliser une webcam sur une distribution installée sur WSL 2

## Utiliser une webcam USB

On attache notre webcam USB aux distributions WSL 2 :

{% content-ref url="/pages/AE0V3SBnILPmFEAPxRKQ" %}
[Attacher un périphérique USB aux distributions installées sur WSL 2](/windows/windows-subsystem-for-linux/attacher-un-peripherique-usb-aux-distributions-installees-sur-wsl-2)
{% endcontent-ref %}

On ajoute notre utiliser au groupe **video** :

```bash
sudo usermod -aG video $USER
```

On ferme notre session WSL, on la réouvre, et on devrait pouvoir accéder à notre webcam.

## Utiliser une webcam intégrée

On ouvre l'**Invite de commandes** en tant qu'admnistrateur et l'on installe **ffmpeg** :

```batch
winget install ffmpeg
```

On le ferme et on l'ouvre de nouveau en tant qu'administrateur puis on liste les caméras disponibles :

```batch
ffmpeg -list_devices true -f dshow -i dummy
```

On récupère l'IP de la ligne terminant par eth0 sur notre distribution WSL 2 :

```bash
ip addr | grep inet
```

On capture et diffuse en streaming UDP notre caméra depuis l'**Invite de commandes Windows** :

```batch
ffmpeg -f dshow -i video="<NOM DE LA CAMÉRA>" -c:v libx264 -f mpegts udp://<IP DE LA DISTRIBUTION>:11795?pkt_size=1024
```

On peut lire notre flux à l'adresse `udp://@:11795`.

### Problèmes éventuels

Si l'on souhaite accéder au flux depuis un script Python, il pourrait être nécessaire d'installer les bibliothèques suivantes :

```bash
sudo apt install -y \
  libgl1-mesa-dri \
  libgl1-mesa-glx \
  libqt5core5a \
  libqt5gui5 \
  libqt5widgets5 \
  libqt5x11extras5 \
  libsm6 \
  libx11-6 \
  libx11-xcb-dev \
  libxext-dev \
  libxext6 \
  libxkbcommon-x11-0 \
  libxrender-dev \
  libxrender1 \
  libxcb-cursor0 \
  libxcb-icccm4 \
  libxcb-image0 \
  libxcb-keysyms1 \
  libxcb-randr0 \
  libxcb-render-util0 \
  libxcb-util1 \
  libxcb-xfixes0 \
  libxcb-xinerama0 \
  libxcb-xinerama0-dev \
  libxcb1
```


