You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

在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:

1. Use a QR Detection Library (Don’t Reinvent the Wheel)

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.

2. Set Up ZXing.Net in Your Project
  • 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 Assets folder. You’ll only need the core ZXing and ZXing.QrCode assemblies for this task.
3. Capture WebCam Data and Extract Position Patterns

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();
        }
    }
}
4. Key Notes to Avoid Headaches
  • Coordinate Spaces: The ResultPoints return coordinates in the webcam texture’s space (0,0 is top-left or bottom-left depending on the device). Use the AdjustForVideoRotation method 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.
5. If You Insist on Building It From Scratch

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 WebCamTexture pixels 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

火山引擎 最新活动