Face detection using Python/OpenCV on Raspberry Pi, display on ST7789 LCD using Luma.LCD.
Last exercise
ILI9488 SPI LCD on Raspberry Pi/Python using Luma.LCD display images on
3.5 inch 480x320 ILI9488 SPI LCD, run on Raspberry Pi 4B/Raspberry Pi OS 64-bit (bookworm), using Python +
PIL + Luma.LCD.
This exercise introduce using OpenCV to read
images, convert OpenCV ndarray to PIL Image, then display on
2.4 inch TFT Module 240×320 ST7789V
using Luma.LCD. Also implement face detection.
Connection between
ST7789 and Raspberry Pi, follow last exercise, same GPIO pins (for sure, the
pin order on display module hanged). Also other setup
, create Python virtual environment and install luma.lcd. Read
last exercise.
To use OpenCV (cv2) in this exercise we have to
install opencv-python in Python virtual environment:
With Python virtual environment activated, run the command:
pip install opencv-python
Exercise code:luma_st7789_cv2_image_show.py, read a single jpg image using cv2, convert OpenCV ndarray to PIL Image, display on ST7789 SPI LCD using Luma.LCD.
"""
2.4 inch 240x320 TFT with SPI ST7789
on Raspberry Pi 4B using Python/luma.lcd + OpenCV (cv2)
Show image.
"""
from luma.core.interface.serial import spi
from luma.core.render import canvas
from luma.lcd.device import st7789
from PIL import Image
import cv2
import numpy as np
serial = spi(port=0, device=0, gpio_DC=23, gpio_RST=24)
device = st7789(serial, width=320, height=240,
gpio_LIGHT=18, active_low=False) # BACKLIGHT PIN = GPIO 18, active High
device.backlight(True) # Turn on Back Light
ImagePath = "/home/pi/myImages/images/img_004.jpg"
"""
# Use PIL.Image
image = Image.open(ImagePath)
print("Open image:", ImagePath)
img_resized = image.resize((320, 240), Image.LANCZOS)
print(type(img_resized))
device.display(img_resized)
"""
# Use cv2
cv_ndarray = cv2.imread(ImagePath)
cv_ndarray_resized = cv2.resize(cv_ndarray, (320, 240))
print("cv_ndarray_resized type: ", type(cv_ndarray_resized))
#convert from numpy.ndarray to PIL Image
cv_ndarray_resized = cv_ndarray_resized.astype(np.uint8)
cv_ndarray_resized = cv_ndarray_resized[:, :, [2, 1, 0]] #convert RGB order
image_resized = Image.fromarray(cv_ndarray_resized)
print("image_resized type: ", type(image_resized))
device.display(image_resized)
haarcascade_frontalface_default.xml is needed, download from https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml, save in the working directory (same directory on the python code).
luma_st7789_cv2_facedetect_loop.py
"""
2.4 inch 240x320 TFT with SPI ST7789
on Raspberry Pi 4B using Python/luma.lcd + OpenCV (cv2)
Loop to show images, with face detection.
"""
from luma.core.interface.serial import spi
from luma.core.render import canvas
from luma.lcd.device import st7789
from PIL import Image
import cv2
import numpy as np
import os
import time
import RPi.GPIO as GPIO
serial = spi(port=0, device=0, gpio_DC=23, gpio_RST=24)
device = st7789(serial, width=320, height=240,
gpio_LIGHT=18, active_low=False) # BACKLIGHT PIN = GPIO 18, active High
device.backlight(False) # Turn OFF Back Light firstly
BACKLIGHT_PIN = 18
#GPIO.setmode(GPIO.BCM)
#GPIO.setup(BACKLIGHT_PIN, GPIO.OUT)
pwm = GPIO.PWM(BACKLIGHT_PIN, 1000)
pwm.start(0)
def fade_in():
for duty_cycle in range(0, 101, 1):
pwm.ChangeDutyCycle(duty_cycle)
time.sleep(0.01)
def fade_out():
for duty_cycle in range(100, -1, -1):
pwm.ChangeDutyCycle(duty_cycle)
time.sleep(0.01)
def show_cv_image_facedetect(imgSrc):
print(imgSrc)
cv_ndarray = cv2.imread(imgSrc)
# face detect
# ref:
# https://opencv-tutorial.readthedocs.io/en/latest/face/face.html
gray = cv2.cvtColor(cv_ndarray, cv2.COLOR_BGR2GRAY)
path = 'haarcascade_frontalface_default.xml'
face_detector = cv2.CascadeClassifier(path)
face_rects = face_detector.detectMultiScale(gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30),
flags = cv2.CASCADE_SCALE_IMAGE)
print(f'found {len(face_rects)} face(s)')
for rect in face_rects:
cv2.rectangle(cv_ndarray, rect, (255, 255, 255), 2)
# end of face detect
# resize to 320x240
cv_ndarray_resized = cv2.resize(cv_ndarray, (320, 240))
#convert from numpy.ndarray to PIL Image
cv_ndarray_resized = cv_ndarray_resized.astype(np.uint8)
cv_ndarray_resized = cv_ndarray_resized[:, :, [2, 1, 0]] #convert RGB order
image_resized = Image.fromarray(cv_ndarray_resized)
device.display(image_resized)
images_folder = "/home/pi/myImages/images"
files = os.listdir(images_folder)
jpg_files = [file for file in files if file.endswith('.jpg')]
jpg_file_list = sorted(jpg_files)
print("=== Start ===")
print("# of file:", len(jpg_file_list))
while True:
for i in range(0, len(jpg_file_list)):
ImagePath = os.path.join(images_folder, jpg_file_list[i])
show_cv_image_facedetect(ImagePath)
fade_in()
time.sleep(3)
fade_out()
luma_s7789.py
"""
2.4 inch 240x320 TFT with SPI ST7789
on Raspberry Pi 4B using Python/luma.lcd
Hello World with color/pwm backlight test.
"""
from luma.core.interface.serial import spi
from luma.core.render import canvas
from luma.lcd.device import st7789
from PIL import ImageFont
import time
serial = spi(port=0, device=0, gpio_DC=23, gpio_RST=24)
device = st7789(serial, width=320, height=240, rotate=0)
font_FreeMonoBold_30 = ImageFont.truetype("/usr/share/fonts/truetype/freefont/FreeMonoBold.ttf", 30)
font_FreeSansBold_20 = ImageFont.truetype("/usr/share/fonts/truetype/freefont/FreeSansBold.ttf", 20)
font_FreeSerifBoldItalic_30 = ImageFont.truetype("/usr/share/fonts/truetype/freefont/FreeSerifBoldItalic.ttf", 30)
device.backlight(False) # Turn on backlight using luma device.backlight()
with canvas(device) as draw:
print(device.bounding_box)
draw.rectangle(device.bounding_box, outline="white", fill="black")
draw.text((30, 40), "Hello World", font=font_FreeSerifBoldItalic_30, fill="white")
time.sleep(3)
with canvas(device) as draw:
draw.rectangle(device.bounding_box, outline="white", fill="red")
draw.text((30, 40), "red", font=font_FreeMonoBold_30, fill="white")
time.sleep(3)
with canvas(device) as draw:
draw.rectangle(device.bounding_box, outline="white", fill="green")
draw.text((30, 40), "green", font=font_FreeMonoBold_30, fill="white")
time.sleep(3)
with canvas(device) as draw:
draw.rectangle(device.bounding_box, outline="white", fill="blue")
draw.text((30, 40), "blue", font=font_FreeMonoBold_30, fill="white")
time.sleep(3)
with canvas(device) as draw:
draw.rectangle(device.bounding_box, outline="white", fill="black")
draw.text((10, 40), "Test backlight using GPIO.PWM", font=font_FreeMonoBold_30, fill="white")
#=== Test control BACKLIGHT_PIN using GPIO.PWM ===
import RPi.GPIO as GPIO
BACKLIGHT_PIN = 18
#GPIO.setmode(GPIO.BCM)
#GPIO.setup(BACKLIGHT_PIN, GPIO.OUT)
pwm = GPIO.PWM(BACKLIGHT_PIN, 1000)
pwm.start(0)
def fade_in():
for duty_cycle in range(0, 101, 1):
pwm.ChangeDutyCycle(duty_cycle)
time.sleep(0.01)
def fade_out():
for duty_cycle in range(100, -1, -1):
pwm.ChangeDutyCycle(duty_cycle)
time.sleep(0.01)
while True:
fade_in()
time.sleep(1)
fade_out()
time.sleep(1)
pwm.stop()
GPIO.cleanup()
luma_st7789_image_show.py
"""
2.4 inch 240x320 TFT with SPI ST7789
on Raspberry Pi 4B using Python/luma.lcd
Show image.
"""
from luma.core.interface.serial import spi
from luma.core.render import canvas
from luma.lcd.device import st7789
from PIL import Image, ImageOps
serial = spi(port=0, device=0, gpio_DC=23, gpio_RST=24)
device = st7789(serial, width=320, height=240,
gpio_LIGHT=18, active_low=False) # BACKLIGHT PIN = GPIO 18, active High
device.backlight(True) # Turn on Back Light
ImagePath = "/home/pi/myImages/images/img_008.jpg"
image = Image.open(ImagePath)
print("Open image:", ImagePath)
img_resized = image.resize((320, 240), Image.LANCZOS)
print(type(img_resized))
device.display(img_resized)
luma_st7789_image_slideshow.py
"""
2.4 inch 240x320 TFT with SPI ST7789
on Raspberry Pi 4B using Python/luma.lcd
Show images in Slideshow.
"""
from luma.core.interface.serial import spi
from luma.core.render import canvas
from luma.lcd.device import st7789
from PIL import Image, ImageOps
import os
import time
serial = spi(port=0, device=0, gpio_DC=23, gpio_RST=24)
device = st7789(serial, width=320, height=240,
gpio_LIGHT=18, active_low=False) # BACKLIGHT PIN = GPIO 18, active High
device.backlight(True) # Turn on Back Light
# Convert image source of 1024x768
# to 320x240 to match LCD display.
def showImage(image_source):
image = Image.open(image_source)
print("Open image:", image_source)
img_resized = image.resize((320, 240), Image.LANCZOS)
device.display(img_resized)
images_folder = "/home/pi/myImages/images"
files = os.listdir(images_folder)
jpg_files = [file for file in files if file.endswith('.jpg')]
jpg_file_list = sorted(jpg_files)
print("=== Start ===")
print("# of file:", len(jpg_file_list))
while True:
for i in range(0, len(jpg_file_list)):
ImagePath = os.path.join(images_folder, jpg_file_list[i])
showImage(ImagePath)
time.sleep(3)
luma_st7789_image_slideshow_fade.py
"""
2.4 inch 240x320 TFT with SPI ST7789
on Raspberry Pi 4B using Python/luma.lcd
Show images in Slideshow,
"""
from luma.core.interface.serial import spi
from luma.core.render import canvas
from luma.lcd.device import st7789
from PIL import Image, ImageOps
import os
import time
import RPi.GPIO as GPIO
serial = spi(port=0, device=0, gpio_DC=23, gpio_RST=24)
device = st7789(serial, width=320, height=240,
gpio_LIGHT=18, active_low=False) # BACKLIGHT PIN = GPIO 18, active High
device.backlight(False) # Turn OFF Back Light firstly
BACKLIGHT_PIN = 18
#GPIO.setmode(GPIO.BCM)
#GPIO.setup(BACKLIGHT_PIN, GPIO.OUT)
pwm = GPIO.PWM(BACKLIGHT_PIN, 1000)
pwm.start(0)
def fade_in():
for duty_cycle in range(0, 101, 1):
pwm.ChangeDutyCycle(duty_cycle)
time.sleep(0.01)
def fade_out():
for duty_cycle in range(100, -1, -1):
pwm.ChangeDutyCycle(duty_cycle)
time.sleep(0.01)
# Convert image source of 1024x768
# to 320x240 to match LCD display.
def showImage(image_source):
image = Image.open(image_source)
print("Open image:", image_source)
img_resized = image.resize((320, 240), Image.LANCZOS)
time_begin = time.time()
device.display(img_resized)
time_end = time.time()
print("Duration to display:", str(time_end-time_begin))
images_folder = "/home/pi/myImages/images"
files = os.listdir(images_folder)
jpg_files = [file for file in files if file.endswith('.jpg')]
jpg_file_list = sorted(jpg_files)
print("=== Start ===")
print("# of file:", len(jpg_file_list))
while True:
for i in range(0, len(jpg_file_list)):
ImagePath = os.path.join(images_folder, jpg_file_list[i])
showImage(ImagePath)
fade_in()
time.sleep(3)
fade_out()
Comments
Post a Comment