QR-Code erzeugen und lesen

Aus HSHL Mechatronik
Zur Navigation springen Zur Suche springen

Autor: Hauke Ludwig
Betreuer: Prof. Schneider

Wohin man auch blickt ... überall prangert ein QR-Code an Wänden.

Motivation

QR-Codes sind omnipräsent, aber wie codiert man Informationen als QR-Code?

Ziel

Erzeugen Sie ein Matlab Executable, welches aus einer eingegebenen URL einen QR-Code mit beliebigem Logo in der Mitte erzeugt.

Aufgabe

  1. Arbeiten Sie sich in die Erstellung von QR-Codes ein.
  2. Erzeugen Sie ein Matlab Executable, welches aus einer eingegebenen URL einen QR-Code mit beliebigem Logo in der Mitte erzeugt.
  3. Lesen Sie mit Matlab diesen QR-Code ein, so dass dieser Sie auf eine Webpage verlinkt.

Lösung

Vorbearbeitung

Als erser Schritt wird das zu verarbeitende Bild in ein Schwarz/Weiß-Bild konvertiert. Bei dieser Konvertierung werden gleichzeitig alle Bildelemente welche nicht einem Grauwert entsprechen eleminiert. Grauwertentsprechende Werte sind Werte, welche gleichmäßige Anteile an Rot-, Grün- und Blautanteile haben. Das Ergebnis der Eleminierung einzelner Pixel ist deutlich an den schwarzen Flecken im Grayscale-Bild zu erkennen.

Vorbearbeitung des Bildes

Extrahierung

Die Extrahierung des QR-Codes aus dem Bild erfolgt anhand eines Box-Find-Algorithmus, welcher bereits in MatLab implementiert ist [1]

Code

%****************************************************************
%        Hochschule Hamm-Lippstadt                              *
%****************************************************************
% Modul	          : QR Code Extractor                           *
%                                                               *
% Datum           : 15-Jun-2014                                 *
%                                                               *
% Funktion        : Extrahierung eines QR_Codes aus Bildern     *
%                                                               *
% Implementation  : MATLAB R2013a                               *
%                                                               *
% Author          : Hauke Ludwig                                *
%                                                               *
% Letzte Änderung : 15-Jun-2014                                 *
%                                                               *
% Copyright (c) 2014, Hauke Ludwig                              *
% All rights reserved.                                          *
%***************************************************************/

function [Pair] = extract (Image)
%% extract
% returns extracted QR-Code as bitfield from Image 
% (as RGB-Matrix (uint8) width x heigh x RGB )

%% Defines
distSizeThresh = 10;
distPosThresh = 100;
distDensityThresh = 15;
diff_Density = 0.04;

Padding_Crop = 50;

%% Matrix
Pair = [0 0];
DensityPassed = [0 0 0];

%% Code
% Image Convertion
gray= rgb2gray(Image);
gray(~(abs(Image(:,:,1)-Image(:,:,2))+abs(Image(:,:,2)-Image(:,:,3))+abs(Image(:,:,1)-Image(:,:,3))<40))=0;
BW=~im2bw(Image,graythresh(Image));
BW(~(abs(Image(:,:,1)-Image(:,:,2))+abs(Image(:,:,2)-Image(:,:,3))+abs(Image(:,:,1)-Image(:,:,3))<40))=0;
cAll = edge(BW,'sobel','vertical')+edge(BW,'sobel','horizontal')+edge(gray,'sobel','horizontal')+edge(gray,'sobel','vertical');

%% DISPLAY RESULT
figure
subplot(2,4,1)
imshow(Image)
title('Source')
subplot(2,4,4)
imshow(cAll)
title('Canny')
subplot(2,4,2)
imshow(gray)
title('Grayscale')
subplot(2,4,3)
imshow(~BW)
title('Black/White')

%% Find boxes in image
stat = regionprops(logical(bwareaopen(cAll,100)),'boundingbox');
for cnt = 1 : numel(stat)
    if stat(cnt).BoundingBox(3)/stat(cnt).BoundingBox(4)>0.5 && stat(cnt).BoundingBox(3)/stat(cnt).BoundingBox(4)<1.2               %like rectangle will be filtered
        bb(cnt,:) = stat(cnt).BoundingBox;
    else
        bb(cnt,:)=[-1 -1 -1 -1];
    end
    
end
bb(bb(:,:)==-1)=[];
bb=reshape(bb,size(bb,2)/4,4);

%% Calculate distance between Size of squares
distSize = sqrt(bsxfun(@minus,bb(:,3),bb(:,3)').^2 + bsxfun(@minus,bb(:,4),bb(:,4)').^2);
distSize(distSize(:,:)>distSizeThresh)=0;

%% Calculate distance between position of squares
distPos = sqrt(bsxfun(@minus,bb(:,1),bb(:,1)').^2 + bsxfun(@minus,bb(:,2),bb(:,2)').^2);
distPos(distPos(:,:)>distPosThresh)=0;

%% DISPLAY RESULT
subplot(2,4,6)
imshow(cAll)
title('Canny operated / equal square detection')
hold on

%% Filter boxes for euqal squares
for k=1:size(distSize,1)
    for l=1:k
        if distSize(k,l)~= 0 && size(find(distSize==distSize(k,l)),1)>=6
            Pair(end+1,:)=[k l];
        end
    end
end


Pair(1,:)=[];
for k=1:size(Pair,1)
    CropImage1=imcrop(cAll,bb(Pair(k,1),:));
    Density(k,1)=sum(sum(size(find(CropImage1~=0),1)))/(bb(Pair(k,1),3)*bb(Pair(k,1),4));
    CropImage2=imcrop(cAll,bb(Pair(k,2),:));
    Density(k,2)=sum(sum(size(find(CropImage2~=0),1)))/(bb(Pair(k,2),3)*bb(Pair(k,2),4));
    if abs(Density(k,1)-Density(k,2)) < diff_Density
        if Density(k,1)<0.3  && Density(k,1)>0.1 
            rectangle('position',bb(Pair(k,1),:),'edgecolor','g','linewidth',2);
            Padding_Crop = max([Padding_Crop bb(Pair(k,1),3:4)./1.1]);
            if size(find(DensityPassed(:,1)==Pair(k,1)),1) == 0
                DensityPassed(end+1,:)=[Pair(k,1) bb(Pair(k,1),1)+0.5*bb(Pair(k,1),3) bb(Pair(k,1),2)+0.5*bb(Pair(k,1),4)];
            end
        end
        if Density(k,2)<0.3  && Density(k,2)>0.1 
            rectangle('position',bb(Pair(k,2),:),'edgecolor','g','linewidth',2);
            Padding_Crop = max([Padding_Crop bb(Pair(k,1),3:4)]./1.1);
            if size(find(DensityPassed(:,1)==Pair(k,2)),1) == 0
                DensityPassed(end+1,:)=[Pair(k,2) bb(Pair(k,2),1)+0.5*bb(Pair(k,2),3) bb(Pair(k,2),2)+0.5*bb(Pair(k,2),4)];
            end
        end    
    end
end
if size(DensityPassed,1)>1
    DensityPassed(1,:)=[];
end


if size(DensityPassed,1)>1
    distDensity = sqrt(bsxfun(@minus,DensityPassed(:,2),DensityPassed(:,2)').^2 + bsxfun(@minus,DensityPassed(:,3),DensityPassed(:,3)').^2);
    for k=1:size(distDensity,1)
        for l=k+1:size(distDensity,2)
            PairDensity(k,1)=k;
            if distDensity(k,l) < distDensityThresh
                if sum(sum(ismember(PairDensity(1:k-1,:),k))) ~= 0
                    PairDensity(k,:)=[];
                    for x=1:size(PairDensity,1)-1
                        if sum(ismember(PairDensity(x,:),k)) ~= 0 && sum(ismember(PairDensity(x,:),l)) == 0

                            PairDensity(x,end+1)= l;
                        end
                    end
                else
                    PairDensity(k,end+1)= l;
                end
            end
        end
        if size(PairDensity,1) >= k
            if sum(PairDensity(k,2:end)) == 0
                PairDensity(k,:)=[];
            end
        end
    end
    Passed = [-1 -1];
    for k=1:size(PairDensity,1)
        if sum(PairDensity(k,2:end))>0  % Pair found 
            summean = [0 0];
            count = 0;
            for x=1:size(PairDensity,2)
                if PairDensity(k,x) ~= 0
                    summean = [DensityPassed(PairDensity(k,x),2)+summean(1) DensityPassed(PairDensity(k,x),3)+summean(2)];
                    count = count +1;
                end
            end
            Passed(end+1,:)=[summean(1)/count summean(2)/count];

        else if PairDensity(k,1) ~= 0   % no Pair
            Passed(end+1,:)= DensityPassed(PairDensity(k,1),2:3);
            end
        end
    end
    subplot(2,4,6)
    plot(Passed(:,1),Passed(:,2),'*r');
    Passed(1,:)=[];

    %% Crop Image on Area of Interest

    while size(Passed,1)>3
        kick=mean(sqrt(bsxfun(@minus,Passed(:,1),Passed(:,1)').^2 + bsxfun(@minus,Passed(:,2),Passed(:,2)').^2));
        Passed(find(kick==max(kick)),:)=[]; 
    end
    
    % get dynamic crop area
    Padding_Crop=mean(mean(sqrt(bsxfun(@minus,Passed(:,1),Passed(:,1)').^2 + bsxfun(@minus,Passed(:,2),Passed(:,2)').^2)))/3.5;
    minCrop = [min(Passed(:,1))-Padding_Crop min(Passed(:,2))-Padding_Crop];
    maxCrop = [max(Passed(:,1))+Padding_Crop max(Passed(:,2))+Padding_Crop];
    
    % grop image
    cAllcropped = imcrop(Image, [minCrop maxCrop-minCrop]);
    
    %% DISPLAY RESULT
    subplot(2,4,5)
    imshow(cAllcropped);
    title('croped image from source')
    normCropped = im2bw(cAllcropped);
    subplot(2,4,7)
    imshow(cAllcropped);    
    hold on
    plot(Passed(:,1)-minCrop(1),Passed(:,2)-minCrop(2),'*r');   
    title('croped image from source with equal squares')
    subplot(2,4,8)
    imshow(normCropped);
    hold on
    plot(Passed(:,1)-minCrop(1),Passed(:,2)-minCrop(2),'*r');
    title('croped image from black/white')
    DensityPassed = [ DensityPassed(:,1) DensityPassed(:,2)-minCrop(1) DensityPassed(:,3)-minCrop(2)];


    %% Find cornerpairs
    cPair=sqrt(bsxfun(@minus,Passed(:,1),Passed(:,1)').^2 + bsxfun(@minus,Passed(:,2),Passed(:,2)').^2);
    cPair(cPair(:,:)==0)=NaN;
    minPair=min(cPair);

else
    fprintf('Less equal Square to find a QR Code!\n');
end
end

Siehe auch

Beispiele für QR Codes

Weblinks

Einzelnachweis

  1. [1] MatLab, Dokumentation "regionprops" -> Bounding Box

→ zurück zum Hauptartikel: Digitale Signal- und Bildverarbeitung SoSe2014