Object Detection and Barcode Reading
Object detection is a computer technology related to computer vision and image processing that deals with detecting instances of semantic objects of a certain class (such as humans, buildings, or cars) in digital images and videos.1 It can be used in a barcode reading task as barcodes are often printed on objects like labels, books, etc. We can detect the objects first and then read barcodes on these objects, which has the following potential benefits:
- Improve the reading speed
- Check whether there are unread barcodes
- Save the image of the object with barcodes printed on it
In this article, we are going to explore some object detection methods and how to use them with barcode reading. The code is in Python with OpenCV for image processing and Dynamsoft Barcode Reader for barcode reading.
Sample image (5 bottles detected. 1 bottle without barcode read):
Object Detection
There are many ways to detect objects. If the objects have vivid features, we can use some simple image processing methods to detect them. If the objects are complex, we can use deep learning to detect them.
Here, we are going to list some methods for object detection.
Object Detection using Contours Finding
For the labels placed on a blue board, we can detect them by finding the contours on the image’s binary version.
-
Perform thresholding to get a binary image:
original_image = cv2.imread("img.jpg") gray = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(gray,200,255,cv2.THRESH_BINARY)
-
Find contours, filter out small irregular ones and draw their bounding rectangles.
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) rects = [] for cnt in contours: rect = cv2.boundingRect(cnt) x, y, w, h = rect if w > 50 and h > 20 and w>h: rects.append(rect) height, width, _ = original_image.shape min_x, min_y = width, height max_x = max_y = 0 for (x,y,w,h) in rects: color = (255,0,0) min_x, max_x = min(x, min_x), max(x+w, max_x) min_y, max_y = min(y, min_y), max(y+h, max_y) cv2.rectangle(original_image, (x,y), (x+w,y+h), color, 5)
Object Detection using Color Segmentation
In the following image, DataMatrix codes are printed on cassettes with vivid colors. We can detect the cassettes based on their colors. To do this, we can convert the image into HSV color space and use OpenCV’s inrange
method for segmentation.
-
Convert the image into HSV color space.
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
-
Use
inrange
to separate the specific color.lower = np.array([26,120,150]) upper = np.array([34,255,255]) mask = cv2.inRange(hsv, lower, upper)
Here is the mask for yellow.
Here is the dict of bounds for colors in this image.
colors_hsv = { "red": { "lower": np.array([156,150,100]), "upper": np.array([180,255,255]) }, "yellow": { "lower": np.array([26,120,150]), "upper": np.array([34,255,255]) }, "pink": { "lower": np.array([156,80,100]), "upper": np.array([180,140,255]) }, "green": { "lower": np.array([88,50,100]), "upper": np.array([99,80,255]) }, "blue": { "lower": np.array([78,120,100]), "upper": np.array([99,255,255]) } }
We can iterate the colors to detect all the cassettes.
-
Find contours on the mask, filter out small and irregular ones and get the bounding rectangles.
contours, hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) rects = [] height, width = img.shape for cnt in contours: rect = cv2.boundingRect(cnt) x, y, w, h = rect if w > 80 and h > 80 and w < width/2 and w>4*h: rects.append(rect) height, width, _ = original_image.shape min_x, min_y = width, height max_x = max_y = 0 for (x,y,w,h) in rects: min_x, max_x = min(x, min_x), max(x+w, max_x) min_y, max_y = min(y, min_y), max(y+h, max_y) cv2.rectangle(original_image, (x,y), (x+w,y+h), (255, 0, 0), 5)
Object Detection using YOLO
In the following image, there are five bottles. It is not easy to detect them with simple image processing. We can use YOLOv8 to detect them which is a deep learning method.
-
Install YOLOv8.
pip install ultralytics
-
Use the following code to detect the bottles.
from ultralytics import YOLO import cv2 model = YOLO("yolov8n.pt") img = cv2.imread("image.jpg") results = model.predict(source=img)
-
Save the detections in a list.
detections = [] for result in results: for box in result.boxes: xyxy = box.xyxy[0] detection = {} detection["x"] = int(xyxy[0]) detection["y"] = int(xyxy[1]) detection["w"] = int(xyxy[2]) - int(xyxy[0]) detection["h"] = int(xyxy[3]) - int(xyxy[1]) detection["confidence"] = float(box.conf) class_index = int(box.cls[0]) detection["class"] = model.names[class_index] detections.append(detection)
-
Draw the results.
for box in boxes: x = int(box["x"]) y = int(box["y"]) w = int(box["w"]) h = int(box["h"]) color = (255,0,0) cv2.rectangle(resized, (x, y), (x+w, y+h), color=color, thickness=2) cv2.putText(resized, box["class"], (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36,255,12), 2)
Barcode Reading
After detecting the objects, we can crop the images and read the barcodes on them. Here, we use Dynamsoft Barcode Reader to read them.
-
Activate the license. You can apply for a license here.
error = BarcodeReader.init_license("DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==") #one-day trial if error[0] != EnumErrorCode.DBR_OK: # Add your code for license error processing print("License error: "+ error[1])
-
Create a new instance of a barcode reader.
reader = BarcodeReader()
-
Set the barcode format to DataMatrix which is printed on the sample images.
settings = reader.get_runtime_settings() settings.barcode_format_ids = EnumBarcodeFormat.BF_DATAMATRIX reader.update_runtime_settings(settings)
-
Crop the objects in the images, read the barcodes in them and draw the results.
for box in boxes: has_barcodes = True box_image = img[box["y"]:box["y"]+box["h"],box["x"]:box["x"]+box["w"]] barcode_results = reader.decode_buffer(box_image) if barcode_results == None: has_barcodes = False color = (255,0,0) if has_barcodes == False: color = (0,0,255) cv2.rectangle(img, (x, y), (x+w, y+h), color=color, thickness=2)
If there are no barcodes found on the objects, use red to draw the rectangles.
Source Code
You can find the complete code here: https://github.com/tony-xlh/object-detection-and-barcode-reading
References
-
Dasiopoulou, Stamatia, et al. “Knowledge-assisted semantic video object detection.” IEEE Transactions on Circuits and Systems for Video Technology 15.10 (2005): 1210–1224. ↩