在Unity(C#)中使用ZXing获取QR码Position Pattern坐标的方法
Hey there! Let's break down how to grab those three Position Pattern coordinates from a QR code captured via WebCamTexture in Unity using C#. I've tackled this a few times before, so here's a straightforward, practical approach:
Writing your own QR code position pattern detection from scratch is tedious—you’d have to handle edge detection, contour analysis, and pattern matching, which is easy to mess up. Instead, use ZXing.Net, a popular, Unity-compatible library that already does the heavy lifting and exposes the position pattern data directly.
- Grab the Unity-compatible ZXing.Net package (you can get it via NuGet or the official GitHub releases—just make sure it matches your Unity version).
- Import the package into your project’s
Assetsfolder. You’ll only need the core ZXing and ZXing.QrCode assemblies for this task.
Here’s a complete C# script that captures the webcam feed, decodes the QR code, and pulls out the three position pattern coordinates:
using UnityEngine; using ZXing; using ZXing.QrCode; public class QRCameraPositionDetector : MonoBehaviour { private WebCamTexture _webCamTexture; private BarcodeReader _barcodeReader; void Start() { // Initialize webcam feed WebCamDevice[] availableDevices = WebCamTexture.devices; if (availableDevices.Length > 0) { _webCamTexture = new WebCamTexture(availableDevices[0].name); _webCamTexture.Play(); } // Configure barcode reader for QR code detection _barcodeReader = new BarcodeReader { Options = new QrCodeEncodingOptions { TryHarder = true, // Improves detection for blurry/small QR codes PureBarcode = false, // Critical—disables "pure barcode" mode so we get actual image coordinates Width = _webCamTexture.width, Height = _webCamTexture.height } }; } void Update() { if (_webCamTexture != null && _webCamTexture.didUpdateThisFrame) { // Convert webcam pixels to Color32 format (ZXing's preferred input) Color32[] pixelData = _webCamTexture.GetPixels32(); // Decode the QR code from the pixel data var decodeResult = _barcodeReader.Decode(pixelData, _webCamTexture.width, _webCamTexture.height); if (decodeResult != null) { // Access the three position pattern points var positionPatterns = decodeResult.ResultPoints; if (positionPatterns != null && positionPatterns.Length == 3) { for (int i = 0; i < positionPatterns.Length; i++) { // Get raw texture-space coordinates float textureX = positionPatterns[i].X; float textureY = positionPatterns[i].Y; // Adjust for common webcam quirks (mirroring/rotation) // Fix mirroring (common with front-facing cameras) textureX = _webCamTexture.width - textureX; // Fix rotation if webcam is in portrait mode AdjustForVideoRotation(ref textureX, ref textureY); // Convert texture coordinates to Unity screen space (if needed) Vector2 screenPosition = ConvertTextureToScreenSpace(textureX, textureY); Debug.Log($"Position Pattern {i+1}: Texture X = {textureX:F2}, Texture Y = {textureY:F2} | Screen X = {screenPosition.x:F2}, Screen Y = {screenPosition.y:F2}"); } } } } } // Adjust coordinates for webcam video rotation private void AdjustForVideoRotation(ref float x, ref float y) { switch (_webCamTexture.videoRotationAngle) { case 90: float temp90 = x; x = y; y = _webCamTexture.width - temp90; break; case 270: float temp270 = x; x = _webCamTexture.height - y; y = temp270; break; // 0 and 180 degrees usually don't need adjustment, but add cases if needed } } // Convert texture-space coordinates to Unity screen space private Vector2 ConvertTextureToScreenSpace(float textureX, float textureY) { // Assuming your webcam feed is rendered on a full-screen plane or quad Vector3 worldPos = new Vector3(textureX / _webCamTexture.width, textureY / _webCamTexture.height, 0); return Camera.main.WorldToScreenPoint(worldPos); } void OnDestroy() { if (_webCamTexture != null) { _webCamTexture.Stop(); } } }
- Coordinate Spaces: The
ResultPointsreturn coordinates in the webcam texture’s space (0,0 is top-left or bottom-left depending on the device). Use theAdjustForVideoRotationmethod to fix orientation issues from portrait/landscape switches. - Mirroring: Front-facing cameras almost always mirror the feed, so flipping the X coordinate is essential for accurate positioning.
- Performance: Running QR detection every
Update()can be heavy on mobile. Consider reducing the detection frequency (e.g., run every 2-3 frames) or downscaling the webcam texture if you’re targeting low-end devices.
If you want to skip third-party libraries, here’s the high-level workflow (but I don’t recommend this unless you have a specific reason):
- Convert the
WebCamTexturepixels to a grayscale array. - Apply edge detection (like the Canny algorithm) to find sharp edges.
- Detect square contours and filter for the 7x7 black-white-black pattern that defines QR position markers.
- Calculate the center of each valid marker to get your X/Y coordinates.
This approach requires a lot of image processing code and will likely have more bugs than using a battle-tested library.
Hope this helps you get those position pattern coordinates sorted out smoothly! Let me know if you hit any snags with orientation or library setup.
内容的提问来源于stack exchange,提问作者Isaac Chuang




