【问题标题】:Calculate width of each bar of Barcode in Matlab在Matlab中计算条码每个条的宽度
【发布时间】:2019-10-15 08:05:10
【问题描述】:

我有一个条形码,我想在 matlab 中处理它并计算一维条形码中每个条的宽度(以像素为单位)。

我尝试通过 graythresh 级别将图像转换为灰度,并将其转换为二进制。

%read the image code3
barz=imread('barcode1.jpg');
grayBarz=rgb2gray(barz);

binImage = imbinarize(barz,graythresh(barz));

s = regionprops(binImage == 0,'Area','PixelIdxList');
imshow(barz);

我想要条形码中每个条的宽度(以像素为单位)。

【问题讨论】:

  • 请将barcode1.jpg图片上传到您的问题中。
  • 上传图片供大家参考

标签: matlab image-processing barcode


【解决方案1】:

有时无需完整的图像处理工具箱就能做事很有趣。

下面的解决方案允许您计算每个黑条的像素宽度,而无需任何额外的工具箱:

%% Read the image
barz=imread('barcode.jpg');
grayBarz=rgb2gray(barz);

%% Extract an horizontal line in the middle
sz = size(grayBarz) ;
idxMidLine = round(sz(1)/2) ; % index of a line roughly in the middle
eline = grayBarz(idxMidLine,:) ;    % extract a line
eline(eline<128) = 0 ;              % sharpen transitions
eline = ~logical(eline) ;           % convert to logical (0=white / 1=black)

%% Now count the pixels
npts = numel(eline) ;   % number of points in the line

% Find every transition:
    % high to low   => -1
    % no change     =>  0
    % low to high   => +1
idd = find( diff(eline) ) ;

% this contain the start and end indices of every interval
ddd = [ 1 , idd ; ...
        idd , npts ] ;

% This contains the width of every bar (white and black),
% in order from left to right
barWidth = diff(ddd) ;

if ~eline(1)
    % The first interval is 0 (is white)
    pixBarWhite = barWidth( 1:2:end ) ;
    pixBarBlack = barWidth( 2:2:end ) ;
else
    % The first interval is 1 (is black)
    pixBarBlack = barWidth( 1:2:end ) ;
    pixBarWhite = barWidth( 2:2:end ) ;
end

nBarWhite = numel(pixBarWhite) ;
nBarBlack = numel(pixBarBlack) ;

%% Display results
fprintf('Found a total of %d black pixels along the horizontal,\n',sum(pixBarBlack))
fprintf('spread over %d black bars,\n',nBarBlack)
fprintf('Individual bar pixel thickness:\n')
for k=1:nBarBlack
    fprintf('Bar %02d : Thickness: %02d pixels\n',k,pixBarBlack(k))
end

对于您的图像,它将返回:

Found a total of 599 black pixels along the horizontal,
spread over 49 black bars,
Individual bar pixel thinchness:,
Bar 01 : Thickness: 13 pixels
Bar 02 : Thickness: 07 pixels
Bar 03 : Thickness: 20 pixels
% [edited to keep it short]
Bar 47 : Thickness: 20 pixels
Bar 48 : Thickness: 07 pixels
Bar 49 : Thickness: 13 pixels

请注意,变量pixBarWhite 还包含黑条之间所有白色间隔的像素厚度。以后可能会派上用场...

【讨论】:

    【解决方案2】:

    假设你已经有了bars的regionprops,宽度可以很容易的通过

    'MinFeretProperties'
    

    'MinorAxisLength'
    

    如果您的条形与图像光栅平行,您还可以使用'BoundingBox' 的较小尺寸

    https://de.mathworks.com/help/images/ref/regionprops.html

    【讨论】:

      【解决方案3】:

      为了好玩,这是一个使用 Python OpenCV 的实现

      • 将图像转换为灰度和 Otsu 的阈值
      • 检测所有垂直线并在蒙版上绘制
      • 在蒙版上查找轮廓并从左到右排序
      • 遍历轮廓并找到每条线的像素宽度

      结果

      条码宽度:[13, 7, 20, 27, 7, 19, 12, 13, 13, 7, 6, 13, 20, 7, 14, 7, 6, 12, 20, 7, 13, 27 , 19, 7, 6, 6, 13, 7, 27, 7, 14, 19, 6, 19, 6, 13, 13, 7, 5, 6, 26, 6, 6, 13, 6, 12, 20 , 7, 13]

      条码条数:49

      总像素:599

      代码

      import cv2
      from imutils import contours
      import numpy as np
      
      # Load in image, grayscale, and Otsu's threshold
      image = cv2.imread('1.jpg')
      mask = np.zeros(image.shape, dtype=np.uint8)
      gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
      thresh = cv2.threshold(gray,0,255,cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)[1]
      
      # Detect vertical lines
      vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,80))        
      remove_vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel)
      cnts = cv2.findContours(remove_vertical, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
      cnts = cnts[0] if len(cnts) == 2 else cnts[1]
      cv2.fillPoly(mask, cnts, (255,255,255))
      
      # Find contours on mask and sort from left to right
      mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
      cnts = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
      cnts = cnts[0] if len(cnts) == 2 else cnts[1]
      cnts, _ = contours.sort_contours(cnts, method="left-to-right")
      
      # Iterate through contours and find width of each line
      barcode_width = []
      for c in cnts:
          x,y,w,h = cv2.boundingRect(c)
          current = image.copy()
          cv2.rectangle(current, (x, y), (x + w, y + h), (36,255,12), -1)
          cv2.putText(current, 'Width: {}'.format(w), (15,50), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (36,255,12), 3)
          barcode_width.append(w)
          cv2.imshow('current', current)
          cv2.waitKey(175)
      
      print("Barcode Width:", barcode_width)
      print('Barcode Bars: ', len(barcode_width))
      print('Total Pixels: ', sum(barcode_width))
      cv2.waitKey()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-26
        • 2013-03-04
        • 1970-01-01
        • 1970-01-01
        • 2015-02-16
        • 1970-01-01
        相关资源
        最近更新 更多