C# 中的 ZXing(“斑马线”)

8
我正在寻找一个良好的开源库,可以从图像中查找和读取条形码(而不是使用条形码扫描器)。从 Stack Overflow 上的其他问题中,我发现 ZXing(“斑马线”)非常好。虽然它是为 Java 设计的,但有一个 C# 移植版 - 不过,我认为它可能不完整。你认为它足够可靠以解析这种情况下的条形码,还是有其他更好的库? 编辑:正如 Ed 在评论中指出的那样,我应该先尝试一下。哇,我没有想到。 :) 但我想知道这个部分移植版是否足够可靠 - 如果你们中有人以前用过它,它能够熟练扫描吗?

3
为什么不尝试一下呢?你知道的… - Ed S.
@Ed 哦,嗯,呵呵,你知道的,我想我需要关闭我的问题。糟糕了。 - Maxim Zaslavsky
好的,这个问题本身将来对人们会有用,所以我认为关闭它是不正确的。此外,有些人可能有需要学习时间才能获得的见解,你可能会在第一眼错过它们。我只是建议,在这段时间里,先尝试一下是我的第一个目标。 - Ed S.
是的,我完全同意,谢谢!我会尽快尝试一下。 - Maxim Zaslavsky
3个回答

3

我已经使用了一年以上的Java版本,每天大约扫描100个,效果非常好。我认为C#版本不会差到哪去。


2
当然,这取决于你使用它的目的。即使是zxing的Java版本也存在一些重要的限制和性能问题。例如,它只能在页面上找到一个条形码。此外,它用于定位页面上的1-D条形码的算法并不特别高效(我不知道2-D条形码的算法 - 因为这不是我正在处理的项目要求的部分)。这些都是可以解决的问题 - 我几个月前开始了一个增强功能,并能够显着提高1-D位置性能和可靠性,但我们的开发重点已经转移,所以我从那以后没有继续工作。
至于部分移植到C#是否好,如果您想回复有关差异的信息,我很乐意发表评论。
编辑 - 这是我进行的一些重构:
首先,将RowNumberStrategy因以下原因分解:
public interface RowNumberStrategy {
public int getNextRowNumber();

public class OriginalRowStrategy implements RowNumberStrategy{
    int middle;
    boolean tryHarder = false;
    int rowStep;
    int maxLines;
    int maxRows;

    int x;

    public OriginalRowStrategy(int maxRows, boolean tryHarder) {
        this.x = 0;
        this.maxRows = maxRows;
        this.middle = maxRows >> 1; // divide by 2
        this.tryHarder = tryHarder;
        rowStep = Math.max(1, maxRows >> (tryHarder ? 7 : 4));
        if (tryHarder) {
          maxLines = maxRows; // Look at the whole image, not just the center
        } else {
          maxLines = 9; // Nine rows spaced 1/16 apart is roughly the middle half of the image
        }
    }

    public int getNextRowNumber() {
        if (x > maxLines)
            return -1;

        int rowStepsAboveOrBelow = (x + 1) >> 1;
        boolean isAbove = (x & 0x01) == 0; // i.e. is x even?
        int rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);
        if (rowNumber < 0 || rowNumber >= maxRows) {
          // Oops, if we run off the top or bottom, stop
          return -1;
        }

        x = x + 1;

        return rowNumber;
    }

}

public class LinearScanRowStrategy implements RowNumberStrategy{
    private final int maxRows;
    private int currentRow;
    public LinearScanRowStrategy(int totalRows) {
        maxRows = totalRows;
        currentRow = 0;
    }

    public int getNextRowNumber() {
        if (currentRow > maxRows)
            return -1;

        return maxRows - 1 - currentRow++;
    }

}

public class ProgressiveScanRowStrategy implements RowNumberStrategy{
    private final int maxRows;
    private int currentStepSize;
    private int currentStep;

    public ProgressiveScanRowStrategy(int totalRows) {
        maxRows = totalRows;
        currentStep = 0;
        currentStepSize = maxRows;
    }

    public int getNextRowNumber() {
        int nextRow = (currentStep++) * currentStepSize;
        if (nextRow < maxRows)
            return nextRow;

        currentStepSize = currentStepSize >> 1;
        if (currentStepSize <= 0)
            return -1;
        currentStep = 1;

        nextRow = currentStep * currentStepSize;

        return nextRow;
    }

}



}

那么doDecode的顶部部分将变成如下:

private Result doDecode(MonochromeBitmapSource image, Hashtable hints) throws ReaderException {


int width = image.getWidth();
int height = image.getHeight();
BitArray row = new BitArray(width);
boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
RowNumberStrategy rowProvider = new RowNumberStrategy.ProgressiveScanRowStrategy(height);  

int rowNumber;
while ((rowNumber = rowProvider.getNextRowNumber()) != -1){
...
}

最终,这应该是可以通过DecodeHintType设置的内容,但我们发现在我们能够使用的每种情况下,渐进策略比旧策略更快(而且不仅仅是快一点点,而是快得多)。


尝试使用MultipleBarcodeReader在图像中查找多个条形码。不确定您认为一维检测效率低的原因是什么--它从中心向外扫描几行。如果有什么问题,默认模式快速但肤浅。 - Sean Owen
我一定会去看看MBR - 感谢你的建议。从算法上讲,扫描策略对于大型图像(比如3300行)并不高效,因为它使用了固定的步进方法。我会在完整的帖子中回复我的问题,以便展示代码。 - Kevin Day
不是这样的,扫描步骤是与高度函数相关的--默认情况下,它会在每个步骤跳过图像高度的1/16行。 - Sean Owen
Sean - 是的,高度/16的方法比它需要的要慢得多,并且会错过条形码。上述自适应策略更快,并且可以获取所有大小的条形码。我将在另一个月或两个月内接手这项工作 - 我会给你发送一个补丁。 - Kevin Day

-1
尝试使用ikvmc编译Java版本,然后从您的C#代码中访问它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接