ich bin nicht nur neu hier im Forum, sondern auch in der Programmierung mit MatLab. Aktuell bearbeite ich folgendes Problem:
Bestimmung der Ballposition[x,y] eines roten Balles in einem Bild. In Anlehnung an ein Youtube-Tutorial und den dort verwendeten Code habe ich mir ebenfalls ein Bild herausgesucht, in welchem u.a. ein roter Ball zu sehen ist. Mit kleinem Aufwand habe ich den Code an mein individuelles Bild angepasst und der Ball wird wie gewünscht erkannt.
Nun zu meiner Frage/meinem Problem:
Im Code selbst wird allein das Merkmal "Rot" aus dem RGB-Raum angesprochen, doch wie man im Bild sieht und es auch später für mein eigentliches Vorhaben relevant ist, ist das "Rot" in Abhängigkeit seiner Distanz mal heller (weißer) und mal dunkler (schwarz).
Wie kann ich dieses Spektrum der möglichen "Rotfarben" in den Code einpflegen, wie würde ein Bsp. aussehen? Ich habe gelesen, dass sich der HSV-Farbraum besser anbietet, eben wegen der Helligkeits- und Sättigungskomponente. Leider habe ich auch da stets nur den allgemeinen Code von RGB -> HSV und umgekehrt gefunden. Keine Detailangabe zu Formulierungen von Wertebereichen.
Hier mein aktueller Code + Bild:
Code:
%% Get Infomation about the Image
info = imageinfo('Ball.png');
%% Load/Read Image
A = imread('Ball.png');
rgb = imresize(A,1/2);
imshow(rgb);
% we have to subtract the red component % from the grayscale image to extract the red components in the image.
diff_im = imsubtract(rgb(:,:,1), rgb2gray(rgb));
%Use a medianfilter to filter out noise
diff_im = medfilt2(diff_im, [33]);
% Convert the resulting grayscale image into a binary image.
diff_im = im2bw(diff_im,0.18);
% Remove all those pixels less than 300px
diff_im = bwareaopen(diff_im,300);
% Label all the connected components in the image.
bw = bwlabel(diff_im, 8);
% Here we do the image blob analysis. % We get a set of properties for each labeled region.
stats = regionprops(bw, 'BoundingBox', 'Centroid');
%This is a loop to bound the red objects in a rectangular box.
for object = 1:length(stats)
bb = stats(object).BoundingBox;
bc = stats(object).Centroid;
rectangle('Position',bb,'EdgeColor','r','LineWidth',2) plot(bc(1),bc(2), '-m+')
a=text(bc(1)+15,bc(2), strcat('X: ', num2str(round(bc(1))), ' Y: ', num2str(round(bc(2)))));
set(a, 'FontName', 'Arial', 'FontWeight', 'bold', 'FontSize', 12, 'Color', 'yellow');
end
Meine Frage zum HSV-Raum und einer detaillierteren Codierung nach Rot wäre, da es sich ja um einen Farbkreis für H handelt, wird die Farbe Rot ca. von 0°-50° und 315°-360° abgebildet, "S"= 1 und "V"= 255 Wie kann ich diesen Wertebereich in den allgemeinen Code
integrieren? Mit Bezug auf Entfernungs- und Belichtungsunterschiede zur späteren Kameraposition denke ich, dass das Rot vielleicht mal mehr Richtung Gelb oder Magenta gehen kann. Dies würde ich gern mit diesem Wertebereich abdecken.
Viele Grüße, MatLabStarter
PS: Ich hoffe, dass mein Anliegen nicht zu umständlich erfragt ist
Rot ist eine Vollfarbe. Um andere Farben darzustellen musst du G und/oder B beimischen. Man kann also nicht den Rotbereich am Maximalwert erweitern. Die anderen Werte sind beispielhaft oben aufgeführt. Du musst nur herausfinden, welche Bereiche geändert werden müssen. Dein Ball wird doch in HSV gut dargestellt. Besser als RGB!!??
kannst du mir bitte kurz anhand meines Codes zeigen, wie ich die Analyse über den HSV-Raum realisiere, aktuell ist er ja für den RGB-Raum geschrieben, Danke.
% Subtract the red component from grayscale image to extract the red % components
diff_im = imsubtract (rgb(:,:,1), rgb2gray(rgb));
% Use a median filter to filter out noise
diff_im = medfilt2(diff_im, [33]);
% Convert the resulting grayscale image into a binary image.
diff_im = im2bw(diff_im,0.1);
% Remove all those pixels less than 300px
diff_im = bwareaopen(diff_im,300);
% Label all the connected components in the image.
bw = bwlabel(diff_im, 8);
% Here we do the image blob analysis. % We get a set of properties for each labeled region.
stats = regionprops(bw, 'BoundingBox','Centroid');
Dein Farbraum ist HSV und nicht RGB. Du wandelst doch sofort um! Außerdem fragte ich in meiner Antwort von heute, warum die Konvertierung nach HSV nicht reicht. Dein Ball wird doch optimal dargestellt. Darauf bist du nicht eingegangen! Was willst du denn erreichen? Das ist doch entscheidend!
Natürlich musst du von HSV nach RGB zurück konvertieren und wenn die Farbgebung nicht stimmen sollte, natürlich mit den veränderten HSV-Werten. Wie vorstehend bereits erwähnt.
ich denke ich sollte vielleicht etwas ausholen, was das ganze hier betrifft. Also ich bearbeite gerade ein Projekt mit dem Ziel die Position eines roten Balls anhand seiner Pixelkoordinaten(Schwerpunkt) zu bestimmen.
Auf der Suche nach einer Programmlösung/-hilfe bin ich auf den o. g. Code (1. Beitrag) gestoßen, da er auf einfache Art mir schon ein sehr naheliegendes Ergebnis bringt.
Bei meinem Beispiel Billiard-Bild sieht man, dass die Box um die "deutlichen" Rotenpixel gelegt wird und von diesem Bereich der Schwerpunkt bestimmt wird. Bei genauem hinsehen sieht man jedoch, dass der Ball größer ist, aber durch Helligkeitsunterschiede (Schatten/schwarz) dieser Bereich bei der Berechnung der Box ausgelassen wird, gleiches passiert auch, wenn ich den blauen Ball anspreche.
Da mein späterer Versuch im Freiland stattfindet, werden mich Helligkeitsunterschiede zum "Normal-Rot" sicher heimsuchen.
Um den Programmcode präzieser zu gestalten, habe ich anhand einiger Recherche erfahren, dass der HSV-Farbraum geeignet sei. Ich selbst habe jedoch wenig Erfahrung mit Bildverarbeitung bei Matlab und versuche nicht nur irgendwelche Codes zu kopieren, möchte sie gern verstehen ... quasi "Warum welcher Befehl was und Wie er was macht?!".
Meine Frage/Bitte wäre eben, wie kann ich diese Farbsegmentierung detaillierter gestalten durch Befehle/Randbedingungen anhand des vorliegenden Grundcodes?
Wenn ich mir den Code anschaue, dann lade ich ja ein "truecolor" Image (RGB), bestimme das Farbband "Rot", ... . Wie müsste ich jetzt das HSV-Image in diesen Code einbinden? Wäre cool, wenn du mir da helfen könntest.
Ich bin der Meinung, dass dein Problem nicht vorrangig zwischen RGB und HSV liegt. Wenn das so wäre, würde ein einfache Konvertierung bereits zum Ziel führen. Dein Problem sind die Schatten, die mit den gleichen Pixelwerten am Ball anliegen und zu einer unrunden Form führen. Da müsste man ansetzen und fragen, wie bekomme ich die unrunde Form wieder rund. Denn kein automatisches System wird eine Trennung zwischen gleichwertigen Pixeln vollziehen.
Du solltest dir die zu erwartenden Bilder hinsichtlich dieser Beschreibung genau ansehen und feststellen, wo die Probleme in den "Pixelwerten" liegen. Dann müsste man das "Unrund"-Problem angehen. Da könnte die Bildsegmentierung vl. helfen.
Ich würde zunächst den roten Ball samt Schatten ausschneiden und versuchen, diese Form wieder rund zu bekommen. Denn eine runde Form ist die Voraussetzung für die nachfolgenden Funktionen.
Nachtrag:
Vl. kannst du u.a. auch diese Funktion gebrauchen:
Ich habe gestern etwas wesentliches vergessen. Man muss sich die Schatten sehr genau ansehen. Es kann sein, und das ist in deinem Bildbeispiel der Fall, dass in den Schatten Farbreste verborgen liegen. Das kann man sehr schnell herausfinden, wenn man die Bildhelligkeit überzieht. Der Ball hat in den Schatten noch rote Bildanteile. Das bedeutet, dass bei einem hell überzogenem Bild der gesamte Ball vom Rahmen umzogen und erkannt wird. Ohne dass weitere Maßnahmen erforderlich sind.
Eine (1) Möglichkeit, das Bild aufzuhellen, ist die Funktion "immultiply". Das Beispiel zeigt, dass man erst einmal die Gesamtsituation genauer analysieren sollte und sich nicht vorrangig dem Problem zu RGB <> HSV ( als allgemeines Beispiel ) widmet.
mit Bezug auf mein Problem "Erkennen eines roten Balls und dessen Schwerpunktermittlung" habe ich aktuell folgende Schwierigkeiten:
1. Besteht die Möglichkeit neben dem Erzeugen eines "Binärbildes" aus den 3 R,G,B-Arrays (siehe Code) ein Weiteres definiert über einen anderen (2.) Farbraum zu erzeugen und beide sinngemäß übereinander zulegen um die "Qualität der Kontur" zu erhöhen? Durch den Helligkeitseinfluss zeigt sich im 'Binary Image' , dass der Ball nicht schön rund dargestellt wird.
2. Das Ergebnis des aktuellen Programm zeigt, dass ich mit dem vorliegenden Code und der Definition "rot" andere Objekte gleicher Farbe mitdetektiere und diese leider in die Box integriert werden, obwohl im 'Binary Image' beide Elemte klar voeinander getrennt sind. Kann mir jemand helfen, wo der Fehler im aktuellen Code liegt bzw. gibt es eine Möglichkeit (Befehl) die Element getrennt zu betrachten?
Code:
%% Programmteil Ballerkennung
A = imread('BK3.jpg');
rgbImage = imresize (A, 1/2); %Ändern des Bildfomates [m x n]
%I = imread('filename');
%rgbImage = immultiply(I,1.5); % Bild aufhellen
% Extract out the color bands from the original image
redBand = rgbImage(:, :, 1);
greenBand = rgbImage(:, :, 2);
blueBand = rgbImage(:, :, 3);
% Display them. subplot(3, 3, 2);
imshow(redBand);
title('Red Band');
subplot(3, 3, 3);
imshow(greenBand);
title('Green Band');
subplot(3, 3, 4);
imshow(blueBand);
title('Blue Band');
%% Step 2 - Filterbild erstellen
% Assign the low and high thresholds for each color band.
redThresholdLow = 139;
redThresholdHigh = 255;
greenThresholdLow = 0;
greenThresholdHigh = 99;
blueThresholdLow = 0;
blueThresholdHigh = 71;
% Now apply each color band's particular thresholds to the color band
redMask = (redBand >= redThresholdLow) & (redBand <= redThresholdHigh);
greenMask = (greenBand >= greenThresholdLow) & (greenBand <= greenThresholdHigh);
blueMask = (blueBand >= blueThresholdLow) & (blueBand <= blueThresholdHigh);
% Display the thresholded binary images. subplot(3, 3, 5);
imshow(redMask, []);
title('Red Mask');
subplot(3, 3, 6);
imshow(greenMask, []);
title('Green Mask');
subplot(3, 3, 7);
imshow(blueMask, []);
title('Blue Mask');
% Combine the masks to find where all 3 are "true."
redObjectsMask = uint8(redMask & greenMask & blueMask);
smallestAcceptableArea = 100; % Keep areas only if they're bigger than this. % Get rid of small objects. Note: bwareaopen returns a logical.
redObjectsMask = uint8(bwareaopen(redObjectsMask, smallestAcceptableArea));
% Smooth the border using a morphological closing operation, imclose().
structuringElement = strel('disk', 4);
redObjectsMask = imclose(redObjectsMask, structuringElement);
% Fill in any holes in the regions, since they are most likely red also
redObjectsMask = uint8(imfill(redObjectsMask, 'holes'));
redObjectsMask = imclearborder(redObjectsMask);
figure,imshow(redObjectsMask, []);
title('Binary Image');
%This is a loop to bound the red objects in a rectangular box.
for object = 1:length(stats)
bb = stats(object).BoundingBox;
bc = stats(object).Centroid;
rectangle('Position',bb,'EdgeColor','r','LineWidth',2) plot(bc(1),bc(2), '-m+')
a=text(bc(1)+15,bc(2), strcat('X: ', num2str(round(bc(1))), ' Y: ', num2str(round(bc(2)))));
set(a, 'FontName', 'Arial', 'FontWeight', 'bold', 'FontSize', 12, 'Color', 'yellow');
end
wenn man 2 gleiche Farben hat, wie z.B. Rot, dann kommt man über die Farbe nicht weiter. Der einzige Unterschied ist dann nur noch die Form. Ich habe mal folgendes versucht:
I=greenband; % Threshold bringt nicht weiter
I2=imclose(I,strel('disk',8);
I3=imopen(I2,strel('rectangle',[522]));
I4=immultiply(I3,2);
[centers,radii]=imfindcircles(I4,[3040],'ObjectPolarity','dark','Sensitivity',0.9);
figure; imshow(I4)% jetzt liegt ein roter Kreis um den Ball
h=viscircles(centers,radii)
% Extract out the color bands from the original image
redBand = rgbImage(:, :, 1);
greenBand = rgbImage(:, :, 2);
blueBand = rgbImage(:, :, 3);
% Display them. subplot(3, 3, 2);
imshow(redBand);
title('Red Band');
subplot(3, 3, 3);
imshow(greenBand);
title('Green Band');
subplot(3, 3, 4);
imshow(blueBand);
title('Blue Band');
I=greenBand; % Threshold bringt nicht weiter
I2=imclose(I,strel('disk',8));
I3=imopen(I2,strel('rectangle',[522]));
I4=immultiply(I3,2);
[centers,radii]=imfindcircles(I4,[3040],'ObjectPolarity','dark','Sensitivity',0.9);
figure; imshow(I4)% jetzt liegt ein roter Kreis um den Ball
h=viscircles(centers,radii);
Du kannst Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen. Du kannst Dateien in diesem Forum posten Du kannst Dateien in diesem Forum herunterladen
MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.