本文目录导读:

- Web 端(JavaScript + 浏览器摄像头)
- 原生 App(Android / iOS)
- 软硬件结合(通用脚本 - 基于 OpenCV + pyzbar)
- 检测“扫描异常”的通用方法论
- 专业工具(非脚本)
检测二维码扫描是否正常,通常取决于你的应用场景(是网页端、原生App、还是硬件设备),核心思路是:模拟扫描流程,验证解码结果和性能指标。
以下分不同场景给出具体的检测方案和脚本思路:
Web 端(JavaScript + 浏览器摄像头)
最常用的库是 html5-qrcode 或 zbar-wasm,检测“是否正常”主要看:摄像头能否打开、二维码能否被识别、识别速度。
检测脚本示例(使用 html5-qrcode):
<!DOCTYPE html>
<html>
<head>二维码扫描检测</title>
<script src="https://unpkg.com/html5-qrcode"></script>
</head>
<body>
<div id="reader" style="width:300px;"></div>
<div id="result"></div>
<script>
function testQRScanner() {
const html5QrCode = new Html5Qrcode("reader");
const resultDiv = document.getElementById('result');
// 1. 检测摄像头权限和可用性
Html5Qrcode.getCameras().then(devices => {
if (devices && devices.length) {
resultDiv.innerHTML = '✅ 摄像头可用,数量: ' + devices.length;
// 2. 尝试开始扫描(检测解码功能)
startScanner(html5QrCode, devices[0].id);
} else {
resultDiv.innerHTML = '❌ 未找到摄像头';
}
}).catch(err => {
resultDiv.innerHTML = '❌ 摄像头权限被拒绝或不可用: ' + err;
});
// 3. 设置超时检测(防止卡死)
setTimeout(() => {
if (resultDiv.innerHTML.includes('等待扫描')) {
resultDiv.innerHTML = '⚠️ 超时警告:扫描未响应(可能环境光线不足或二维码质量差)';
}
}, 10000); // 10秒超时
}
function startScanner(html5QrCode, cameraId) {
html5QrCode.start(
{ deviceId: cameraId },
{ fps: 10, qrbox: { width: 250, height: 250 } },
(decodedText, decodedResult) => {
// 成功解码
resultDiv.innerHTML = '✅ 扫描正常,解码内容: ' + decodedText;
html5QrCode.stop(); // 测试完成后停止
},
(errorMessage) => {
// 扫描失败(这是正常的,因为可能没对准二维码)
resultDiv.innerHTML = '⏳ 等待扫描... 错误: ' + errorMessage.substring(0, 30);
}
).catch(err => {
resultDiv.innerHTML = '❌ 启动摄像头失败: ' + err;
});
}
// 执行检测
testQRScanner();
</script>
</body>
</html>
检测的关键指标:
- 摄像头列表非空
start()方法无异常抛出- 10秒内成功解码至少一个二维码(可以准备一张测试二维码图片)
原生 App(Android / iOS)
Android(Java/Kotlin + ML Kit / ZXing)
可以使用 Instrumentation Test 或 UI Automator 进行自动化检测。
核心检测逻辑(伪代码):
// 使用 Espresso + 自定义摄像头模拟器
@Test
fun testQRScannerWorking() {
// 1. 启动扫描 Activity
val scenario = ActivityScenario.launch(ScannerActivity::class.java)
// 2. 注入模拟的二维码图像(Bitmap)
val testBitmap = generateQRBitmap("https://example.com")
injectCameraFrame(testBitmap) // 需要模拟 Camera2 API
// 3. 等待回调
onView(withId(R.id.scan_result))
.check(matches(withText(containsString("https://example.com"))))
// 4. 测试低光条件(可选)
val darkBitmap = generateDarkQRBitmap() // 降低亮度
injectCameraFrame(darkBitmap)
// 期望:失败或需要额外处理
}
iOS(Swift + AVFoundation)
使用 XCTest + CIImage 注入模拟帧:
func testQRScannerPerformance() {
let scanner = QRScannerController()
// 模拟 AVCaptureOutput 回调
let mockOutput = AVCaptureVideoDataOutput()
// 注入包含二维码的 CMSampleBuffer
scanner.captureOutput(mockOutput,
didOutput: sampleBufferWithQRCode,
from: connection)
// 断言闭包被调用且结果正确
XCTAssertEqual(scanner.lastDecodedResult, "test_data")
}
软硬件结合(通用脚本 - 基于 OpenCV + pyzbar)
如果你需要批量检测二维码打印质量或扫码枪灵敏度,可以使用 Python 脚本。
import cv2
from pyzbar.pyzbar import decode
import time
def test_qr_scanner(
image_path="test_qr.png", # 测试二维码图片
camera_index=0, # 摄像头索引
test_duration=10 # 测试时长(秒)
):
# 1. 测试静态图片解码
img = cv2.imread(image_path)
decoded_objects = decode(img)
if decoded_objects:
print(f"✅ 图片解码成功: {decoded_objects[0].data.decode()}")
print(f" 二维码位置: {decoded_objects[0].rect}")
else:
print("❌ 图片解码失败")
return False
# 2. 测试实时摄像头扫描
cap = cv2.VideoCapture(camera_index)
if not cap.isOpened():
print("❌ 无法打开摄像头")
return False
start_time = time.time()
scanned = False
while time.time() - start_time < test_duration:
ret, frame = cap.read()
if not ret:
print("❌ 摄像头读取帧失败")
break
# 检测二维码
decoded = decode(frame)
if decoded:
print(f"✅ 实时扫描成功: {decoded[0].data.decode()}")
print(f" 耗时: {time.time() - start_time:.2f} 秒")
scanned = True
break
cv2.imshow('Test', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
time.sleep(0.05)
if not scanned:
print(f"⚠️ 测试超时({test_duration}秒),未扫描到二维码")
print(" - 检查摄像头焦距")
print(" - 检查环境光线")
print(" - 检查二维码清晰度")
cap.release()
cv2.destroyAllWindows()
return scanned
# 运行测试
test_qr_scanner()
检测“扫描异常”的通用方法论
无论什么场景,检测是否正常主要关注以下三点:
| 检测项 | 正常标准 | 异常表现 | 检测方法 |
|---|---|---|---|
| 硬件可用性 | 摄像头能打开,无权限拒绝 | 空设备列表、权限弹窗 | getCameras() 或 cap.isOpened() |
| 解码成功率 | 标准二维码(30x30模块)能在 2 秒内识别 | 超时、解码失败 | 使用已知内容的测试码,测量耗时 |
| 鲁棒性 | 模糊、旋转 30°、亮度 50-300 lux 仍可识别 | 仅在完美条件下工作 | 在脚本中变换图像参数(模糊、旋转、亮度) |
专业工具(非脚本)
如果你需要检测扫码枪硬件(如霍尼韦尔、斑马等):
- USB 传输测试:使用串口工具(如 RealTerm)监听扫码枪输出,看是否有正确的 ASCII 码传输。
- 波型检测:对于激光扫码枪,用示波器查看激光信号波形是否正常(通常只有研发需要)。
- 前端/Web:用
html5-qrcode+ 超时检测。 - 原生 App:注入模拟图像帧到 Camera API。
- 硬件/批量测试:Python + OpenCV + pyzbar。
- 核心思路:准备一张的二维码,看系统能否在合理时间内正确解码。
如果你能提供更具体的场景(如:App 类型、使用什么库、是手机还是摄像头),我可以帮你定制更精确的检测脚本。