In the world of computer vision and IoT, compact devices like the Arduino Nicla Vision are proving that big things can come in small packages. With its powerful onboard camera and AI capabilities, the Nicla Vision is ideal for edge computing tasks—like scanning and interpreting QR codes in real time.
But what if you need more than just reading the code? What if your application depends on knowing how the QR code position and orientation?
In this page, we'll explore how to detect the position and orientation of a QR code using the Arduino Nicla Vision. Whether you're building an automated sorting system, a smart scanner, or simply want to add a layer of intelligence to your QR-based project, understanding orientation can be the key to more dynamic and reliable interactions.
This script demonstrates how to use the Arduino Nicla Vision to detect QR codes using its built-in camera and visualize their orientation based on the corner coordinates. The script also includes optional IMU and ToF sensor integrations. Here is the Python source code used in the video:
import pyb # Import module for board related functions
import sensor # Import the module for sensor related functions
import image # Import module containing machine vision algorithms
import imu
from vl53l1x import VL53L1X
from machine import Pin, I2C
redLED = pyb.LED(1) # built-in red LED
blueLED = pyb.LED(3) # built-in blue LED
sensor.reset() # Initialize the camera sensor.
#sensor.set_pixformat(sensor.GRAYSCALE) # Sets the sensor to RGB
sensor.set_pixformat(sensor.RGB565) # Sets the sensor to RGB
sensor.set_framesize(sensor.QVGA) # Sets the resolution to 320x240 px
#sensor.set_framesize(sensor.VGA) # Sets the resolution to 480x320 px
#sensor.set_framesize(sensor.VGA) # Sets the resolution to 640x480 px
#sensor.set_framesize(sensor.XGA) # Sets the resolution to 640x480 px
#sensor.set_hflip(True) # Flips the image vertically
#sensor.set_hmirror(True) # Mirrors the image horizontally
redLED.on()
sensor.skip_frames(time = 100) # Skip some frames to let the image stabilize
redLED.off()
blueLED.on()
#tof = VL53L1X(I2C(2))
while(True):
#distance = tof.read()
#print(f"Distance: {distance}mm")
#imu_pitch = imu.pitch()
#imu_roll = imu.roll()
#temperature = imu.temperature_c()
img = sensor.snapshot()
#img.to_grayscale()
#print (distance, imu_pitch, imu_roll, temperature)
for code in img.find_qrcodes():
blueLED.on()
print (code)
img.draw_rectangle((code.x(), code.y(),code.w() ,code.h()),color=(255,0,0))
img.draw_circle(code.corners()[0][0], code.corners()[0][1], 5,color=(0,255,0))
img.draw_circle(code.corners()[1][0], code.corners()[1][1], 5,color=(0,0,255))
img.draw_circle(code.corners()[2][0], code.corners()[2][1], 5,color=(0,0,255))
img.draw_circle(code.corners()[3][0], code.corners()[3][1], 5,color=(0,0,255))
#print("You're on camera!")
#sensor.snapshot().save("example.jpg")
blueLED.off()
#blueLED.off()
#print("Done! Reset the camera to see the saved image.")
import pyb
import sensor
import image
import imu
from vl53l1x import VL53L1X
from machine import Pin, I2C
find_qrcodes()
.redLED = pyb.LED(1)
blueLED = pyb.LED(3)
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.reset()
: Resets and initializes the camera module.set_pixformat(sensor.RGB565)
: Sets the image format to color.set_framesize(sensor.QVGA)
: Sets resolution to 320x240 pixels (a good balance of quality and performance).You could optionally flip or mirror the image depending on your hardware setup:
# sensor.set_hflip(True)
# sensor.set_hmirror(True)
redLED.on()
sensor.skip_frames(time = 100)
redLED.off()
blueLED.on()
while(True):
img = sensor.snapshot()
for code in img.find_qrcodes():
blueLED.on()
print(code)
img.find_qrcodes()
: Detects QR codes in the current frame.print(code)
: Outputs the detected QR code data and position.img.draw_rectangle((code.x(), code.y(),code.w() ,code.h()), color=(255,0,0))
img.draw_circle(code.corners()[0][0], code.corners()[0][1], 5, color=(0,255,0))
img.draw_circle(code.corners()[1][0], code.corners()[1][1], 5, color=(0,0,255))
img.draw_circle(code.corners()[2][0], code.corners()[2][1], 5, color=(0,0,255))
img.draw_circle(code.corners()[3][0], code.corners()[3][1], 5, color=(0,0,255))
# distance = tof.read()
# imu_pitch = imu.pitch()
# imu_roll = imu.roll()
# temperature = imu.temperature_c()
blueLED.off()
This script lays the foundation for a vision-based embedded system using Nicla Vision that can: