QR-Code erzeugen und lesen: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
Zeile 21: | Zeile 21: | ||
=== Extrahierung === | === Extrahierung === | ||
=== | === Code === | ||
<source lang="matlab"> | |||
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 | |||
</source> | |||
== Siehe auch == | == Siehe auch == |
Version vom 15. Juni 2014, 15:27 Uhr
Autor: Hauke Ludwig
Betreuer: Prof. Schneider
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
- Arbeiten Sie sich in die Erstellung von QR-Codes ein.
- Erzeugen Sie ein Matlab Executable, welches aus einer eingegebenen URL einen QR-Code mit beliebigem Logo in der Mitte erzeugt.
- 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.
Extrahierung
Code
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
Weblinks
- QR Generator
- Open Source QR Code Generator
- Mobile Tagging
- YouTube: How to Decode a QR Code by Hand
- Wikipedia: QR Code
→ zurück zum Hauptartikel: Digitale Signal- und Bildverarbeitung SoSe2014