主要内容

本地化和读取多个条形码图像

这个例子展示了如何使用readBarcode从计算机视觉的工具箱™函数来检测和解码一维、二维条形码的形象。条形码广泛用于编码数据视觉、机器可读的格式。他们是有用的在许多应用,如项目识别、仓库库存跟踪和合规跟踪。一维条形码的readBarcode函数返回的位置条码端点。对于二维条形码,函数返回的位置搜索模式。这个示例使用两种方法对本地化多个条形码图像。一种方法是clustering-based,更健壮的不同成像条件和需要统计和机器学习的工具箱™。第二种方法使用一个有效的工作流程和可能需要基于成像条件参数调优。

条形码检测使用readBarcode函数

从图像读取QR码。

我= imread (“barcodeQR.jpg”);%二维码搜索图像。(味精,~,loc) = readBarcode(我);%注释的图像解码的信息。xyText = loc (2);Imsg = insertText(我xyText、味精、“BoxOpacity”,1“字形大小”25);%仪模式位置插入了圈。Imsg = insertShape (Imsg,“实心圆”疯狂的,repmat(10、长度(loc), 1)),“颜色”,“红色”,“不透明度”1);%显示图象。imshow (Imsg)

图包含一个坐标轴对象。坐标轴对象包含一个类型的对象的形象。

从图像读取一维条码。

我= imread (“barcode1D.jpg”);%读了一维条形码和确定格式. .(味精、格式、loc) = readBarcode(我);%显示检测到的信息和格式。disp (“发现格式和消息:“+格式+”、“+味精)
发现格式和消息:EAN-13, 1234567890128
%插入一行显示条码的扫描行。:xyBegin = loc (1);imSize =大小(I);我= insertShape (,“行”[1 xyBegin (2) imSize (2) xyBegin (2)),“线宽”7);%插入标记在条形码的位置。我= insertShape (,“实心圆”(locrepmat(10、长度(loc), 1)),“颜色”,“红色”,“不透明度”1);%显示图象。imshow(我)

图包含一个坐标轴对象。坐标轴对象包含一个类型的对象的形象。

提高条形码检测

对于一个成功的检测,条形码必须清晰可见。条形码必须是紧密地结合起来,尽可能的水平或垂直位置。的readBarcode函数本质上是更健壮的为二维旋转矩阵码比一维或线性条形码。例如,条形码不能被发现在这个形象。

我= imread (“rotated1DBarcode.jpg”);%显示图像。imshow(我)

图包含一个坐标轴对象。坐标轴对象包含一个类型的对象的形象。

%通过图像readBarcode函数。readBarcode(我)
ans = " "

使用旋转图像imrotate条形码是大致水平。使用readBarcode在旋转图像。

% 30度的图像顺时针旋转。Irot = imrotate(我-30);%显示旋转图像。imshow (Irot)

图包含一个坐标轴对象。坐标轴对象包含一个类型的对象的形象。

%通过旋转图像readBarcode函数。readBarcode (Irot)
ans = " 012345678905 "

检测多个条形码

readBarcode功能检测只有一个条形码在每个图像。为了检测多个条形码,你必须指定一个区域(ROI)。指定一个ROI,您可以使用drawrectangle功能交互地确定roi。您还可以使用图像分析技术检测图像中多个条形码的ROI。

交互地确定roi

我= imread (“multiple1DBarcodes.jpg”);

使用drawrectangle函数来绘制并获得矩形参数。

roi1 = drawrectangle;

pos = roi1.Position;

使用drawrectangle %获得roi投资回报率= (180 100 330 180 180 320 330 180 180 550 330 180);imSize =大小(I);i = 1:尺寸(roi, 1)(味精、格式、loc) = readBarcode(我,roi(我,:));disp (“解码格式和消息:“+格式+”、“+味精)%插入一行表示条码的扫描行。:xyBegin = loc (1);我= insertShape (,“行”[1 xyBegin (2) imSize (2) xyBegin (2)),“线宽”5);%注释图像解码消息。我= insertText(我,xyBegin、味精、“BoxOpacity”,1“字形大小”,20);结束
解码格式和消息:UPC-A, 012345678905解码格式和消息:EAN-13, 4567891324562解码格式和消息:39码,abc - 123
imshow(我)

