You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在OpenCV Python二维码扫描程序中限制扫描区域(仿Android二维码扫描框效果)

Restrict QR Code Scanning to a Specific Region (Custom Scan Frame)

I totally get what you're looking for—having a dedicated scan frame not only makes the UI more intuitive but also cuts down on unnecessary processing by focusing only on the area that matters. Let's tweak your existing code to add this feature, matching the styled scan frame you referenced.

Key Changes We'll Implement

  • Define a centered, adjustable scan region (square by default)
  • Draw a polished scan frame with corner markers and an animated scan line
  • Crop the video feed to only the scan region before running QR detection
  • Map detected QR code coordinates back to the original frame for accurate display

Modified Full Code

import cv2
import numpy as np
import sys
import pyzbar.pyzbar as pyzbar

cap = cv2.VideoCapture(0)
hasFrame, frame = cap.read()
if not hasFrame:
    print("Could not access camera!")
    sys.exit()

# Define scan region parameters (adjust these to fit your needs)
frame_width = frame.shape[1]
frame_height = frame.shape[0]
scan_size = min(frame_width, frame_height) // 2  # Size of the square scan frame
scan_x = (frame_width - scan_size) // 2
scan_y = (frame_height - scan_size) // 2
scan_w = scan_size
scan_h = scan_size

# Initialize video writer
vid_writer = cv2.VideoWriter('output.avi', cv2.VideoWriter_fourcc('M','J','P','G'), 10, (frame_width, frame_height))

# For animated scan line effect
scan_line_y = scan_y
scan_line_direction = 1  # 1 = move down, -1 = move up

# Display barcode/QR code location (adjusted for scan region coordinates)
def display(im, decodedObjects, scan_x, scan_y):
    for decodedObject in decodedObjects:
        points = decodedObject.polygon

        # Handle non-quad shapes with convex hull
        if len(points) > 4 :
            hull = cv2.convexHull(np.array([point for point in points], dtype=np.float32))
            hull = list(map(tuple, np.squeeze(hull)))
        else :
            hull = points
        
        # Adjust coordinates from cropped region back to original frame
        adjusted_hull = [(x + scan_x, y + scan_y) for (x, y) in hull]
        
        # Draw the convex hull
        n = len(adjusted_hull)
        for j in range(0, n):
            cv2.line(im, adjusted_hull[j], adjusted_hull[(j+1) % n], (255, 0, 0), 3)

# Initialize OpenCV QR detector
qrDecoder = cv2.QRCodeDetector()

while True:
    hasFrame, inputImage = cap.read()
    if not hasFrame:
        break
    
    # Draw scan frame UI elements
    # Outer border
    cv2.rectangle(inputImage, (scan_x-2, scan_y-2), (scan_x+scan_w+2, scan_y+scan_h+2), (0, 255, 0), 2)
    # Optional: Darken areas outside scan region to focus attention
    mask = np.zeros_like(inputImage)
    mask[scan_y:scan_y+scan_h, scan_x:scan_x+scan_w] = inputImage[scan_y:scan_y+scan_h, scan_x:scan_x+scan_w]
    inputImage = cv2.addWeighted(inputImage, 0.5, mask, 0.5, 0)
    # Corner markers for the scan frame
    corner_length = 20
    cv2.line(inputImage, (scan_x, scan_y), (scan_x + corner_length, scan_y), (0, 255, 0), 3)
    cv2.line(inputImage, (scan_x, scan_y), (scan_x, scan_y + corner_length), (0, 255, 0), 3)
    
    cv2.line(inputImage, (scan_x+scan_w, scan_y), (scan_x+scan_w - corner_length, scan_y), (0, 255, 0), 3)
    cv2.line(inputImage, (scan_x+scan_w, scan_y), (scan_x+scan_w, scan_y + corner_length), (0, 255, 0), 3)
    
    cv2.line(inputImage, (scan_x, scan_y+scan_h), (scan_x + corner_length, scan_y+scan_h), (0, 255, 0), 3)
    cv2.line(inputImage, (scan_x, scan_y+scan_h), (scan_x, scan_y+scan_h - corner_length), (0, 255, 0), 3)
    
    cv2.line(inputImage, (scan_x+scan_w, scan_y+scan_h), (scan_x+scan_w - corner_length, scan_y+scan_h), (0, 255, 0), 3)
    cv2.line(inputImage, (scan_x+scan_w, scan_y+scan_h), (scan_x+scan_w, scan_y+scan_h - corner_length), (0, 255, 0), 3)
    
    # Animate the scan line
    cv2.line(inputImage, (scan_x, scan_line_y), (scan_x+scan_w, scan_line_y), (0, 255, 0), 2)
    scan_line_y += scan_line_direction
    if scan_line_y >= scan_y + scan_h or scan_line_y <= scan_y:
        scan_line_direction *= -1
    
    # Crop to the scan region for QR detection
    scan_region = inputImage[scan_y:scan_y+scan_h, scan_x:scan_x+scan_w]
    
    # Run detection only on the cropped scan region
    decodedObjects = pyzbar.decode(scan_region)
    zbarData = decodedObjects[0].data.decode('utf-8') if decodedObjects else ''
    
    opencvData, bbox, rectifiedImage = qrDecoder.detectAndDecode(scan_region)
    
    # Display detection results
    if zbarData:
        cv2.putText(inputImage, f"ZBAR : {zbarData}", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)
    else:
        cv2.putText(inputImage, "ZBAR : QR Code NOT Detected", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA)

    if opencvData:
        cv2.putText(inputImage, f"OpenCV: {opencvData}", (10, 150), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)
    else:
        cv2.putText(inputImage, "OpenCV: QR Code NOT Detected", (10, 150), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA)

    # Draw detected QR code borders (adjusted to original frame)
    display(inputImage, decodedObjects, scan_x, scan_y)
    
    # Draw OpenCV's detected QR box if present
    if bbox is not None:
        bbox = bbox + np.array([[scan_x, scan_y]])
        n = len(bbox)
        for j in range(n):
            cv2.line(inputImage, tuple(bbox[j][0]), tuple(bbox[(j+1)%n][0]), (0, 0, 255), 3)
    
    cv2.imshow("Result", inputImage)
    vid_writer.write(inputImage)

    k = cv2.waitKey(20)
    if k == 27:  # Press ESC to exit
        break

cv2.destroyAllWindows()
vid_writer.release()
cap.release()

Breakdown of Key Modifications

  1. Scan Region Setup:
    • We calculate a centered square using the camera's frame dimensions. Adjust scan_size to make the frame larger or smaller as needed.
  2. Polished UI:
    • Added corner markers and an animated scan line to match the example you referenced.
    • Optional darkening of areas outside the scan region helps users focus on the target area.
  3. Cropped Detection:
    • Only the scan region is passed to QR detection functions, reducing processing overhead and ensuring only codes in the frame are recognized.
  4. Coordinate Adjustment:
    • Detected QR code coordinates are mapped back to the original frame so the bounding boxes appear in the correct position.

内容的提问来源于stack exchange,提问作者alex-uarent-alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 19:19:06