Added scanning barcodes with a camera
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# Configure Barcode Readers {#configure-readers}
|
||||
|
||||
This guide explains how to configure which barcode formats Quagga2 will detect.
|
||||
|
||||
## Basic Configuration {#basic-configuration}
|
||||
|
||||
Specify readers in the `decoder.readers` array:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
decoder: {
|
||||
readers: ["code_128_reader", "ean_reader"]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Available Readers {#available-readers}
|
||||
|
||||
| Reader | Format | Common Uses |
|
||||
|--------|--------|-------------|
|
||||
| `code_128_reader` | Code 128 | Shipping, packaging |
|
||||
| `ean_reader` | EAN-13 | Retail products |
|
||||
| `ean_8_reader` | EAN-8 | Small products |
|
||||
| `upc_reader` | UPC-A | North American retail |
|
||||
| `upc_e_reader` | UPC-E | Small products |
|
||||
| `code_39_reader` | Code 39 | Industrial |
|
||||
| `code_39_vin_reader` | Code 39 VIN | Vehicle identification |
|
||||
| `codabar_reader` | Codabar | Libraries, blood banks |
|
||||
| `i2of5_reader` | Interleaved 2 of 5 | Warehouse |
|
||||
| `2of5_reader` | Standard 2 of 5 | Industrial |
|
||||
| `code_93_reader` | Code 93 | Logistics |
|
||||
| `code_32_reader` | Code 32 | Italian pharmaceuticals |
|
||||
|
||||
## Reader Priority {#reader-priority}
|
||||
|
||||
Readers are processed in order. Put most likely formats first:
|
||||
|
||||
```javascript
|
||||
decoder: {
|
||||
readers: [
|
||||
"ean_reader", // Most common - checked first
|
||||
"upc_reader", // Second most common
|
||||
"code_128_reader" // Fallback
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## EAN Supplements {#ean-supplements}
|
||||
|
||||
To read EAN-2 or EAN-5 extension supplements:
|
||||
|
||||
```javascript
|
||||
decoder: {
|
||||
readers: [
|
||||
"ean_reader", // Regular EAN without supplements
|
||||
{
|
||||
format: "ean_reader",
|
||||
config: {
|
||||
supplements: ["ean_5_reader", "ean_2_reader"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices {#best-practices}
|
||||
|
||||
1. **Only enable needed readers** - More readers = slower performance
|
||||
2. **Order by frequency** - Put most common formats first
|
||||
3. **Test thoroughly** - Some formats can conflict
|
||||
|
||||
## Related {#related}
|
||||
|
||||
- [Supported Barcode Types](../reference/readers.md) - Complete reader documentation
|
||||
- [Configuration Reference](../reference/configuration.md) - All configuration options
|
||||
|
||||
---
|
||||
|
||||
[← Back to How-To Guides](index.md)
|
||||
234
quagga2/quagga2-1.12.1/docs/how-to-guides/external-readers.md
Normal file
234
quagga2/quagga2-1.12.1/docs/how-to-guides/external-readers.md
Normal file
@@ -0,0 +1,234 @@
|
||||
# How-To: Create and Use External Readers {#create-and-use-external-readers}
|
||||
|
||||
This guide explains how to create custom barcode reader plugins and integrate them into Quagga2.
|
||||
|
||||
## Using Existing External Readers {#using-existing-external-readers}
|
||||
|
||||
### QR Code Reader {#qr-code-reader}
|
||||
|
||||
The most common external reader is [quagga2-reader-qr](https://github.com/ericblade/quagga2-reader-qr) for QR code support:
|
||||
|
||||
```javascript
|
||||
import Quagga from '@ericblade/quagga2';
|
||||
import QRReader from 'quagga2-reader-qr';
|
||||
|
||||
// Register the external reader
|
||||
Quagga.registerReader('qr', QRReader);
|
||||
|
||||
// Use it in your config
|
||||
Quagga.init({
|
||||
decoder: {
|
||||
readers: ['qr']
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## External Reader Priority {#external-reader-priority}
|
||||
|
||||
External readers follow the **same priority rules** as built-in readers:
|
||||
|
||||
1. **Registration first**: Call `Quagga.registerReader(name, ReaderClass)` before using the reader
|
||||
2. **Position determines priority**: The reader's position in the `readers` array determines when it attempts to decode
|
||||
3. **First success wins**: The first reader to return a valid result is used
|
||||
|
||||
### Example: Prioritizing External Readers {#prioritizing-external-readers}
|
||||
|
||||
```javascript
|
||||
// Register external reader
|
||||
Quagga.registerReader('my_custom_reader', MyCustomReader);
|
||||
|
||||
// External reader tried first, then built-in readers
|
||||
Quagga.init({
|
||||
decoder: {
|
||||
readers: ['my_custom_reader', 'ean_reader', 'code_128_reader']
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Example: External Reader as Fallback {#external-reader-fallback}
|
||||
|
||||
```javascript
|
||||
// Register external reader
|
||||
Quagga.registerReader('my_fallback_reader', MyFallbackReader);
|
||||
|
||||
// Built-in readers tried first, external as fallback
|
||||
Quagga.init({
|
||||
decoder: {
|
||||
readers: ['ean_reader', 'code_128_reader', 'my_fallback_reader']
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Creating Custom Readers {#creating-custom-readers}
|
||||
|
||||
Quagga2 exports the `BarcodeReader` prototype that you can extend to create custom readers.
|
||||
|
||||
### Basic Reader Structure {#basic-reader-structure}
|
||||
|
||||
```javascript
|
||||
import { Readers } from '@ericblade/quagga2';
|
||||
|
||||
const { BarcodeReader } = Readers;
|
||||
|
||||
class MyCustomReader extends BarcodeReader {
|
||||
FORMAT = 'my_custom_format';
|
||||
|
||||
constructor(config, supplements) {
|
||||
super(config, supplements);
|
||||
// Custom initialization
|
||||
}
|
||||
|
||||
decode(row, start) {
|
||||
// Implement barcode decoding logic
|
||||
// row: Array<number> - binary line data
|
||||
// start: number - starting position
|
||||
|
||||
// Return null if no barcode found
|
||||
// Return Barcode object if successful
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export default MyCustomReader;
|
||||
```
|
||||
|
||||
### Reader Return Format {#reader-return-format}
|
||||
|
||||
Your `decode()` method should return either `null` (no match) or a result object:
|
||||
|
||||
```javascript
|
||||
{
|
||||
code: '1234567890', // The decoded barcode value
|
||||
start: 0, // Start position in the row
|
||||
end: 100, // End position in the row
|
||||
startInfo: { start: 0, end: 10 }, // Start pattern info
|
||||
format: 'my_custom_format', // Your reader's format name
|
||||
decodedCodes: [...] // Optional: decoded character info
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern Matching Utilities {#pattern-matching-utilities}
|
||||
|
||||
BarcodeReader provides useful methods for pattern matching:
|
||||
|
||||
- `_nextSet(line, offset)` - Find next set (1) bit
|
||||
- `_nextUnset(line, offset)` - Find next unset (0) bit
|
||||
- `_matchPattern(counter, code, maxSingleError)` - Match bar patterns
|
||||
- `_fillCounters(offset, end, isWhite)` - Count consecutive bars/spaces
|
||||
|
||||
### Example: Simple Pattern Reader {#simple-pattern-reader}
|
||||
|
||||
```javascript
|
||||
class SimpleBarReader extends BarcodeReader {
|
||||
FORMAT = 'simple_bar';
|
||||
START_PATTERN = [1, 1, 1]; // Three bars pattern
|
||||
|
||||
decode(row, start) {
|
||||
if (row) {
|
||||
this._row = row;
|
||||
}
|
||||
|
||||
// Find start pattern
|
||||
const startInfo = this._findPattern(this.START_PATTERN, 0, false);
|
||||
if (!startInfo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Decode the barcode content
|
||||
const result = this._decodeContent(startInfo.end);
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
code: result.code,
|
||||
start: startInfo.start,
|
||||
end: result.end,
|
||||
startInfo: startInfo,
|
||||
format: this.FORMAT
|
||||
};
|
||||
}
|
||||
|
||||
_decodeContent(offset) {
|
||||
// Implement your decoding logic
|
||||
return null;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Image-Based Readers {#image-based-readers}
|
||||
|
||||
For non-linear barcodes (like QR codes), implement `decodeImage()` instead:
|
||||
|
||||
```javascript
|
||||
class MyImageReader extends BarcodeReader {
|
||||
FORMAT = 'my_image_format';
|
||||
|
||||
// Override decode to return null (not a linear barcode)
|
||||
decode() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Implement image-based decoding
|
||||
async decodeImage(imageWrapper) {
|
||||
// imageWrapper.data - pixel data
|
||||
// imageWrapper.size - { x, y } dimensions
|
||||
|
||||
// Process the image and decode
|
||||
const result = await this.processImage(imageWrapper);
|
||||
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
codeResult: {
|
||||
code: result.data,
|
||||
format: this.FORMAT
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Your Reader {#testing-your-reader}
|
||||
|
||||
1. **Unit tests**: Test pattern matching and decoding logic in isolation
|
||||
2. **Integration tests**: Use `Quagga.decodeSingle()` with test images
|
||||
3. **Live testing**: Test with real camera input
|
||||
|
||||
### Example Test {#example-test}
|
||||
|
||||
```javascript
|
||||
import Quagga from '@ericblade/quagga2';
|
||||
import MyCustomReader from './my-custom-reader';
|
||||
|
||||
Quagga.registerReader('my_custom', MyCustomReader);
|
||||
|
||||
const result = await Quagga.decodeSingle({
|
||||
src: './test-image.jpg',
|
||||
decoder: {
|
||||
readers: ['my_custom']
|
||||
}
|
||||
});
|
||||
|
||||
console.log('Result:', result?.codeResult?.code);
|
||||
```
|
||||
|
||||
## Best Practices {#best-practices}
|
||||
|
||||
1. **Set unique FORMAT**: Use a distinctive format name to identify your reader
|
||||
2. **Handle edge cases**: Return `null` gracefully when patterns don't match
|
||||
3. **Validate checksums**: Implement checksum validation when the format supports it
|
||||
4. **Consider performance**: Optimize pattern matching for real-time scanning
|
||||
5. **Test thoroughly**: Test with various image qualities and conditions
|
||||
|
||||
## Related {#related}
|
||||
|
||||
- [Supported Barcode Types](../reference/readers.md) - Built-in readers
|
||||
- [Configuration Reference](../reference/configuration.md) - Full config options
|
||||
- [quagga2-reader-qr](https://github.com/ericblade/quagga2-reader-qr) - Example external reader
|
||||
|
||||
---
|
||||
|
||||
[← Back to How-To Guides](index.md)
|
||||
@@ -0,0 +1,127 @@
|
||||
# Handle Difficult Barcodes {#handle-difficult-barcodes}
|
||||
|
||||
This guide provides techniques for improving barcode detection in challenging conditions.
|
||||
|
||||
## Common Challenges {#common-challenges}
|
||||
|
||||
- Poor lighting or shadows
|
||||
- Blurry or out-of-focus images
|
||||
- Small or distant barcodes
|
||||
- Damaged or partially obscured barcodes
|
||||
- Low contrast between bars and background
|
||||
|
||||
## Improving Detection {#improving-detection}
|
||||
|
||||
### Adjust Patch Size {#adjust-patch-size}
|
||||
|
||||
For small or distant barcodes, use a smaller patch size:
|
||||
|
||||
```javascript
|
||||
locator: {
|
||||
patchSize: "small" // or "x-small" for very small barcodes
|
||||
}
|
||||
```
|
||||
|
||||
### Increase Resolution {#increase-resolution}
|
||||
|
||||
Higher resolution provides more detail:
|
||||
|
||||
```javascript
|
||||
inputStream: {
|
||||
size: 1280, // Larger processing size
|
||||
constraints: {
|
||||
width: { ideal: 1920 },
|
||||
height: { ideal: 1080 }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Disable Half Sampling {#disable-half-sampling}
|
||||
|
||||
For fine details, process at full resolution:
|
||||
|
||||
```javascript
|
||||
locator: {
|
||||
halfSample: false
|
||||
}
|
||||
```
|
||||
|
||||
## Handling False Positives {#handling-false-positives}
|
||||
|
||||
### Validate Results {#validate-results}
|
||||
|
||||
Check result confidence and format:
|
||||
|
||||
```javascript
|
||||
Quagga.onDetected(function(result) {
|
||||
// Check if result has expected format
|
||||
if (result.codeResult.format !== 'ean_13') {
|
||||
return; // Ignore unexpected formats
|
||||
}
|
||||
|
||||
// Validate checksum externally if needed
|
||||
if (!validateBarcode(result.codeResult.code)) {
|
||||
return;
|
||||
}
|
||||
|
||||
processBarcode(result.codeResult.code);
|
||||
});
|
||||
```
|
||||
|
||||
### Require Multiple Reads {#require-multiple-reads}
|
||||
|
||||
Confirm detection across multiple frames:
|
||||
|
||||
```javascript
|
||||
let lastCode = null;
|
||||
let readCount = 0;
|
||||
|
||||
Quagga.onDetected(function(result) {
|
||||
const code = result.codeResult.code;
|
||||
|
||||
if (code === lastCode) {
|
||||
readCount++;
|
||||
if (readCount >= 3) {
|
||||
// Confirmed detection
|
||||
processBarcode(code);
|
||||
readCount = 0;
|
||||
}
|
||||
} else {
|
||||
lastCode = code;
|
||||
readCount = 1;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Using Debug Flags {#using-debug-flags}
|
||||
|
||||
Enable visual debugging to understand detection issues:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
debug: true,
|
||||
decoder: {
|
||||
debug: {
|
||||
drawBoundingBox: true,
|
||||
drawScanline: true
|
||||
}
|
||||
},
|
||||
locator: {
|
||||
debug: {
|
||||
showFoundPatches: true
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
See [Use Debug Flags](use-debug-flags.md) for complete details.
|
||||
|
||||
## Related {#related}
|
||||
|
||||
- [Configuration Reference](../reference/configuration.md) - All configuration options
|
||||
- [Optimize Performance](optimize-performance.md) - Balance accuracy vs speed
|
||||
- [Use Debug Flags](use-debug-flags.md) - Diagnostic tools
|
||||
|
||||
---
|
||||
|
||||
[← Back to How-To Guides](index.md)
|
||||
77
quagga2/quagga2-1.12.1/docs/how-to-guides/index.md
Normal file
77
quagga2/quagga2-1.12.1/docs/how-to-guides/index.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# How-To Guides
|
||||
|
||||
Task-oriented guides for solving specific problems with Quagga2. These assume you have basic familiarity with the library and focus on getting things done.
|
||||
|
||||
## Configuration & Setup
|
||||
|
||||
### [Configure Barcode Readers](configure-readers.md)
|
||||
|
||||
Select which barcode formats to scan (EAN, CODE 128, UPC, etc.) and understand the trade-offs.
|
||||
|
||||
### [Use Debug Flags](use-debug-flags.md) 🆕
|
||||
|
||||
Enable diagnostic output to troubleshoot issues with localization, decoding, or camera setup.
|
||||
|
||||
## Performance & Quality
|
||||
|
||||
### [Optimize Performance](optimize-performance.md)
|
||||
|
||||
Improve scanning speed and reduce CPU usage through configuration tuning.
|
||||
|
||||
### [Handle Difficult Barcodes](handle-difficult-barcodes.md)
|
||||
|
||||
Techniques for decoding barcodes with poor lighting, damage, rotation, or small size.
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### [Create External Readers](external-readers.md)
|
||||
|
||||
Build custom barcode decoder plugins to support additional formats.
|
||||
|
||||
## Camera & Input
|
||||
|
||||
### [Select Specific Camera](select-camera.md) *(Coming Soon)*
|
||||
|
||||
Choose between front/back cameras on mobile devices or select from multiple USB cameras.
|
||||
|
||||
### [Adjust Camera Settings](camera-settings.md) *(Coming Soon)*
|
||||
|
||||
Control focus, zoom, flash/torch, and other camera parameters.
|
||||
|
||||
## Drawing & Visualization
|
||||
|
||||
### [Working with Box Coordinates](working-with-coordinates.md) 🆕
|
||||
|
||||
Understand how `box`, `boxes`, and `line` coordinates relate to processed vs. original image dimensions, and how to properly scale coordinates for overlay rendering on video elements.
|
||||
|
||||
## Tips & Best Practices
|
||||
|
||||
### [Tips and Tricks](tips-and-tricks.md)
|
||||
|
||||
Practical advice for getting the best results with Quagga2, including camera setup, user experience, and handling results.
|
||||
|
||||
## Integration
|
||||
|
||||
### [Handle Multiple Barcodes](multiple-barcodes.md) *(Coming Soon)*
|
||||
|
||||
Detect and decode several barcodes in a single frame simultaneously.
|
||||
|
||||
### [Scan in Background](background-scanning.md) *(Coming Soon)*
|
||||
|
||||
Continue scanning while users interact with other UI elements.
|
||||
|
||||
## Differences from Tutorials
|
||||
|
||||
**Tutorials** are for learning - they're comprehensive, beginner-friendly, and explain *why* you're doing each step.
|
||||
|
||||
**How-To Guides** are for doing - they're focused, assume knowledge, and show *how* to accomplish specific goals.
|
||||
|
||||
If you're new to Quagga2, start with [Tutorials](../tutorials/) instead.
|
||||
|
||||
## Contributing
|
||||
|
||||
Have a useful technique or solution to share? We welcome contributions! See the [Contributing Guide](../contributing.md).
|
||||
|
||||
---
|
||||
|
||||
[← Back to Documentation Home](../index.md)
|
||||
@@ -0,0 +1,114 @@
|
||||
# Optimize Performance {#optimize-performance}
|
||||
|
||||
This guide covers techniques to improve Quagga2's barcode scanning performance.
|
||||
|
||||
## Overview {#overview}
|
||||
|
||||
Performance optimization in Quagga2 involves balancing accuracy against speed. The key areas to optimize are:
|
||||
|
||||
- Input resolution and scaling
|
||||
- Locator configuration
|
||||
- Reader selection
|
||||
- Processing frequency
|
||||
|
||||
## Input Resolution {#input-resolution}
|
||||
|
||||
### Using `inputStream.size` {#inputstream-size}
|
||||
|
||||
Reducing the processing resolution is the most effective way to improve performance:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
inputStream: {
|
||||
size: 640 // Process at 640px max dimension instead of full resolution
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Recommended values:**
|
||||
- **1280px** - High quality, slower (good for static images)
|
||||
- **800px** - Balanced (default for `decodeSingle`)
|
||||
- **640px** - Fast (recommended for live scanning)
|
||||
- **480px** - Very fast (may reduce accuracy)
|
||||
|
||||
### Camera Constraints {#camera-constraints}
|
||||
|
||||
Request only the resolution you need:
|
||||
|
||||
```javascript
|
||||
inputStream: {
|
||||
constraints: {
|
||||
width: { ideal: 1280 },
|
||||
height: { ideal: 720 }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Locator Configuration {#locator-configuration}
|
||||
|
||||
### Half Sampling {#half-sampling}
|
||||
|
||||
Keep `halfSample: true` (default) for faster localization:
|
||||
|
||||
```javascript
|
||||
locator: {
|
||||
halfSample: true // Processes at half resolution
|
||||
}
|
||||
```
|
||||
|
||||
### Patch Size {#patch-size}
|
||||
|
||||
Larger patch sizes are faster but may miss small barcodes:
|
||||
|
||||
```javascript
|
||||
locator: {
|
||||
patchSize: "large" // Options: x-small, small, medium, large, x-large
|
||||
}
|
||||
```
|
||||
|
||||
## Reader Selection {#reader-selection}
|
||||
|
||||
Only enable the barcode formats you need:
|
||||
|
||||
```javascript
|
||||
decoder: {
|
||||
readers: ["code_128_reader"] // Don't enable all readers
|
||||
}
|
||||
```
|
||||
|
||||
## Processing Frequency {#processing-frequency}
|
||||
|
||||
Limit scan rate to reduce CPU usage:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
frequency: 10 // Max 10 scans per second
|
||||
});
|
||||
```
|
||||
|
||||
## Disable Localization {#disable-localization}
|
||||
|
||||
If barcode position is fixed, disable localization entirely:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
locate: false,
|
||||
inputStream: {
|
||||
area: {
|
||||
top: "25%",
|
||||
right: "25%",
|
||||
bottom: "25%",
|
||||
left: "25%"
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Related {#related}
|
||||
|
||||
- [Configuration Reference](../reference/configuration.md) - All configuration options
|
||||
- [How Barcode Localization Works](../explanation/how-barcode-localization-works.md) - Understanding the algorithm
|
||||
|
||||
---
|
||||
|
||||
[← Back to How-To Guides](index.md)
|
||||
115
quagga2/quagga2-1.12.1/docs/how-to-guides/tips-and-tricks.md
Normal file
115
quagga2/quagga2-1.12.1/docs/how-to-guides/tips-and-tricks.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# Tips and Tricks {#tips-and-tricks}
|
||||
|
||||
Practical advice for getting the best results with Quagga2.
|
||||
|
||||
## Camera Setup {#camera-setup}
|
||||
|
||||
### Choosing the Right Camera {#choosing-camera}
|
||||
|
||||
- Use the **back camera** on mobile devices (higher resolution, autofocus)
|
||||
- Request environment-facing camera: `facingMode: "environment"`
|
||||
- Avoid wide-angle cameras for barcode scanning
|
||||
|
||||
### Optimal Distance {#optimal-distance}
|
||||
|
||||
- Barcode should fill 50-80% of the frame width
|
||||
- Too close: barcode may be out of focus
|
||||
- Too far: insufficient resolution for small bars
|
||||
|
||||
## Lighting {#lighting}
|
||||
|
||||
- Ensure even lighting across the barcode
|
||||
- Avoid harsh shadows or reflections
|
||||
- Enable torch/flash for dark environments:
|
||||
|
||||
```javascript
|
||||
await Quagga.CameraAccess.enableTorch();
|
||||
```
|
||||
|
||||
## User Experience {#user-experience}
|
||||
|
||||
### Visual Feedback {#visual-feedback}
|
||||
|
||||
Show users the scan area:
|
||||
|
||||
```javascript
|
||||
inputStream: {
|
||||
area: {
|
||||
top: "25%",
|
||||
right: "10%",
|
||||
bottom: "25%",
|
||||
left: "10%",
|
||||
borderColor: "rgba(0, 255, 0, 0.7)",
|
||||
borderWidth: 2
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Audio Feedback {#audio-feedback}
|
||||
|
||||
Play a sound on successful scan:
|
||||
|
||||
```javascript
|
||||
Quagga.onDetected(function(result) {
|
||||
new Audio('/beep.mp3').play();
|
||||
processBarcode(result.codeResult.code);
|
||||
});
|
||||
```
|
||||
|
||||
## Performance {#performance}
|
||||
|
||||
### Reduce CPU Usage {#reduce-cpu-usage}
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
frequency: 10, // Limit to 10 scans/second
|
||||
inputStream: {
|
||||
size: 640 // Reduce processing resolution
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Stop When Not Needed {#stop-when-not-needed}
|
||||
|
||||
```javascript
|
||||
// Stop scanning when modal closes
|
||||
Quagga.stop();
|
||||
|
||||
// Remove event handlers
|
||||
Quagga.offDetected();
|
||||
Quagga.offProcessed();
|
||||
```
|
||||
|
||||
## Handling Results {#handling-results}
|
||||
|
||||
### Debounce Detections {#debounce-detections}
|
||||
|
||||
Avoid processing the same barcode multiple times:
|
||||
|
||||
```javascript
|
||||
let lastScanned = '';
|
||||
let lastTime = 0;
|
||||
|
||||
Quagga.onDetected(function(result) {
|
||||
const code = result.codeResult.code;
|
||||
const now = Date.now();
|
||||
|
||||
if (code === lastScanned && now - lastTime < 2000) {
|
||||
return; // Same barcode within 2 seconds
|
||||
}
|
||||
|
||||
lastScanned = code;
|
||||
lastTime = now;
|
||||
processBarcode(code);
|
||||
});
|
||||
```
|
||||
|
||||
## Related {#related}
|
||||
|
||||
- [Optimize Performance](optimize-performance.md) - Detailed performance guide
|
||||
- [Handle Difficult Barcodes](handle-difficult-barcodes.md) - Improve detection
|
||||
- [Camera Access API](../reference/camera-access.md) - Camera control
|
||||
|
||||
---
|
||||
|
||||
[← Back to How-To Guides](index.md)
|
||||
776
quagga2/quagga2-1.12.1/docs/how-to-guides/use-debug-flags.md
Normal file
776
quagga2/quagga2-1.12.1/docs/how-to-guides/use-debug-flags.md
Normal file
@@ -0,0 +1,776 @@
|
||||
# How to Use Debug Flags {#how-to-use-debug-flags}
|
||||
|
||||
Quagga2 includes several debug flags that enable diagnostic console output to help troubleshoot issues with barcode detection and decoding. This guide explains when and how to use them.
|
||||
|
||||
## Overview {#overview}
|
||||
|
||||
Debug flags control what information Quagga2 logs to the browser console. By default, **all debug output is suppressed** to keep your console clean. Enable specific flags when you need to diagnose problems.
|
||||
|
||||
## Important Note {#important-note}
|
||||
|
||||
Debug flags only work when `ENV.development` is `true` (development builds). Production builds strip out all debug code to minimize bundle size.
|
||||
|
||||
## Available Debug Flags {#available-debug-flags}
|
||||
|
||||
Debug flags are organized into three categories:
|
||||
|
||||
1. **Console logging flags** - Print diagnostic information to the console
|
||||
2. **Visual canvas overlays** - Draw debugging information on the canvas
|
||||
3. **Performance analysis** - Display frequency and pattern data
|
||||
|
||||
### Console Logging Flags {#console-logging-flags}
|
||||
|
||||
#### `inputStream.debug.showImageDetails` {#inputstream-debug-showimagedetails}
|
||||
|
||||
**What it shows**: Image loading and frame grabber operations
|
||||
|
||||
**Console output example**:
|
||||
|
||||
```text
|
||||
*** frame_grabber_browser: willReadFrequency=undefined canvas=<canvas>
|
||||
Image Loader: Loaded 3 images from /path/to/image.jpg
|
||||
```
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Camera feed not showing
|
||||
- Images not loading from file input
|
||||
- Canvas-related issues
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
inputStream: {
|
||||
// ... your input config
|
||||
debug: {
|
||||
showImageDetails: true
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
#### `decoder.debug.printReaderInfo` {#decoder-debug-printreaderinfo}
|
||||
|
||||
**What it shows**: Barcode reader registration and initialization
|
||||
|
||||
**Console output example**:
|
||||
|
||||
```text
|
||||
* ImageWrapper getCanvasAndContext
|
||||
Registering reader: code_128_reader
|
||||
Before registering reader: EANReader
|
||||
Registered Readers: code_128, ean
|
||||
```
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Verifying which readers are active
|
||||
- Reader not detecting expected barcode type
|
||||
- Multiple reader configuration issues
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
decoder: {
|
||||
readers: ["code_128_reader", "ean_reader"],
|
||||
debug: {
|
||||
printReaderInfo: true
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
#### `locator.debug.showPatchSize` {#locator-debug-showpatchsize}
|
||||
|
||||
**What it shows**: Patch dimensions during barcode localization
|
||||
|
||||
**Console output example**:
|
||||
|
||||
```text
|
||||
Patch-Size: 320x240
|
||||
```
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Barcode locator not finding barcodes
|
||||
- Understanding what image size the locator is processing
|
||||
- Performance optimization (smaller patches = faster)
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
locator: {
|
||||
patchSize: "medium",
|
||||
debug: {
|
||||
showPatchSize: true
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
#### `locator.debug.showImageDetails` {#locator-debug-showimagedetails}
|
||||
|
||||
**What it shows**: Canvas and image wrapper initialization for locator
|
||||
|
||||
**Console output example**:
|
||||
|
||||
```text
|
||||
* initCanvas getCanvasAndContext
|
||||
* ImageWrapper getCanvasAndContext
|
||||
```
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Locator canvas not rendering
|
||||
- Debugging locator initialization failures
|
||||
- Understanding when canvas contexts are created
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
locator: {
|
||||
// ... your locator config
|
||||
debug: {
|
||||
showImageDetails: true
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
### Visual Canvas Overlay Flags {#visual-canvas-overlay-flags}
|
||||
|
||||
These flags draw debugging information directly on the canvas, allowing you to visualize the barcode detection algorithm's internal state.
|
||||
|
||||
Note: The scan area overlay (defined via `inputStream.area`) is not a debug flag. When `locate: false`, Quagga draws the scan area on the overlay canvas each processed frame. You can also draw it manually using `Quagga.drawScannerArea()`. See the [Configuration Reference](../reference/configuration.md#inputstream-area-drawing) and [API](../reference/api.md#quagga-drawscannerarea).
|
||||
|
||||
#### `decoder.debug.drawBoundingBox` {#decoder-debug-drawboundingbox}
|
||||
|
||||
**What it shows**: Draws a box around the detected barcode location
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Verify barcode is being located correctly
|
||||
- Debug positioning issues
|
||||
- Understand where the decoder thinks the barcode is
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
decoder: {
|
||||
debug: {
|
||||
drawBoundingBox: true
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
#### `decoder.debug.drawScanline` {#decoder-debug-drawscanline}
|
||||
|
||||
**What it shows**: Draws the scanline path used for decoding
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Verify scanner is reading through the barcode correctly
|
||||
- Debug angle/orientation issues
|
||||
- Understand why certain barcodes fail to decode
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
decoder: {
|
||||
debug: {
|
||||
drawScanline: true
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
#### `locator.debug.showCanvas` {#locator-debug-showcanvas}
|
||||
|
||||
**What it shows**: Displays the locator's internal canvas used for image processing
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Debug localization algorithm
|
||||
- Verify image preprocessing is working
|
||||
- Understand what the locator "sees"
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
locator: {
|
||||
debug: {
|
||||
showCanvas: true
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
#### `locator.debug.showPatches` {#locator-debug-showpatches}
|
||||
|
||||
**What it shows**: Draws all patches extracted during the localization phase
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Debug patch extraction issues
|
||||
- Verify patch size is appropriate
|
||||
- Understand what regions are being analyzed
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
locator: {
|
||||
debug: {
|
||||
showPatches: true
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
#### `locator.debug.showFoundPatches` {#locator-debug-showfoundpatches}
|
||||
|
||||
**What it shows**: Highlights patches where potential barcodes were found
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Verify barcode candidates are being identified
|
||||
- Debug false positives/negatives in patch detection
|
||||
- Optimize patch threshold settings
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
locator: {
|
||||
debug: {
|
||||
showFoundPatches: true
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
#### `locator.debug.showSkeleton` {#locator-debug-showskeleton}
|
||||
|
||||
**What it shows**: Displays the skeleton structure extracted from patches
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Debug advanced localization algorithm
|
||||
- Understand structure detection
|
||||
- Verify skeleton extraction is working
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
locator: {
|
||||
debug: {
|
||||
showSkeleton: true
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
#### `locator.debug.showLabels` {#locator-debug-showlabels}
|
||||
|
||||
**What it shows**: Displays component labels during connected component analysis
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Debug component labeling phase
|
||||
- Verify components are being identified correctly
|
||||
- Understand clustering behavior
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
locator: {
|
||||
debug: {
|
||||
showLabels: true
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
#### `locator.debug.showPatchLabels` {#locator-debug-showpatchlabels}
|
||||
|
||||
**What it shows**: Shows labels assigned to individual patches
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Debug patch classification
|
||||
- Verify patches are being labeled correctly
|
||||
- Understand patch grouping
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
locator: {
|
||||
debug: {
|
||||
showPatchLabels: true
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
#### `locator.debug.showRemainingPatchLabels` {#locator-debug-showremainingpatchlabels}
|
||||
|
||||
**What it shows**: Displays labels for patches remaining after filtering
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Debug patch filtering logic
|
||||
- Verify correct patches survive filtering
|
||||
- Optimize filter thresholds
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
locator: {
|
||||
debug: {
|
||||
showRemainingPatchLabels: true
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
#### `locator.debug.boxFromPatches.showTransformed` {#locator-debug-boxfrompatches-showtransformed}
|
||||
|
||||
**What it shows**: Shows transformed patch coordinates during box calculation
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Debug coordinate transformation
|
||||
- Verify spatial transformations are correct
|
||||
- Understand box calculation from patches
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
locator: {
|
||||
debug: {
|
||||
boxFromPatches: {
|
||||
showTransformed: true
|
||||
}
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
#### `locator.debug.boxFromPatches.showTransformedBox` {#locator-debug-boxfrompatches-showtransformedbox}
|
||||
|
||||
**What it shows**: Displays the bounding box after transformation
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Debug box transformation
|
||||
- Verify box coordinates after spatial transform
|
||||
- Understand final box positioning
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
locator: {
|
||||
debug: {
|
||||
boxFromPatches: {
|
||||
showTransformedBox: true
|
||||
}
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
#### `locator.debug.boxFromPatches.showBB` {#locator-debug-boxfrompatches-showbb}
|
||||
|
||||
**What it shows**: Displays the final bounding box around detected barcode region
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Verify final bounding box is correct
|
||||
- Debug box calculation from patches
|
||||
- Optimize localization accuracy
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
locator: {
|
||||
debug: {
|
||||
boxFromPatches: {
|
||||
showBB: true
|
||||
}
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
### Performance Analysis Flags {#performance-analysis-flags}
|
||||
|
||||
#### `decoder.debug.showFrequency` {#decoder-debug-showfrequency}
|
||||
|
||||
**What it shows**: Displays frequency data from the barcode scanline
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Analyze barcode signal quality
|
||||
- Debug decoding issues at the signal level
|
||||
- Understand why certain barcodes fail to decode
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
decoder: {
|
||||
debug: {
|
||||
showFrequency: true
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
#### `decoder.debug.showPattern` {#decoder-debug-showpattern}
|
||||
|
||||
**What it shows**: Displays the pattern data extracted from the barcode
|
||||
|
||||
**When to use**:
|
||||
|
||||
- Analyze pattern recognition issues
|
||||
- Debug specific barcode format problems
|
||||
- Understand pattern extraction process
|
||||
|
||||
**How to enable**:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
decoder: {
|
||||
debug: {
|
||||
showPattern: true
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
## Common Debugging Scenarios {#common-debugging-scenarios}
|
||||
|
||||
### "No barcodes detected" {#no-barcodes-detected}
|
||||
|
||||
Enable console logging first, then add visual overlays if needed:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
inputStream: {
|
||||
target: document.querySelector('#scanner'),
|
||||
debug: {
|
||||
showImageDetails: true
|
||||
}
|
||||
},
|
||||
decoder: {
|
||||
readers: ["code_128_reader"],
|
||||
debug: {
|
||||
printReaderInfo: true,
|
||||
drawBoundingBox: true, // Visual: see if barcode is located
|
||||
drawScanline: true // Visual: see scan path
|
||||
}
|
||||
},
|
||||
locator: {
|
||||
debug: {
|
||||
showPatchSize: true,
|
||||
showImageDetails: true,
|
||||
showFoundPatches: true // Visual: see candidate patches
|
||||
}
|
||||
}
|
||||
}, function(err) {
|
||||
if (err) {
|
||||
console.error("Init error:", err);
|
||||
return;
|
||||
}
|
||||
console.log("Starting Quagga...");
|
||||
Quagga.start();
|
||||
});
|
||||
```
|
||||
|
||||
Check console for:
|
||||
|
||||
- ✅ Readers registered correctly?
|
||||
- ✅ Images loading?
|
||||
- ✅ Patch size reasonable (not 0x0)?
|
||||
- ✅ Canvas contexts created?
|
||||
|
||||
Check canvas overlay for:
|
||||
|
||||
- ✅ Are patches being detected? (green highlights)
|
||||
- ✅ Is a bounding box drawn?
|
||||
- ✅ Is the scanline visible and passing through the barcode?
|
||||
|
||||
### "Camera not working" {#camera-not-working}
|
||||
|
||||
Enable input stream debugging:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
inputStream: {
|
||||
type: "LiveStream",
|
||||
debug: {
|
||||
showImageDetails: true // Shows camera/canvas setup
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
### "Wrong barcode type detected" {#wrong-barcode-type}
|
||||
|
||||
Enable reader info to verify configuration:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
decoder: {
|
||||
readers: [
|
||||
"code_128_reader", // Did you enable the right readers?
|
||||
"ean_reader"
|
||||
],
|
||||
debug: {
|
||||
printReaderInfo: true // Shows which readers are active
|
||||
}
|
||||
},
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
### "Deep-dive localization debugging" {#deep-dive-debugging}
|
||||
|
||||
For advanced debugging of the localization algorithm, enable all visual overlays:
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
locator: {
|
||||
debug: {
|
||||
showCanvas: true,
|
||||
showPatches: true,
|
||||
showFoundPatches: true,
|
||||
showSkeleton: true,
|
||||
showLabels: true,
|
||||
showPatchLabels: true,
|
||||
showRemainingPatchLabels: true,
|
||||
boxFromPatches: {
|
||||
showTransformed: true,
|
||||
showTransformedBox: true,
|
||||
showBB: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}, function(err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
Quagga.start();
|
||||
});
|
||||
```
|
||||
|
||||
This will display every step of the localization process visually on the canvas. Use this to:
|
||||
|
||||
- Understand the complete localization pipeline
|
||||
- Optimize patch size and thresholds
|
||||
- Debug complex barcode positioning issues
|
||||
- Learn how the algorithm works
|
||||
|
||||
**Warning**: Enabling all visual overlays may impact performance and make the canvas cluttered. Enable only what you need.
|
||||
|
||||
## Performance Impact {#performance-impact}
|
||||
|
||||
Debug flags have varying performance impacts:
|
||||
|
||||
**Console logging flags** (minimal impact):
|
||||
|
||||
- `showImageDetails`, `printReaderInfo`, `showPatchSize` - negligible overhead
|
||||
- Only execute when enabled and only in development builds
|
||||
|
||||
**Visual canvas overlays** (moderate to high impact):
|
||||
|
||||
- Drawing operations on canvas can slow down real-time detection
|
||||
- More overlays = more draw calls = slower performance
|
||||
- Consider disabling in production or using only for development/debugging
|
||||
|
||||
**Performance analysis flags** (high impact):
|
||||
|
||||
- `showFrequency`, `showPattern` - can generate large amounts of data
|
||||
- Best used sparingly when diagnosing specific decoding issues
|
||||
|
||||
**Recommendation**: Enable only the flags you need. Disable all visual overlays for production.
|
||||
|
||||
## Disabling Debug Output {#disabling-debug-output}
|
||||
|
||||
To turn off all debug output, either:
|
||||
|
||||
**Option 1**: Remove debug properties entirely
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
inputStream: {
|
||||
// debug property removed
|
||||
},
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
**Option 2**: Set flags to `false`
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
inputStream: {
|
||||
debug: {
|
||||
showImageDetails: false
|
||||
}
|
||||
},
|
||||
decoder: {
|
||||
debug: {
|
||||
printReaderInfo: false,
|
||||
drawBoundingBox: false,
|
||||
drawScanline: false,
|
||||
showFrequency: false,
|
||||
showPattern: false
|
||||
}
|
||||
},
|
||||
locator: {
|
||||
debug: {
|
||||
showCanvas: false,
|
||||
showPatches: false,
|
||||
showFoundPatches: false,
|
||||
showSkeleton: false,
|
||||
showLabels: false,
|
||||
showPatchLabels: false,
|
||||
showRemainingPatchLabels: false,
|
||||
showPatchSize: false,
|
||||
showImageDetails: false,
|
||||
boxFromPatches: {
|
||||
showTransformed: false,
|
||||
showTransformedBox: false,
|
||||
showBB: false
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Using in Node.js {#using-in-nodejs}
|
||||
|
||||
Debug flags work in Node.js too! Output goes to `console.log`:
|
||||
|
||||
```javascript
|
||||
const Quagga = require('@ericblade/quagga2').default;
|
||||
|
||||
Quagga.decodeSingle({
|
||||
src: './barcode.jpg',
|
||||
decoder: {
|
||||
readers: ['code_128_reader'],
|
||||
debug: {
|
||||
printReaderInfo: true // Shows reader registration
|
||||
}
|
||||
}
|
||||
}, (result) => {
|
||||
// Check console for debug output
|
||||
if (result) {
|
||||
console.log('Decoded:', result.codeResult.code);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Development vs Production {#development-vs-production}
|
||||
|
||||
**Development builds** (`dist/quagga.js` or when using webpack dev server):
|
||||
|
||||
- Debug flags work
|
||||
- Console output visible
|
||||
- Larger file size
|
||||
|
||||
**Production builds** (`dist/quagga.min.js`):
|
||||
|
||||
- Debug flags are stripped out (no-op)
|
||||
- No console output
|
||||
- Smaller file size
|
||||
|
||||
To enable debug output in production:
|
||||
|
||||
1. Use the development build (`quagga.js` instead of `quagga.min.js`)
|
||||
2. Set `ENV.development = true` before importing Quagga
|
||||
|
||||
## Summary {#summary}
|
||||
|
||||
Quagga2 provides **19 debug flags** organized into three categories:
|
||||
|
||||
**Console logging** (4 flags) - Minimal performance impact:
|
||||
|
||||
- `inputStream.debug.showImageDetails` - Frame grabber and image loading
|
||||
- `decoder.debug.printReaderInfo` - Reader registration
|
||||
- `locator.debug.showPatchSize` - Patch dimensions
|
||||
- `locator.debug.showImageDetails` - Canvas initialization
|
||||
|
||||
**Visual canvas overlays** (13 flags) - Moderate to high performance impact:
|
||||
|
||||
- `decoder.debug.drawBoundingBox` - Barcode location box
|
||||
- `decoder.debug.drawScanline` - Scan path
|
||||
- `locator.debug.showCanvas` - Locator's internal canvas
|
||||
- `locator.debug.showPatches` - All extracted patches
|
||||
- `locator.debug.showFoundPatches` - Candidate patches
|
||||
- `locator.debug.showSkeleton` - Skeleton structure
|
||||
- `locator.debug.showLabels` - Component labels
|
||||
- `locator.debug.showPatchLabels` - Patch labels
|
||||
- `locator.debug.showRemainingPatchLabels` - Post-filter labels
|
||||
- `locator.debug.boxFromPatches.showTransformed` - Transformed coordinates
|
||||
- `locator.debug.boxFromPatches.showTransformedBox` - Transformed box
|
||||
- `locator.debug.boxFromPatches.showBB` - Final bounding box
|
||||
|
||||
**Performance analysis** (2 flags) - High impact:
|
||||
|
||||
- `decoder.debug.showFrequency` - Signal frequency data
|
||||
- `decoder.debug.showPattern` - Pattern extraction data
|
||||
|
||||
**Debugging strategy**: Start with console logging flags, then add visual overlays as needed. Disable all flags in production.
|
||||
|
||||
## Related {#related}
|
||||
|
||||
- [Configuration Reference](../reference/configuration.md) - Complete config documentation
|
||||
- [Optimize Performance](optimize-performance.md) - Speed up barcode detection
|
||||
- [Handle Difficult Barcodes](handle-difficult-barcodes.md) - Improve detection accuracy
|
||||
|
||||
## Changelog {#changelog}
|
||||
|
||||
**v1.8.4+** (November 2025): Debug flags introduced to replace always-on console spam
|
||||
|
||||
Prior versions logged debug information unconditionally, making it difficult to debug application code. The new flag system provides fine-grained control over diagnostic output.
|
||||
|
||||
---
|
||||
|
||||
**Questions?** Ask in [Gitter Chat](https://gitter.im/quaggaJS/Lobby) or [open an issue](https://github.com/ericblade/quagga2/issues).
|
||||
@@ -0,0 +1,254 @@
|
||||
# Working with Box Coordinates {#working-with-box-coordinates}
|
||||
|
||||
This guide explains how Quagga2's coordinate system works and how to properly use `box`, `boxes`, and `line` coordinates for overlay rendering, especially when using `inputStream.size` to scale processing.
|
||||
|
||||
## Understanding the Coordinate System {#understanding-coordinate-system}
|
||||
|
||||
Quagga2 returns `box`, `boxes`, and `line` coordinates in **processed canvas coordinates**, not original image/video coordinates. This is important to understand when:
|
||||
|
||||
- Drawing overlay boxes on a video element
|
||||
- Using `inputStream.size` to reduce processing resolution
|
||||
- Cropping detected barcode regions from the original image
|
||||
|
||||
### Key Concepts {#key-concepts}
|
||||
|
||||
| Term | Description |
|
||||
|------|-------------|
|
||||
| **Real Size** | The actual dimensions of the source image/video |
|
||||
| **Processed Size** | The scaled dimensions used for barcode detection (controlled by `inputStream.size`) |
|
||||
| **Canvas Size** | The dimensions of the processing canvas (typically matches processed size) |
|
||||
|
||||
### How Coordinates are Generated {#how-coordinates-generated}
|
||||
|
||||
1. **Image Scaling**: When `inputStream.size` is set, the image is scaled so the longest side equals that value
|
||||
2. **Localization**: Barcode regions are found in the scaled image
|
||||
3. **Box Coordinates**: Returned coordinates are relative to the scaled/processed image
|
||||
4. **halfSample Adjustment**: If `halfSample: true`, coordinates are automatically scaled 2x
|
||||
|
||||
## Converting Coordinates to Original Image Space {#converting-coordinates}
|
||||
|
||||
When you need to draw boxes on the original video/image (not the processed canvas), you must scale the coordinates.
|
||||
|
||||
### For Live Video Streams {#live-video-streams}
|
||||
|
||||
```javascript
|
||||
Quagga.onDetected(function(result) {
|
||||
if (!result.box) return;
|
||||
|
||||
// Get the video element
|
||||
const video = document.querySelector('video');
|
||||
const videoWidth = video.videoWidth; // Real video dimensions
|
||||
const videoHeight = video.videoHeight;
|
||||
|
||||
// Get processed dimensions from Quagga
|
||||
const canvas = Quagga.canvas.dom.image;
|
||||
const processedWidth = canvas.width;
|
||||
const processedHeight = canvas.height;
|
||||
|
||||
// Calculate scale factors
|
||||
const scaleX = videoWidth / processedWidth;
|
||||
const scaleY = videoHeight / processedHeight;
|
||||
|
||||
// Convert box coordinates to video space
|
||||
const scaledBox = result.box.map(function(point) {
|
||||
return [
|
||||
point[0] * scaleX,
|
||||
point[1] * scaleY
|
||||
];
|
||||
});
|
||||
|
||||
// Now use scaledBox for drawing on video overlay
|
||||
drawBoxOnVideo(scaledBox);
|
||||
});
|
||||
```
|
||||
|
||||
### For Static Images with decodeSingle {#static-images-decodesingle}
|
||||
|
||||
```javascript
|
||||
Quagga.decodeSingle({
|
||||
src: './barcode.jpg',
|
||||
inputStream: {
|
||||
size: 800 // Process at 800px max dimension
|
||||
},
|
||||
// ... other config
|
||||
}, function(result) {
|
||||
if (!result || !result.box) return;
|
||||
|
||||
// Load original image to get real dimensions
|
||||
const img = new Image();
|
||||
img.onload = function() {
|
||||
const realWidth = img.naturalWidth;
|
||||
const realHeight = img.naturalHeight;
|
||||
|
||||
// Calculate what the processed size was
|
||||
const aspectRatio = realWidth / realHeight;
|
||||
let processedWidth, processedHeight;
|
||||
|
||||
if (aspectRatio > 1) {
|
||||
// Landscape: width is the longest side
|
||||
processedWidth = 800;
|
||||
processedHeight = Math.floor(800 / aspectRatio);
|
||||
} else {
|
||||
// Portrait: height is the longest side
|
||||
processedHeight = 800;
|
||||
processedWidth = Math.floor(800 * aspectRatio);
|
||||
}
|
||||
|
||||
// Calculate scale factors
|
||||
const scaleX = realWidth / processedWidth;
|
||||
const scaleY = realHeight / processedHeight;
|
||||
|
||||
// Convert coordinates
|
||||
const scaledBox = result.box.map(function(point) {
|
||||
return [
|
||||
point[0] * scaleX,
|
||||
point[1] * scaleY
|
||||
];
|
||||
});
|
||||
|
||||
// Use scaledBox for original image operations
|
||||
cropBarcodeFromOriginal(scaledBox);
|
||||
};
|
||||
img.src = './barcode.jpg';
|
||||
});
|
||||
```
|
||||
|
||||
## Complete Example: Drawing Boxes on Live Video {#complete-example}
|
||||
|
||||
Here's a complete example showing how to draw accurate bounding boxes on a live video stream:
|
||||
|
||||
```javascript
|
||||
// Initialize Quagga with reduced processing size for performance
|
||||
Quagga.init({
|
||||
inputStream: {
|
||||
name: "Live",
|
||||
type: "LiveStream",
|
||||
target: document.querySelector('#scanner-container'),
|
||||
constraints: {
|
||||
width: 1280,
|
||||
height: 720,
|
||||
facingMode: "environment"
|
||||
},
|
||||
size: 640 // Process at 640px for better performance
|
||||
},
|
||||
locator: {
|
||||
patchSize: "medium",
|
||||
halfSample: true
|
||||
},
|
||||
decoder: {
|
||||
readers: ["code_128_reader", "ean_reader"]
|
||||
}
|
||||
}, function(err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
Quagga.start();
|
||||
});
|
||||
|
||||
// Handle detections with coordinate scaling
|
||||
Quagga.onDetected(function(result) {
|
||||
const video = document.querySelector('video');
|
||||
const overlay = document.querySelector('#overlay-canvas');
|
||||
const ctx = overlay.getContext('2d');
|
||||
|
||||
// Match overlay to video size
|
||||
overlay.width = video.videoWidth;
|
||||
overlay.height = video.videoHeight;
|
||||
|
||||
// Get processed canvas size
|
||||
const processedCanvas = Quagga.canvas.dom.image;
|
||||
|
||||
// Calculate scale factors
|
||||
const scaleX = video.videoWidth / processedCanvas.width;
|
||||
const scaleY = video.videoHeight / processedCanvas.height;
|
||||
|
||||
// Clear previous drawings
|
||||
ctx.clearRect(0, 0, overlay.width, overlay.height);
|
||||
|
||||
// Draw all detected boxes
|
||||
if (result.boxes) {
|
||||
result.boxes.forEach(function(box) {
|
||||
drawScaledBox(ctx, box, scaleX, scaleY, '#00ff00');
|
||||
});
|
||||
}
|
||||
|
||||
// Highlight the successfully decoded box
|
||||
if (result.box) {
|
||||
drawScaledBox(ctx, result.box, scaleX, scaleY, '#ff0000');
|
||||
}
|
||||
});
|
||||
|
||||
function drawScaledBox(ctx, box, scaleX, scaleY, color) {
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineWidth = 2;
|
||||
ctx.beginPath();
|
||||
|
||||
// Scale and draw each point
|
||||
const scaledPoints = box.map(p => [p[0] * scaleX, p[1] * scaleY]);
|
||||
|
||||
ctx.moveTo(scaledPoints[0][0], scaledPoints[0][1]);
|
||||
for (let i = 1; i < scaledPoints.length; i++) {
|
||||
ctx.lineTo(scaledPoints[i][0], scaledPoints[i][1]);
|
||||
}
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
}
|
||||
```
|
||||
|
||||
## When Coordinates Don't Need Scaling {#no-scaling-needed}
|
||||
|
||||
If you're drawing on Quagga's own overlay canvas (`Quagga.canvas.dom.overlay`), coordinates are already in the correct space:
|
||||
|
||||
```javascript
|
||||
Quagga.onDetected(function(result) {
|
||||
const ctx = Quagga.canvas.ctx.overlay;
|
||||
const canvas = Quagga.canvas.dom.overlay;
|
||||
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// No scaling needed - coordinates match the overlay canvas
|
||||
if (result.box) {
|
||||
Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, ctx, {
|
||||
color: "#00ff00",
|
||||
lineWidth: 2
|
||||
});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Common Pitfalls {#common-pitfalls}
|
||||
|
||||
### 1. Forgetting halfSample Adjustment {#forgetting-halfsample}
|
||||
|
||||
If you're manually calculating processed size, remember that `halfSample: true` doesn't affect the returned coordinates (they're already adjusted).
|
||||
|
||||
### 2. Using Wrong Canvas Reference {#wrong-canvas-reference}
|
||||
|
||||
```javascript
|
||||
// ❌ Wrong - using overlay canvas for scale calculation
|
||||
const wrongWidth = Quagga.canvas.dom.overlay.width;
|
||||
|
||||
// ✅ Correct - using image canvas for scale calculation
|
||||
const correctWidth = Quagga.canvas.dom.image.width;
|
||||
```
|
||||
|
||||
### 3. Assuming Square Pixels {#assuming-square-pixels}
|
||||
|
||||
Always calculate scaleX and scaleY separately, as aspect ratios may differ:
|
||||
|
||||
```javascript
|
||||
// ❌ Wrong - using single scale factor
|
||||
const scale = videoWidth / canvasWidth;
|
||||
|
||||
// ✅ Correct - separate scale factors
|
||||
const scaleX = videoWidth / canvasWidth;
|
||||
const scaleY = videoHeight / canvasHeight;
|
||||
```
|
||||
|
||||
## Performance Tips {#performance-tips}
|
||||
|
||||
1. **Use smaller `inputStream.size`** (e.g., 640-800) for live video to reduce CPU usage
|
||||
2. **Cache scale factors** - recalculate only when video dimensions change
|
||||
3. **Use requestAnimationFrame** for smooth overlay rendering
|
||||
4. **Consider using Quagga's built-in overlay** when possible to avoid manual scaling
|
||||
Reference in New Issue
Block a user