图包含一个坐标轴对象。坐标轴对象包含一个类型的对象的形象。

图像分析来确定roi

使用图像分析技术来自动检测多个条形码。这需要本地化多个条形码图像,确定他们的取向,取向和纠正。没有预处理,条形码不能检测到图像中包含多个旋转条形码。

我= imread (“multiple1DBarcodesRotated.jpg”);Igray = im2gray(我);%显示图像。imshow(我)

图包含一个坐标轴对象。坐标轴对象包含一个类型的对象的形象。

%通过readBarcode函数未处理的图像。readBarcode (Igray“一维”)
ans = " "

检测未处理的图像导致没有检测。

步骤1:使用ms检测条形码的候选区域

检测图像中感兴趣的区域使用detectMSERFeatures函数。然后,您可以消除地区感兴趣的基于一个特定的标准,如长宽比。您可以使用二进制图像过滤结果的进一步处理。

%检测女士特性。[~,cc] = detectMSERFeatures (Igray);%计算区域属性MajorAxisLength和MinorAxisLength。regionStatistics = regionprops (cc、“MajorAxisLength”,“MinorAxisLength”);%过滤组件有一个低的长宽比是不合适的%的候选人在条形码的酒吧。minAspectRatio = 10;candidateRegions =找到(((regionStatistics.MajorAxisLength)。/ [regionStatistics.MinorAxisLength]) > minAspectRatio);%二进制映像存储过滤组件。BW = false(大小(Igray));%更新二进制图像。i = 1:长度(candidateRegions) BW (cc.PixelIdxList {candidateRegions (i)}) = true;结束%显示二进制图像与过滤组件。imshow (BW)标题(“条形码”候选区域)

图包含一个坐标轴对象。条形码的坐标轴对象与标题候选区域包含一个类型的对象的形象。

步骤2:使用霍夫变换提取条码线段

检测突出边缘图像中使用边缘函数。然后使用霍夫变换找到感兴趣的线。垂直的线表示可能的候选人酒吧的条形码。

%进行霍夫变换。BW =边缘(BW,“精明”);[H T R] =踝关节(BW);%显示边缘检测操作的结果。imshow (BW)

图包含一个坐标轴对象。坐标轴对象包含一个类型的对象的形象。

%确定抑制邻域的大小。reductionRatio = 500;nhSize =地板(大小(H) / reductionRatio);idx =国防部(nhSize, 2) < 1;nhSize (idx) = nhSize (idx) + 1;%确定霍夫变换的山峰。P = houghpeaks (H,长度(candidateRegions),“NHoodSize”,nhSize);%根据检测到的峰值检测行。行= houghlines (BW T R P);%显示行发现使用houghlines函数。Ihoughlines = 1(大小(BW));%检测到线的开始点和结束点。startPts =重塑(((:行)。point1), 2、长度()行)';endPts =重塑(((:行)。卷帘窗),2、长度()行)';Ihoughlines = insertShape (Ihoughlines,“行”(startPts endPts),“线宽”2,“颜色”,“绿色”);%显示检测到的原始图像显示行。Ibarlines = imoverlay(我~ Ihoughlines (:,: 1));imshow (Ibarlines)

图包含一个坐标轴对象。坐标轴对象包含一个类型的对象的形象。

步骤3:定位条形码图像

提取线段后,提出了两种方法对本地化的个人条形码图片:

  • 方法1:clustering-based从统计和机器学习技术,使用功能工具箱™来识别个人的条形码。这种技术更健壮的异常值检测使用上面的图像分析技术。它还可以扩展到广泛的成像条件无需调整参数。

  • 方法2:一个有效的工作流程将个人的条形码。该方法使用其他图像分析技术来定位和旋转正确提取的条形码。虽然这工作很好,但可能需要一些参数调优,以防止检测离群值。

方法1:集群基于工作流

