Professional Documents
Culture Documents
Politechniki Białostockiej
Katedra Robotyki i Mechatroniki
SYSTEMY WIZYJNE
Ćwiczenie nr: 3
Białystok 2022
Cel ćwiczenia
Celem ćwiczenia jest stworzenie kompletnego algorytmu analizy i przetwarzania obrazu do
rozpoznawania kodów 1D oraz 2D znajdujących się obiektach umieszczonych na taśmociągu
przemysłowym wykorzystując kamerę Kinect.
1. Wprowadzenie
Kod kreskowy to informacje w postaci cyfr albo liter zawarte w znaku graficznym. Zależnie od
rodzaju kodu kreskowego wyróżniamy: kod 1D (zbudowany z pasków) oraz kod 2D
(zbudowany z kwadracików) np. kody QR. Odczyt polega na rozszyfrowaniu kombinacji
czarnych i białych elementów w symbolu, która odpowiada za konkretne znaki (cyfry i liczby).
Kombinacja określona jest za pomocą szerokości każdej z kresek lub złożoności kwadratów
w zależności od rodzaju kodu kreskowego [1].
Kody jednowymiarowe:
Kody 1D inaczej linearne, opierają się na pionowych, ciemnych oraz jasnych liniach. Procedura
odczytu kodów jednowymiarowych opiera się na określaniu różnic między szerokościami linii
w kodzie kreskowym. Odczyt ten ogranicza się wyłącznie do odczytu poziomego pionowych
linii [2].
Rodzaje kodów 1D:
• EAN – kod typu EAN występuje w dwóch wersjach: EAN – 13 (12 cyfr danych oraz
jedna kontrolna). Kod EAN 13 w USA znany jest także jako UPC. Używany również
w połączeniu z ISSN w magazynach prasowych.
• Kod 39 (Code 39) – kod kreskowy złożony z pasków, który zawiera znaki
alfanumeryczne. Jest zmiennej długości i pozwala zapisać 43 znaki. Każdy znak ma 9
elementów, 3 są znacznie szersze.
• Kod 128 (Code 128) – kod alfanumeryczny o zmiennej długości, który został
opracowany, aby rozszerzyć liczbę znaków do 128.
• Kod przeplatany 2 z 5 (Interleaved 2 of 5) –kod wyłącznie numeryczny o parzystej,
zmiennej długości. Wyróżnia się dużym zagęszczeniem – cyfry kodowane są parami
w „przeplocie” – czarne paski odpowiadają za jedną cyfrę, natomiast białe paski za
drugą.
Kody dwuwymiarowe
Kody 2D pozwalają zmieścić większą ilość informacji niż kody liniowe, ponieważ ich kodowanie
i odczyt odbywa się zarówno pionowo jak i poziomo [2].
Rodzaje kodów 2D:
a) Kamery KINECT
Technologia wykrywania głębi i ruchu stanowiąca podstawę sensora Kinect jest dostępna
dzięki czujnikowi głębi. Oryginalny sensor Kinect v1 (Rys. 2) wykorzystuje w tym celu światło
strukturalne: urządzenie używa wzoru w bliskiej podczerwieni wyświetlanego w przestrzeni
przed sensorem Kinect, podczas gdy czujnik podczerwieni wychwytuje wzór odbitego światła.
Wzór światła jest zniekształcony przez względną głębokość obiektów znajdujących się przed
nim, a do oszacowania tej głębokości można użyć zależności matematycznych związanych
z układem sprzętowym sensora Kinect. Kinect v2 (Rys. 3) używa pomiarów czasu lotu.
Projektor podczerwieni w sensorze Kinect wysyła modulowane światło podczerwone, które
jest następnie przechwytywane przez czujnik. Światło podczerwone odbijające się od bliższych
obiektów będzie miało krótszy czas lotu niż to odbite od elementów bardziej odległych. Czujnik
podczerwieni rejestruje, jak bardzo wzór modulacji został zdeformowany w zależności od
czasu lotu, piksel po pikselu. Pomiary głębokości w czasie lotu mogą być dokładniejsze
i obliczone w krótszym czasie, co pozwala na wykrycie większej liczby klatek na sekundę [3].
3. Przebieg ćwiczenia
Ćwiczenie rozpocząć od dokonania kalibracji wybranego czujnika jakim jest kamera Kinect v1
lub Kinect v2.
Kolejne etapy:
1) Uzyskać podgląd obrazu na żywo;
2) Wykorzystując funkcję readBarcode znaleźć na obrazie kod QR;
msg = readBarcode(I) - wykrywa i dekoduje kod kreskowy 1-D lub 2-D w obrazie
wejściowym i zwraca komunikat skojarzony z tym kodem kreskowym.
Jeśli obraz wejściowy zawiera wiele kodów kreskowych, funkcja readBarcode dekoduje tylko
pierwszy wykryty kod kreskowy.
msg = readBarcode(I,roi) - określa prostokątny obszar zainteresowania (ROI), aby
zmniejszyć obszar, w którym funkcja szuka kodu kreskowego. Obszar zainteresowania ROI
musi być w pełni zawarty w obrazie wejściowym.
msg = readBarcode(___,format) - określa formaty kodów kreskowych w celu
zmniejszenia typów kodów kreskowych, których szuka funkcja. Określ ten argument oprócz
dowolnej kombinacji argumentów wejściowych w poprzednich składniach.
[msg,detectedFormat,loc] - dodatkowo zwraca format, detectFormat i lokalizację loc
wykrytego kodu kreskowego.
3) Dodać adnotację do obrazu za pomocą zdekodowanej wiadomości;
xyText = loc(2,:);
Imsg = insertText(I, xyText, msg, "BoxOpacity", 1, "FontSize", 25);
5) Wyświetlić wynik
W przypadku kodu 1D należy:
• Wyświetlić wynik.
UWAGA:
W celu pomyślnego wykrycia kod kreskowy musi on być widoczny (niczym nie przysłonięty
oraz w polu widzenia kamery). Musi być również jak najbliżej wyrównany do pozycji poziomej
lub pionowej. Funkcja readBarcode jest z natury bardziej odporna na rotacje dla kodów 2-D
lub matrycowych niż dla 1-D lub liniowych kodów kreskowych [3].
Funkcja readBarcode wykrywa tylko jeden kod kreskowy w każdym obrazie. Aby wykryć wiele
kodów kreskowych, trzeba określić region zainteresowania (ROI). Aby określić ROI, można użyć
funkcji Drawrectangle, aby interaktywnie określić ROI. Można także użyć technik analizy
obrazu, aby wykryć ROI wielu kodów kreskowych na obrazie [3].
Wykrywanie wielu kodów na jednym obrazie:
1) Użyć funkcji drawrectangle, aby narysować i uzyskać parametry prostokąta.
roi1 = drawrectangle;
pos = roi1.Position;
2) Użyć funkcji readBarCode w celuy znalezienie kodu oraz jego formatu. Następnie
wprowadzić linie wskazujące linie rzędu skanowanego, po czym nanieść adnotację na
obraz za pomocą zdekodowanej wiadomości;
roi = […………];
imSize = size(I);
for i = 1:size(roi,1)
[msg, format, locs] = readBarcode(I, roi(i,:));
disp("Wiadomosc: " + format + ", " + msg)
xyBegin = locs(1,:);
I = insertShape(I,"Line",[1 xyBegin(2) imSize(2) xyBegin(2)], ...
"LineWidth", 5);
W celu zautomatyzowania procesu wykrywania wielu kodów kreskowych należy posłużyć się
technikami analizy oraz przetwarzania obrazów. Wymaga to zlokalizowania wielu kodów
kreskowych na obrazie, określenia i skorygowania ich orientacji. W przypadku obrazu
zawierającego wiele obróconych kodów kreskowych należy przystąpić do wstępnego
przetwarzania obrazu w celu prawidłowego odczytania ich.
1) Wykryć regiony kandydujące dla kodów kreskowych za pomocą MSER (ang. Maximally
stable extremal regions).
Następnie, wykryć obszary zainteresowania na obrazie za pomocą funkcji
detectMSERFeatures. Pozwoli to wyeliminować niepożądane obszary na podstawie
określonych kryteriów, takich jak współczynnik proporcji. Można użyć obrazu binarnego
z przefiltrowanych wyników do dalszego przetwarzania.
BW = false(size(Igray));
for i = 1:length(candidateRegions)
BW(cc.PixelIdxList{candidateRegions(i)}) = true;
end
imshow(BW)
title("Kandydujace region dla kodow kreskowych")
imshow(BW)
Przykład sprawdza dostępność licencji Statistics and Machine Learning Toolbox™. Jeśli
zostanie znaleziona licencja, w przykładzie zostanie użyta metoda klastrowania.
W przeciwnym razie w przykładzie zastosowano metodę segmentacji.
useClustering = license('test','statistics_toolbox');
if useClustering
[boundingBox, orientation, Iclusters] = clusteringLocalization(lines,
size(I));
imshow(Iclusters)
else
disp("The clustering based workflow requires a license for the
Statistics and Machine Learning Toolbox")
end
if ~useClustering
[boundingBox, orientation, Idilated] =
segmentationLocalization(Ihoughlines);
imshow(Idilated)
end
Kody kreskowe są przycinane z oryginalnego obrazu przy użyciu obwiedni uzyskanych z segmentacji.
Wyniki orientacji są używane do wyrównania kodów kreskowych tak, aby były w przybliżeniu poziome.
for i = 1:length(correctedImages)
[msg, format, ~] = readBarcode(correctedImages{i}, '1D');
disp("Odczytana wiadomosc: " + format + ", " + msg)
end
negAngles = 90 + [lines(idxNeg).theta];
linesBisector.theta(idxNeg) = negAngles;
midPts = zeros(length(lines),2);
for i = 1:length(lines)
midPts(i,:) = (lines(i).point1 + lines(i).point2)/2;
linesBisector.rho(i) = abs(midPts(i,2) - tand(lines(i).theta) *
midPts(i,1))/...
((tand(lines(i).theta)^2 + 1) ^ 0.5);
end
[linesBisector.x, linesBisector.y] =
pol2cart(deg2rad(linesBisector.theta),linesBisector.rho,'ro');
X = [linesBisector.x,linesBisector.y];
D = pdist2(X,X);
searchRadius = max(imSize/5);
minPoints = 10;
idx = dbscan(D,searchRadius, minPoints);
Iclusters = ones(imSize);
for i = 1:length(numClusters)
classIdx = find(idx == i);
rgbColor = rand(1,3);
startPts = reshape([lines(classIdx).point1], 2, length(classIdx))';
endPts = reshape([lines(classIdx).point2], 2, length(classIdx))';
orientation = zeros(1,length(numClusters));
boundingBox = zeros(length(numClusters), 4);
padding = 40;
for i = 1:length(numClusters)
.
x1 = min(dataXY{i}(:,1)) - padding;
x2 = max(dataXY{i}(:,1)) + padding;
y1 = min(dataXY{i}(:,2)) - padding;
y2 = max(dataXY{i}(:,2)) + padding;
end
end
Ibw = ~Ihoughlines(:,:,1);
Ibw(Ibw > 0) = true;
diskRadius = 10;
se = strel('disk', diskRadius);
Idilated = imdilate(Ibw, se);
padding = 40;
end
orientation = [regionStatistics(:).Orientation];
end
4. Opracowanie wyników
Na podstawie przeprowadzonej kalibracji kamery Kinect oraz poszczególnych etapów
przetwarzania i analizy obrazów przedstawić graficznie poszczególne kroki pozwalające
wykryć i zidentyfikować pojedynczy kod 1D, kod 2D oraz wiele kodów na jednym obrazie.
Sprawozdanie powinno zawierać:
1. Temat ćwiczenia.
2. Datę wykonania ćwiczenia.
3. Przebieg realizacji ćwiczenia.
4. Wykresy danych odczytanych oraz wyniki kalibracji.
5. Wnioski.
5. Pytania kontrolne
1) Co to są kody kreskowe?
2) Wymień rodzaje kodów kreskowych.
3) Jakie ograniczenia mają kody kreskowe?
4) Opisz budowę kamery Kinect v1 oraz v2.
6. Literatura
[1] Gavin Weightman: The History of the Bar Code., 23.09.2015, smithsonianmag.com
[2] Kody kreskowe – rodzaje standardy sprzęt zastosowania – ILiM, Poznań 2000, ISBN 83-
87344-60-5
[3] Creusot, Clement, et al. "Real-time Barcode Detection in the Wild." IEEE Winter Conference
on Applications of Computer Vision, 2015.