在Matlab中计算条形码每条的宽度
Calculate width of each bar of Barcode in Matlab
我有一个条形码,我想在 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);
我想要条形码中每个条的宽度(以像素为单位)。
假设你已经有了bars的regionprops,宽度可以通过
轻松获得
'MinFeretProperties'
或
'MinorAxisLength'
如果您的条形与图像光栅平行,您还可以使用 'BoundingBox'
的较小尺寸
有时候不需要完整的图像处理工具箱。
就可以做事很有趣
下面的解决方案允许您计算每个黑条的像素宽度,而不需要任何额外的工具箱:
%% 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
对于您的图片,它将 return:
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
还包含黑条之间所有白色间隔的像素厚度。以后可能会派上用场...
为了好玩,这里有一个使用 Python OpenCV
的实现
- 将图像转换为灰度和 Otsu 的阈值
- 检测所有垂直线并绘制到遮罩上
- 在蒙版上查找轮廓并从左到右排序
- 遍历轮廓并找到每条线的像素宽度
结果
Barcode Width: [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]
Barcode Bars: 49
Total Pixels: 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()
我有一个条形码,我想在 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);
我想要条形码中每个条的宽度(以像素为单位)。
假设你已经有了bars的regionprops,宽度可以通过
轻松获得'MinFeretProperties'
或
'MinorAxisLength'
如果您的条形与图像光栅平行,您还可以使用 'BoundingBox'
有时候不需要完整的图像处理工具箱。
就可以做事很有趣下面的解决方案允许您计算每个黑条的像素宽度,而不需要任何额外的工具箱:
%% 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
对于您的图片,它将 return:
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
还包含黑条之间所有白色间隔的像素厚度。以后可能会派上用场...
为了好玩,这里有一个使用 Python OpenCV
的实现- 将图像转换为灰度和 Otsu 的阈值
- 检测所有垂直线并绘制到遮罩上
- 在蒙版上查找轮廓并从左到右排序
- 遍历轮廓并找到每条线的像素宽度
结果
Barcode Width: [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]
Barcode Bars: 49
Total Pixels: 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()