在这个工作流程有两个步骤:

1。确定条形码线段等分线

虽然是常见的做法直接使用线(这是使用霍夫变换)获得定位条形码,该方法使用行进一步检测垂直平分线的线。平分线行表示为点在笛卡尔空间中,这使得它们适合识别个体的条形码。使用个人的平分线使检测条形码更加健壮,因为它会导致更少的错误分类的线相似但属于不同的条形码。

2。执行集群的平分线标识个人条形码

因为所有的酒吧在条形码约相互平行,每个酒吧的平分线应该是相同的,和他们的对应点应围绕一个单点。在实践中,这些等分线将不同段段,但仍然足以允许使用density-based相似聚类算法。执行此聚类操作的结果是一组集群,每个点到一个单独的条形码。下面的例子使用了dbscan(统计和机器学习的工具箱)函数,它不需要先验知识集群的数量。不同的集群(条形码)在本例中可视化。

示例检查统计和机器学习工具箱™许可证。如果找到一个许可,使用聚类方法的例子。否则,这个例子使用了分割方法。

useClustering =许可证(“测试”,“statistics_toolbox”);如果,边界框(useClustering(大小)取向,Iclusters] = clusteringLocalization(线条、大小(I));%显示检测到集群。imshow (Iclusters)其他的disp (“基于聚类的工作流程需要一个许可证的统计和机器学习工具箱”)结束

图包含一个坐标轴对象。坐标轴对象包含一个类型的对象的形象。

方法2:分割基于工作流

去除背景噪声和变异后,发现垂直酒吧使用形态学操作,分为个人条形码imdilate。这个例子使用了regionprops函数来确定边界框和取向的条形码。结果用于作物个体从原始图像和条形码东方大致水平。

如果,边界框(~ useClustering(大小)取向,Idilated] = segmentationLocalization (Ihoughlines);%显示扩张的形象。imshow (Idilated)结束

步骤4:作物条形码和纠正他们的旋转

条形码从原始图像裁剪使用边界框获得的分割。定位结果用于对齐条形码大约水平。

%本地化和旋转的条形码图像。correctedImages =细胞(1、长度(方向));%存储条形码的裁剪和旋转校正图像。i = 1:长度(方向)i = insertShape(我“矩形”(我:),边界框(,大小)“线宽”3,“颜色”,“红色”);如果方向(i) > 0取向(i) = -(90 -取向(i));其他的方向(i) = 90 +方向(我);结束%作物的条码使用的原始图像和旋转它%检测方向。correctedImages{我}= imrotate (imcrop((我,:))边界框(Igray,大小),取向(我));结束%显示图像局部的条形码。imshow(我)

图包含一个坐标轴对象。坐标轴对象包含一个类型的对象的形象。

第五步:检测条形码在裁剪和旋转校正图像

条形码的裁剪和旋转校正图像使用的readBarcode函数来解码它们。

%通过readBarcode函数的每个图像。i = 1:长度(correctedImages)(味精,格式,~)= readBarcode (correctedImages {},“一维”);disp (“解码格式和消息:“+格式+”、“+味精)结束
解码格式和消息:UPC-A, 012345678905解码格式和消息:EAN-13, 4567891324562解码格式和消息:39码,abc - 123

这个例子显示了readBarcode函数可以用来探测、解码和本地化条形码图像。而功能运行良好的对齐条形码大概是水平或垂直,条形码出现旋转的时候需要额外的预处理。上面的预处理步骤详细的工作是一个好的起点与多个条形码不一致在一个图像。

万博1manbetx支持功能

clusteringLocalization使用clustering-based工作流本地化个人条形码。

