Software des NXT 3D Laser Scanners: Unterschied zwischen den Versionen
(Die Seite wurde neu angelegt: „= Matlab code = %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Lego NXT Laser3DScanner % In Dieser Progra…“) |
|||
Zeile 1: | Zeile 1: | ||
= Matlab code = | = Matlab code = | ||
Lego NXT Laser3DScanner | |||
In Dieser Programmierung soll ein NXT angesteuert werden der | |||
ein Objekt dreht & eine Webcam, die das Objektaufnimmt um es | |||
am Computer als 3D Figur anzeigt. | |||
* Authoren: Christoph Dörner & Michael Deitel | |||
* Date: 01/12/2013 - 12/01/2014 | |||
* Hochschule Hamm-Lippstadt, www.hshl.de | |||
* basierend auf RWTH - Mindstorms NXT Toolbox: | |||
* http://www.mindstorms.rwth-aachen.de | |||
* MATLAB Image Acquisition Toolbox: | |||
* www.mathworks.com/products/imaq/? | |||
Zeile 22: | Zeile 22: | ||
% | %Programm: | ||
% 1. Sicherstellung der Installation der RWTH-Mindstorm NXT Toolbox | % 1. Sicherstellung der Installation der RWTH-Mindstorm NXT Toolbox | ||
% 2. Schließen aller bestehender Handle (falls diese existieren) | % 2. Schließen aller bestehender Handle (falls diese existieren) | ||
% 3. NXT Verbindung herstellen | % 3. NXT Verbindung herstellen | ||
% 4. Globale Bekanntmachung des NXT Handle | % 4. Globale Bekanntmachung des NXT Handle | ||
% 5. Körper Rotieren lassen, Kamera aktivieren und Film aufnehmen | % 5. Körper Rotieren lassen, Kamera aktivieren und Film aufnehmen | ||
% 6. Kamerawinkel wird gesetzt | % 6. Kamerawinkel wird gesetzt | ||
% 7. Farbe des Lasers wird gesetzt | % 7. Farbe des Lasers wird gesetzt | ||
% 8. Kalibrirungsbild wird zum ausgleichen der Kameraposition genommen, | % 8. Kalibrirungsbild wird zum ausgleichen der Kameraposition genommen, | ||
% falls diese schief zum Objekt steht | % falls diese schief zum Objekt steht | ||
% 9. Den Motormittelpunkt auswählen | % 9. Den Motormittelpunkt auswählen | ||
%10. Den Bildbereich des Objektes auswählen | %10. Den Bildbereich des Objektes auswählen | ||
%11. Bilder werden nach und nach in einer for-Schleife verarbeitet | %11. Bilder werden nach und nach in einer for-Schleife verarbeitet | ||
%12. Dazu wird jedes in ein Binärbild von der Laserfarbe konvertiert | %12. Dazu wird jedes in ein Binärbild von der Laserfarbe konvertiert | ||
% und die Position der Laserlinie analysiert | % und die Position der Laserlinie analysiert | ||
%13. Nach der Schleife werden die Werte verechnet und in der | %13. Nach der Schleife werden die Werte verechnet und in der | ||
% 3D-Grafik angezeigt | % 3D-Grafik angezeigt | ||
Zeile 45: | Zeile 59: | ||
% Sicherstellung, dass die RWTH - Mindstorms NXT Toolbox installiert ist | % Sicherstellung, dass die RWTH - Mindstorms NXT Toolbox installiert ist | ||
if verLessThan('RWTHMindstormsNXT', '2.00'); | if verLessThan('RWTHMindstormsNXT', '2.00'); | ||
error(strcat('This program requires the RWTH - Mindstorms NXT Toolbox ' ... | error(strcat('This program requires the RWTH - Mindstorms NXT Toolbox ' ... | ||
Zeile 52: | Zeile 67: | ||
% Schliessen alle bestehender Handle, falls diese existieren | % Schliessen alle bestehender Handle, falls diese existieren | ||
COM_CloseNXT all | COM_CloseNXT all | ||
% Vorbereitung des Arbeitsplatzes indem sicherheitshalber alle | % Vorbereitung des Arbeitsplatzes indem sicherheitshalber alle | ||
% Variablen gelöscht und alle Fenster geschlossen werden | % Variablen gelöscht und alle Fenster geschlossen werden | ||
close all | close all | ||
clear all | clear all | ||
% Öffnen der NXT Bluetooth Verbindung anhand der Initialisierungsdatei | % Öffnen der NXT Bluetooth Verbindung anhand der Initialisierungsdatei | ||
'bluetooth.ini' | 'bluetooth.ini' | ||
handle = COM_OpenNXT('bluetooth.ini'); | handle = COM_OpenNXT('bluetooth.ini'); | ||
Zeile 65: | Zeile 83: | ||
% Globale bekanntmachung des NXT Handle, damit alle nachfolgenden | % Globale bekanntmachung des NXT Handle, damit alle nachfolgenden | ||
% Funktionen auf dieses Handle zugreifen können. | % Funktionen auf dieses Handle zugreifen können. | ||
COM_SetDefaultNXT(handle); | COM_SetDefaultNXT(handle); | ||
% Motoreinstellung (Grad der Umdrehung & Geschwindigkeit) | % Motoreinstellung (Grad der Umdrehung & Geschwindigkeit) | ||
Fahrgeschwindigkeit = -10; % Prozent | Fahrgeschwindigkeit = -10; % Prozent | ||
UmdrehungenInDeg = 360; % Grad | UmdrehungenInDeg = 360; % Grad | ||
Zeile 78: | Zeile 98: | ||
% Initialisierung des Motors | % Initialisierung des Motors | ||
Objekt.Stop('off'); | Objekt.Stop('off'); | ||
% Öffnen der WebCam | % Öffnen der WebCam | ||
vid = videoinput('winvideo',1,'YUY2_640x480'); | vid = videoinput('winvideo',1,'YUY2_640x480'); | ||
% Bildrate festlegen | % Bildrate festlegen | ||
framerate = 30; | framerate = 30; | ||
% Aufnahmezeit und Anzahl der Bilder festlegen | % Aufnahmezeit und Anzahl der Bilder festlegen | ||
set(vid,'FrameGrabInterval',1); | set(vid,'FrameGrabInterval',1); | ||
capturetime = 5.5; | capturetime = 5.5; | ||
Zeile 101: | Zeile 125: | ||
% Hier wird die Fahrt gestartet | % Hier wird die Fahrt gestartet | ||
Objekt.SendToNXT(); | Objekt.SendToNXT(); | ||
% Warte bis die Aufnahme beendet ist und dann fortfahren | % Warte bis die Aufnahme beendet ist und dann fortfahren | ||
wait(vid,Inf); | wait(vid,Inf); | ||
avi = get(vid,'DiskLogger'); | avi = get(vid,'DiskLogger'); | ||
Zeile 111: | Zeile 137: | ||
%------------------Ende des Scanvorgangs------------------------ | %------------------Ende des Scanvorgangs------------------------ | ||
%--------------Auswerten der .avi Videodatei in 3D--------------- | %--------------Auswerten der .avi Videodatei in 3D--------------- | ||
Zeile 117: | Zeile 144: | ||
% Videodatei die analysiert werden soll | % Videodatei die analysiert werden soll | ||
filename = 'Objekt.avi'; | filename = 'Objekt.avi'; | ||
% Festlegung des Kamerawinkels (pi/4 (45°) wobei pi=180°) | % Festlegung des Kamerawinkels (pi/4 (45°) wobei pi=180°) | ||
camAngle = pi/9; | camAngle = pi/9; | ||
% Festlegung der Laserfarbe zum Orientieren Rot=1 Gruen=2 Blau=3 | % Festlegung der Laserfarbe zum Orientieren Rot=1 Gruen=2 Blau=3 | ||
laserInd = 1; | laserInd = 1; | ||
% Kalibrierungsframe | % Kalibrierungsframe | ||
calFrame = 1; | calFrame = 1; | ||
% Den Scanfilm aufrufen und den Laser herausfiltern | % Den Scanfilm aufrufen und den Laser herausfiltern | ||
m = aviread(filename, calFrame); | m = aviread(filename, calFrame); | ||
calImg = m.cdata(:,:,laserInd); | calImg = m.cdata(:,:,laserInd); | ||
%Kalibrierungsbild anzeigen | %Kalibrierungsbild anzeigen | ||
figure(1); | figure(1); | ||
imshow(calImg); | imshow(calImg); | ||
Zeile 141: | Zeile 174: | ||
% Bild rotieren | % Bild rotieren | ||
figure(1);clf; | figure(1);clf; | ||
calImg = imrotate(calImg, rotAngle); | calImg = imrotate(calImg, rotAngle); | ||
Zeile 146: | Zeile 180: | ||
% Zentrierung bestimmen | % Zentrierung bestimmen | ||
xlabel('Click mouse for center line'); | xlabel('Click mouse for center line'); | ||
set(gcf, 'Pointer', 'fullcrosshair'); | set(gcf, 'Pointer', 'fullcrosshair'); | ||
Zeile 152: | Zeile 187: | ||
% Zu interessierende Region lokalisieren | % Zu interessierende Region lokalisieren | ||
xlabel('Draw rectangle over region of interest'); | xlabel('Draw rectangle over region of interest'); | ||
rect = getrect; | rect = getrect; | ||
Zeile 164: | Zeile 200: | ||
% Unschärfefilter erstellen um das Bild zu glätten | % Unschärfefilter erstellen um das Bild zu glätten | ||
% bevor der Laser gefunden wird | % bevor der Laser gefunden wird | ||
h = ones(5,1)/5; | h = ones(5,1)/5; | ||
% Schwelle einstellen zum finden der Laserlinie | % Schwelle einstellen zum finden der Laserlinie | ||
threshold = 0.1; | threshold = 0.1; | ||
% Laserlinie finden | % Laserlinie finden | ||
nfo = aviinfo(filename); | nfo = aviinfo(filename); | ||
Nframes = 1; | Nframes = 1; | ||
Zeile 175: | Zeile 214: | ||
for k=1:length(frameTab) | for k=1:length(frameTab) | ||
disp(sprintf('Analyzing frame #%d', frameTab(k))); | disp(sprintf('Analyzing frame #%d', frameTab(k))); | ||
% Form vom Scanfilm erkennen | % Form vom Scanfilm erkennen | ||
m = aviread(filename,frameTab(k)); | m = aviread(filename,frameTab(k)); | ||
% Alles rausfiltern außer die Laserlinie & rotieren des Bildes | % Alles rausfiltern außer die Laserlinie & rotieren des Bildes | ||
img = imrotate(m.cdata(:,:,laserInd), rotAngle); | img = imrotate(m.cdata(:,:,laserInd), rotAngle); | ||
% Bild auf die uns interessierende Region schneiden | % Bild auf die uns interessierende Region schneiden | ||
imgCrop = imcrop(img, rect); | imgCrop = imcrop(img, rect); | ||
Zeile 187: | Zeile 230: | ||
% eine große zahl an Bildern haben und die Funktionen mit double | % eine große zahl an Bildern haben und die Funktionen mit double | ||
% arbeiten | % arbeiten | ||
imgFilt = filter2(h,im2double(imgCrop)); | imgFilt = filter2(h,im2double(imgCrop)); | ||
% für jede Zeile maximale Bildintensität finden & dessen x-Position | % für jede Zeile maximale Bildintensität finden & dessen x-Position | ||
[mx(k,:), rtmp(k,:)] = max(imgFilt'); | [mx(k,:), rtmp(k,:)] = max(imgFilt'); | ||
% Sollten in der Laserlinie Löcher sein werden diese ausgefüllt | % Sollten in der Laserlinie Löcher sein werden diese ausgefüllt | ||
if (length(find(mx(k,:)>threshold))>=2) | if (length(find(mx(k,:)>threshold))>=2) | ||
r(k,:)=interp1(find(mx(k,:)>threshold),... | r(k,:)=interp1(find(mx(k,:)>threshold),... | ||
Zeile 201: | Zeile 247: | ||
% Bild Zeichnen und Laserlinie berechnen | % Bild Zeichnen und Laserlinie berechnen | ||
figure(2);clf; | figure(2);clf; | ||
imshow(imgFilt); | imshow(imgFilt); | ||
Zeile 209: | Zeile 256: | ||
% X-Position der Laserlinie und des Bildes zum realen Radius | % X-Position der Laserlinie und des Bildes zum realen Radius | ||
% konvertieren | % konvertieren | ||
if xoffset>0 | if xoffset>0 | ||
R = (r+xoffset)./sin(camAngle); | R = (r+xoffset)./sin(camAngle); | ||
Zeile 217: | Zeile 265: | ||
% Konvertieren zu den Oberflächenkoordinaten | % Konvertieren zu den Oberflächenkoordinaten | ||
X = R.*repmat(cos(theta),1,size(imgFilt,1)); | X = R.*repmat(cos(theta),1,size(imgFilt,1)); | ||
Y = R.*repmat(sin(theta),1,size(imgFilt,1)); | Y = R.*repmat(sin(theta),1,size(imgFilt,1)); | ||
Zeile 222: | Zeile 271: | ||
% Resultat (Scan) anzeigen | % Resultat (Scan) anzeigen | ||
figure(22); | figure(22); | ||
S = surf(X,Y,Z,R); | S = surf(X,Y,Z,R); | ||
set(S, 'LineStyle', 'none'); | set(S, 'LineStyle', 'none'); | ||
axis square; | axis square; |
Aktuelle Version vom 24. Januar 2014, 16:40 Uhr
Matlab code
Lego NXT Laser3DScanner In Dieser Programmierung soll ein NXT angesteuert werden der ein Objekt dreht & eine Webcam, die das Objektaufnimmt um es am Computer als 3D Figur anzeigt.
* Authoren: Christoph Dörner & Michael Deitel * Date: 01/12/2013 - 12/01/2014 * Hochschule Hamm-Lippstadt, www.hshl.de * basierend auf RWTH - Mindstorms NXT Toolbox: * http://www.mindstorms.rwth-aachen.de * MATLAB Image Acquisition Toolbox: * www.mathworks.com/products/imaq/?
%--------------------------Beginn Programm------------------------
%Programm:
% 1. Sicherstellung der Installation der RWTH-Mindstorm NXT Toolbox
% 2. Schließen aller bestehender Handle (falls diese existieren)
% 3. NXT Verbindung herstellen
% 4. Globale Bekanntmachung des NXT Handle
% 5. Körper Rotieren lassen, Kamera aktivieren und Film aufnehmen
% 6. Kamerawinkel wird gesetzt
% 7. Farbe des Lasers wird gesetzt
% 8. Kalibrirungsbild wird zum ausgleichen der Kameraposition genommen,
% falls diese schief zum Objekt steht
% 9. Den Motormittelpunkt auswählen
%10. Den Bildbereich des Objektes auswählen
%11. Bilder werden nach und nach in einer for-Schleife verarbeitet
%12. Dazu wird jedes in ein Binärbild von der Laserfarbe konvertiert % und die Position der Laserlinie analysiert
%13. Nach der Schleife werden die Werte verechnet und in der % 3D-Grafik angezeigt
%----------------Anfang des Scanvorgangs---------------------------
% Sicherstellung, dass die RWTH - Mindstorms NXT Toolbox installiert ist
if verLessThan('RWTHMindstormsNXT', '2.00');
error(strcat('This program requires the RWTH - Mindstorms NXT Toolbox ' ... ,'version 2.00 or greater. Go to http://www.mindstorms.rwth-aachen.de' ... ,' and follow the installation instructions!'));
end
% Schliessen alle bestehender Handle, falls diese existieren
COM_CloseNXT all
% Vorbereitung des Arbeitsplatzes indem sicherheitshalber alle % Variablen gelöscht und alle Fenster geschlossen werden
close all clear all
% Öffnen der NXT Bluetooth Verbindung anhand der Initialisierungsdatei
'bluetooth.ini'
handle = COM_OpenNXT('bluetooth.ini');
% Globale bekanntmachung des NXT Handle, damit alle nachfolgenden % Funktionen auf dieses Handle zugreifen können.
COM_SetDefaultNXT(handle);
% Motoreinstellung (Grad der Umdrehung & Geschwindigkeit)
Fahrgeschwindigkeit = -10; % Prozent UmdrehungenInDeg = 360; % Grad
Objekt = NXTMotor(MOTOR_A); % Motor A wird angesteuert Objekt.SpeedRegulation = false; % Kein Sync Mode Objekt.Power = Fahrgeschwindigkeit; % Fahrgeschwindigkeit in Prozent Objekt.TachoLimit = UmdrehungenInDeg; % Umdrehungen in Deg Objekt.ActionAtTachoLimit = 'Brake'; % Nicht auslaufen
% Initialisierung des Motors
Objekt.Stop('off');
% Öffnen der WebCam
vid = videoinput('winvideo',1,'YUY2_640x480');
% Bildrate festlegen
framerate = 30;
% Aufnahmezeit und Anzahl der Bilder festlegen
set(vid,'FrameGrabInterval',1); capturetime = 5.5; interval = get(vid,'FrameGrabInterval'); numframes = floor(capturetime * framerate / interval) set(vid,'FramesPerTrigger',numframes); set(vid,'LoggingMode','disk'); avi = avifile('Objekt','fps',framerate); set(vid,'DiskLogger',avi); start(vid); pause(1.2);
% Hier wird die Fahrt gestartet
Objekt.SendToNXT();
% Warte bis die Aufnahme beendet ist und dann fortfahren
wait(vid,Inf); avi = get(vid,'DiskLogger'); avi = close(avi);
pause(5);
%------------------Ende des Scanvorgangs------------------------
%--------------Auswerten der .avi Videodatei in 3D---------------
% Parameter
% Videodatei die analysiert werden soll
filename = 'Objekt.avi';
% Festlegung des Kamerawinkels (pi/4 (45°) wobei pi=180°)
camAngle = pi/9;
% Festlegung der Laserfarbe zum Orientieren Rot=1 Gruen=2 Blau=3
laserInd = 1;
% Kalibrierungsframe
calFrame = 1;
% Den Scanfilm aufrufen und den Laser herausfiltern
m = aviread(filename, calFrame); calImg = m.cdata(:,:,laserInd);
%Kalibrierungsbild anzeigen
figure(1); imshow(calImg); xlabel({'Calibrate rotation of image.','Draw line from top to bottom that should be verticle.', 'Left click to start. Right click to end.'}); [rotX, rotY] = getline(1); rotAngle = 180/pi*atan2(rotY(2)-rotY(1),rotX(2)-rotX(1))-90;
% Bild rotieren
figure(1);clf; calImg = imrotate(calImg, rotAngle); imshow(calImg);
% Zentrierung bestimmen
xlabel('Click mouse for center line'); set(gcf, 'Pointer', 'fullcrosshair'); [x,y]=ginput(1); line([x, x], [1,size(calImg,2)]);
% Zu interessierende Region lokalisieren
xlabel('Draw rectangle over region of interest'); rect = getrect; if rect(1)>x
xoffset = rect(1)-x;
else
xoffset = (rect(1)+rect(3))-x;
end; rectangle('Position', rect, 'EdgeColor', [1,0,0]); set(gcf, 'Pointer', 'arrow');
% Unschärfefilter erstellen um das Bild zu glätten % bevor der Laser gefunden wird
h = ones(5,1)/5;
% Schwelle einstellen zum finden der Laserlinie
threshold = 0.1;
% Laserlinie finden
nfo = aviinfo(filename); Nframes = 1; frameTab = 1:Nframes:nfo.NumFrames; for k=1:length(frameTab)
disp(sprintf('Analyzing frame #%d', frameTab(k)));
% Form vom Scanfilm erkennen
m = aviread(filename,frameTab(k));
% Alles rausfiltern außer die Laserlinie & rotieren des Bildes
img = imrotate(m.cdata(:,:,laserInd), rotAngle); % Bild auf die uns interessierende Region schneiden
imgCrop = imcrop(img, rect); % Bild filtern & von uint8 nach double convertieren, da wir % eine große zahl an Bildern haben und die Funktionen mit double % arbeiten
imgFilt = filter2(h,im2double(imgCrop)); % für jede Zeile maximale Bildintensität finden & dessen x-Position
[mx(k,:), rtmp(k,:)] = max(imgFilt');
% Sollten in der Laserlinie Löcher sein werden diese ausgefüllt
if (length(find(mx(k,:)>threshold))>=2) r(k,:)=interp1(find(mx(k,:)>threshold),... rtmp(k,find(mx(k,:)>threshold)),1:size(rtmp,2)); else r(k,:)=zeros(1,size(rtmp,2)); end; % Bild Zeichnen und Laserlinie berechnen
figure(2);clf; imshow(imgFilt); hold on; plot(r(k,:),1:size(r,2),'r');
end;
% X-Position der Laserlinie und des Bildes zum realen Radius % konvertieren
if xoffset>0
R = (r+xoffset)./sin(camAngle);
else
R = (rect(3)-r-xoffset)./sin(camAngle);
end; theta = linspace(0,2*pi,length(frameTab))';
% Konvertieren zu den Oberflächenkoordinaten
X = R.*repmat(cos(theta),1,size(imgFilt,1)); Y = R.*repmat(sin(theta),1,size(imgFilt,1)); Z = -repmat(1:size(imgFilt,1),length(theta),1);
% Resultat (Scan) anzeigen
figure(22); S = surf(X,Y,Z,R); set(S, 'LineStyle', 'none'); axis square;