函数,边界框((大小)取向,Iclusters] = clusteringLocalization(线、imSize)% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -%确定条形码线段等分线% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -%表来存储检测线路的平分线的性质。linesBisector = array2table(0(长度(行),4),“VariableNames”,{“θ”,的ρ,“x”,“y”});%使用方向值的线来确定方向。%的平分线值idxNeg =找到([行。θ)< 0);idxPos =找到([行。θ)> = 0);negAngles = 90 +(线(idxNeg) .theta);linesBisector.theta (idxNeg) = negAngles;posAngles = [(idxPos行)。θ]- 90;linesBisector.theta (idxPos) = posAngles;%确定检测到线的中点。midPts = 0(长度(行),2);%确定的‘ρ值平分线。i = 1:长度()行midPts(我:)= ((i)行。point1 +(我).point2行)/ 2;linesBisector.rho (i) = abs (midPts(我,2),罐内((我).theta行)* midPts(我,1))/((罐内((我).theta行)^ 2 + 1)^ 0.5);结束%更新(x, y)等分线的位置使用他们的极性%的坐标。[linesBisector。x, linesBisector。函数y] = pol2cart (linesBisector.theta), linesBisector.rho,“罗”);% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -%对等分线执行集群标识个人条形码% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -%的存储(x, y)数据平分线用于集群。X = [linesBisector.x linesBisector.y];%得到成对的点之间的距离D = pdist2 (X, X);%执行density-based空间聚类分离的不同%的条形码图像。searchRadius = max (imSize / 5);minPoints = 10;idx = dbscan (D, searchRadius minPoints);%确定集群的数量(条形码)。numClusters =独特(idx (idx > 0));%的存储端点检测线路。dataXY =细胞(1、长度(numClusters));%的图像显示检测到集群(条形码)。Iclusters = 1 (imSize);i = 1:长度(numClusters) classIdx =找到(idx = =我);rgbColor =兰德(1、3);startPts =重塑(((classIdx行)。point1), 2、长度(classIdx));endPts =重塑(((classIdx行)。卷帘窗),2、长度(classIdx));%插入行对应于当前集群(条形码)。Iclusters = insertShape (Iclusters,“行”(startPts endPts),“线宽”2,“颜色”,rgbColor);%更新在每个集群的端点(条形码)。dataXY{我}= [startPts;endPts];结束% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -%的条码定位参数% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -取向= 0(1、长度(numClusters));boundingBox = 0(长度(numClusters), 4);%填充条形码的裁剪图像。填充= 40;%确定ROI和个人取向集群(条形码)。i = 1:长度(numClusters)%边界框坐标与填充。x1 = min (dataXY{我}(:1))-填充;x2 = max (dataXY{我}(:1))+填充;日元= min (dataXY{我}(:,2))-填充;y2 = max (dataXY{我}(:,2))+填充;boundingBox(我:)= (x1, y1, x2-x1 y2-y1);%取向的条形码。方向(i) = (linesBisector意思。θ(idx = =我));结束结束

segmentationLocalization使用一个有效的工作流程本地化个人条形码。

函数,边界框((大小)取向,Idilated] = segmentationLocalization (Ihoughlines)% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -%使用条形码图像膨胀分离% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -%创建二进制图像检测线路。Ibw = ~ Ihoughlines (:: 1);Ibw (Ibw > 0) = true;%扩张图像使用磁盘结构元素。diskRadius = 10;%根据输入图像可能需要调优。se = strel (“磁盘”,diskRadius);Idilated = imdilate (Ibw, se);% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -%的条码定位参数% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -%计算区域属性。边界框(方向和大小)regionStatistics = regionprops (Idilated,“定位”,的边界框(“大小));%裁剪图像填充的条形码。填充= 40;boundingBox = 0(长度(regionStatistics), 4);(边界框(idx = 1:长度(regionStatistics)大小):idx) = regionStatistics (idx) .BoundingBox;%边界框坐标与填充。boundingBox (idx, 1) (idx 1)填充边界框(=大小);(边界框(boundingBox (idx 2) =大小)idx, 2)——填充;(边界框(boundingBox (idx 3) =大小)idx, 3) + 2 *填充;(边界框(boundingBox (idx 4) =大小)idx, 4) + 2 *填充;结束取向= [regionStatistics (:) .Orientation];结束

引用

[1]Creusot、克莱门特、等。“在野外实时条形码检测。”IEEE Winter Conference on Applications of Computer Vision, 2015.