Laden...

Picturebox an Bildauschnitt anpassen

Erstellt von Elias1994 vor 8 Jahren Letzter Beitrag vor 8 Jahren 7.274 Views
E
Elias1994 Themenstarter:in
54 Beiträge seit 2015
vor 8 Jahren
Picturebox an Bildauschnitt anpassen

Hallo,

ich filme mit einer Webcam ein iPad. Der WebcamStream ist in einer pictureBox eingebunden.

Ich möchte, dass der Anwender zur Laufzeit die Größe der PictureBox ändern/verkleinern kann.
So, dass nacher auf dem Webcamstream nur noch das iPad zusehen ist und kein unnötiger Hintergund.

Ich habe schon probiert, dass mit Buttons zu lösen. Leider kann ich mit den Properties Width and High die PictureBox nur von OBEN und RECHTS her verändern/verkleinern.


        private void button1_Click(object sender, EventArgs e)
        {
            pictureBox1.Width = pictureBox1.Width - 1;
        }

       private void button2_Click(object sender, EventArgs e)
        {
            pictureBox1.Height = pictureBox1.Height - 1;
        }

Gibt es auch Eigenschaften, um die PictureBOx von LINKS und OBEN zu verändern?

oder wie würde ihr das Problem lösen?

Liebe Grüße,
Elias

E
Elias1994 Themenstarter:in
54 Beiträge seit 2015
vor 8 Jahren

So soll es danach aussehen:

eig sollte die picturebox hier kleiner sein.

Aber habe geschummelt indem ich die Webcam näher rangerückt habe.

Hier soll nur klar werden, dass man versteht welcher Teil noch in der pictureBox noch zu sehen sein soll.

771 Beiträge seit 2009
vor 8 Jahren

Hallo,

du willst also gar nicht die Größe der PictureBox verändern, sondern das enthaltene Bild zoomen, s z.B. Grafik in PictureBox vergrößern

Auf CodeProject gibt es auch eine fertige Komponente dafür: A Zoomable and Scrollable PictureBox

E
Elias1994 Themenstarter:in
54 Beiträge seit 2015
vor 8 Jahren

Beim Zoomen sehe ich aber das Problem, dass sich mein Bild:

verzerrt: meine PicBox ist momentan 640:480 groß. Das iPad hat aber ein ganz anderes Seitenverhältnis (nehmen wir mal quadratisch 400x400 an) würde ich das jetzt ranzoomen wäre mein qudratisch ipad als 640x480 Verhätnis abgebildet.

Das ist der Grund warum ich die Größe der PictureBox verändern lassen will. So kann ich immer je nachdem welches Seitenverhätnis das iPad hat durch Anpassen der Picturebox exakt dasselbe Seitenverhätnis bekommen.

Beispiel: Ist mein ipad wie oben z.B Qudratisch, könnte ich meine picture Box auch quadratisch ziehen.

Verstehst du was ich meine?

4.942 Beiträge seit 2008
vor 8 Jahren

Hallo,

die Position (links, oben) läßt sich über die Eigenschaften Left und Top ändern.

E
Elias1994 Themenstarter:in
54 Beiträge seit 2015
vor 8 Jahren

Ja aber die Position hilft mir ja da reichlich wenig. Ich will die pictureBox ja nicht verschieben.

Am liebsten wären mir 4 Buttons mit denen ich die picturebox von jeweils allen Seiten verkleinern kann.

Width und Height machen das ja schon teilweise. Nur verkleinern diese eben die PictureBox nur von OBEN und von RECHTS. Jetzt bräuchte ich noch was die pictureBox von LINKS und UNTEn her verkleinert.

1.040 Beiträge seit 2007
vor 8 Jahren

~~Du musst in dem Falle die Position und die Höhe/Breite ändern.

Beispiel:
Control.Left ist 0
Control.Width ist 100

Willst du Links verkleinern, setzt du Left auf 1 und Width auf 99.~~

EDIT: Wobei das eigtl. überhaupt nichts bringt, das Bild "wandert" dann mit.

E
Elias1994 Themenstarter:in
54 Beiträge seit 2015
vor 8 Jahren

Was ich mir auch noch vorstellen könnte:

Ich zeichne ein Rectangle über das iPad und die pictureBox soll sich dann auf die Größe des Rectangles einstellen.

Aber weiß nicht wie ich das umsetzen könnte.

3.825 Beiträge seit 2006
vor 8 Jahren

Hallo Elias,

Wenn Du Width und Height veränderst dann verändert sich die Größe des Bitmap rechts und unten (Location 0,0 ist oben links).

Wenn Du Width und Location.X gleichzeitig ändert dann änderst sich der rechte Rand.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

E
Elias1994 Themenstarter:in
54 Beiträge seit 2015
vor 8 Jahren

Hallo es geht ja um die pictureBox.

Habe eine pictureBox eingefügt und zwei Buttons:


private void button3_Right_Click(object sender, EventArgs e)
        {
           pictureBox1.Width = pictureBox1.Width - 5;
        }

private void button4_Top_Click(object sender, EventArgs e)
        {
           pictureBox1.Height = pictureBox1.Height - 5;
        }

Kannst ja mal selber ausprobieren: Picturebox, 2 Buttons und der obere Code. Es ist genau andersherum:

WIDTH wird von RECHTS kleiner.
HEIGHT wird von OBEN kleiner.

Wie soll mir da jetzt Location weiterhelfen?

Jetzt brauche ich noch 2 Buttons mit denen ich die Picturebox von LINKS und von UNTEN verkleinern kann.

1.040 Beiträge seit 2007
vor 8 Jahren

Kannst du kurz mal zeigen, wie die PictureBox definiert ist? Standardmäßig verkleinert sie sich nämlich rechts und unten.

Zum eigtl. Problem:
Selbst wenn du Links und Oben (oder bei dir unten) setzen könntest - was nicht geht - würde das nur bewirken, dass das Bild nach rechts oder unten (oder bei dir oben) herausgeschoben wird.

Du musst wohl oder übel ans Bild ran und dann ggf. mit dem Ändern der Position und der Breite/Höhe agieren.

E
Elias1994 Themenstarter:in
54 Beiträge seit 2015
vor 8 Jahren

Stimmt. sie verändert sich von rechts und unten. Mein Fehler 😄

Das sich das Bild herausschiebt wäre kein Problem.

Was ich vielelicht noch dazusagen sollte. Das ganze ist kein Image in der picture Box sondern ein WebcamStream.

Ich glaube deshalb fast das diese Idee besser wäre, wenn man die pictureBox von OBEN und LINKS nicht verkleinern kann:

Rectangle zur Laufzeit über das iPad ziehen und dann z.B. auf einen Button klicken so dass die pictureBox sich genau auf den Rectangle-Bereich anpasst. Da hapert es aber leider an der Umsetzung weshalb ich ersteres präferieren würde.

771 Beiträge seit 2009
vor 8 Jahren

Ein PictureBox stellt ein Bild dar, d.h. wenn du die Anzeige ändern willst, dann mußt du das Bild beschneiden, nicht die PictureBox.

Hier noch ein anderer Link: How to zoom an image in pictureBox? (ganz unten der funktionierende Code)

E
Elias1994 Themenstarter:in
54 Beiträge seit 2015
vor 8 Jahren

Was ich dann bräuchte:

Wie man ein Videostream zuschneidet?

2.298 Beiträge seit 2010
vor 8 Jahren

Dazu müssten wir erst einmal wissen, wie du den Video-Stream entgegen nimmst. - Die meißten Bibliotheken die ich kenne liefern nämlich Einzelbilder die man bearbeiten kann.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

E
Elias1994 Themenstarter:in
54 Beiträge seit 2015
vor 8 Jahren


using AForge.Video;
using AForge.Video.DirectShow;

private void Form1_Load(object sender, EventArgs e)
        {
            VideoCaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice); // devicesstored in array

            foreach (FilterInfo VideoCaptureDevice in VideoCaptureDevices)
            {
                comboBox1.Items.Add(VideoCaptureDevice.Name);
            }

            comboBox1.SelectedIndex = 0;
        }

        //void timer_Tick(object sender, EventArgs e)
        //{
        //    throw new NotImplementedException();
        //}

        private void button1_Click(object sender, EventArgs e)
        {
            FinalVideoSource = new VideoCaptureDevice(VideoCaptureDevices[comboBox1.SelectedIndex].MonikerString);
            FinalVideoSource.NewFrame += new NewFrameEventHandler(FinalVideoSource_NewFrame);
            FinalVideoSource.Start();
        }

        void FinalVideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            Bitmap image = (Bitmap)eventArgs.Frame.Clone();
            pictureBox1.Image = image;
        }

2.298 Beiträge seit 2010
vor 8 Jahren

Hallo,

habe ich es mir doch gedacht. In FinalVideoSource_NewFrame hängst du doch ein Bild an die PictureBox. - Genau dieses Bild musst du eben auch entsprechend bearbeiten.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

S
322 Beiträge seit 2007
vor 8 Jahren

Hallo,

du kannst auch die PictureBox in ein Panel reinlegen und dann hinausschieben...


private void button1_Click(object sender, EventArgs e)
{
    pictureBox1.Top -= 10;
}

private void button2_Click(object sender, EventArgs e)
{
    pictureBox1.Top += 10;
}

private void button3_Click(object sender, EventArgs e)
{
    pictureBox1.Left -= 10;
}

private void button4_Click(object sender, EventArgs e)
{
    pictureBox1.Left += 10;
}

Die Picturebox kannst dann auf "SizeMode=Autosize" stellen.
Dann kannst Du noch die Größe von dem Panel extra ändern (Width und Height). (D.h. der Bildausschnitt wird größer).

5.658 Beiträge seit 2006
vor 8 Jahren

Hi Elias1994,

das Zoomen ist doch völlig unabhängig von der Größe der PictureBox. Evtl. solltest du dir auch überlegen, ob eine PictureBox überhaupt das Richtige für diesen Anwendungsfall ist. Besser wäre es, das Zeichnen des Bildes so wie in [Tutorial] Zeichnen in Windows-Forms-Programmen (Paint/OnPaint, PictureBox) umzusetzen. Dann kannst du auch gleich die richtige Überladung der Graphics.DrawImage-Methode verwenden, die einen bestimmten Ausschnitt aus einem Bild in einen bestimmten Ausschnitt auf die Form zeichnet. Damit sparst du dir die Nachbearbeitung der von der WebCam gelieferten Bilder.

Christian

Weeks of programming can save you hours of planning

E
Elias1994 Themenstarter:in
54 Beiträge seit 2015
vor 8 Jahren

Hallo zusammen,

habe nun ein Projekt gefunden mit dem das für ein Bild funktioniert.

Projekt Image cropping

Oben habe ich ja einen ja gepostet wie mein Webcamstream einbinde.
Wie muss ich den Code verändern, dass das auch für mein Video funktioniert?

Gruß,
Elias

E
Elias1994 Themenstarter:in
54 Beiträge seit 2015
vor 8 Jahren

In dem oben verlinkten Projekt wird das so gelöst:

        public static Image Crop(this Image image, Rectangle selection)
        {
            Bitmap bmp = image as Bitmap;

            // Check if it is a bitmap:
            if (bmp == null)
                throw new ArgumentException("Kein gültiges Bild (Bitmap)");

            // Crop the image:
            Bitmap cropBmp = bmp.Clone(selection, bmp.PixelFormat);

            // Release the resources:
            image.Dispose();

            return cropBmp;
        }

aber wie mache ich das für meinen Webcamstream?

1.029 Beiträge seit 2010
vor 8 Jahren

Hi,

ganz ehrlich? Ich glaub deinen "eigenen" Code solltest du dir wirklich noch einmal anschauen... Du bindest nämlich mitnichten einen Stream an deine PictureBox - sondern machst bei jeder Bildaktualisierung ein neues Bild in deine PictureBox. Und mit diesem Bild - kannst du ungefähr machen was du möchtest.

Vorgehensweise:

  1. Hilfsklasse anlegen - z.B. ImageHelper - sieht dann so aus:
static class ImageHelper
{
	public static Image Crop(this Image image, Rectangle selection)
	{
		Bitmap bmp = image as Bitmap;

		// Check if it is a bitmap:
		if (bmp == null)
			throw new ArgumentException("No valid bitmap");

		// Crop the image:
		Bitmap cropBmp = bmp.Clone(selection, bmp.PixelFormat);

		// Release the resources:
		image.Dispose();

		return cropBmp;
	}
}
  1. Hilfsklasse auch benutzen (Abwandlung deines Codes):
void FinalVideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
	Bitmap image = (Bitmap)ImageHelper.Crop(eventArgs.Frame, new Rectangle(30, 30, 300, 300));
	pictureBox1.Image = image;
}
  1. Danach kannst du dir Gedanken machen, wie du die Auswahl eines entsprechenden Rectangles machst. Können wieder Textboxen sein - können auch Trackbars sein - oder gar auf UserClick ein entsprechendes Rectangle in die Picturebox zeichnen.

LG

16.842 Beiträge seit 2008
vor 8 Jahren

Uhh das Dispose in einer Helfterklasse.. da wäre ich vorsichtig.
Das ist von Außen überhaupt nicht erkenntlich und eher ungewöhnlich, dass das in so einer Methode passiert.

E
Elias1994 Themenstarter:in
54 Beiträge seit 2015
vor 8 Jahren

Hey Taipi,

dein Ansatz sieht vielversprechend aus.
Das Rechteck zeichne ich mit Mousevents:

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
		{
			// Starting point of the selection:
			if (e.Button == MouseButtons.Left)
			{
				_selecting = true;
				_selection = new Rectangle(new Point(e.X, e.Y), new Size());
			}
		}
		//---------------------------------------------------------------------
		private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
		{
			// Update the actual size of the selection:
			if (_selecting)
			{
				_selection.Width = e.X - _selection.X;
				_selection.Height = e.Y - _selection.Y;

				// Redraw the picturebox:
				pictureBox1.Refresh();
			}
		}
		//---------------------------------------------------------------------
		private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
		{
			if (e.Button == MouseButtons.Left && _selecting)
			{
				// Create cropped image:
				Image img = pictureBox1.Image.Crop(_selection);

				// Fit image to the picturebox:
				pictureBox1.Image = img.Fit2PictureBox(pictureBox1);

				_selecting = false;
			}
		}
		//---------------------------------------------------------------------

Die Image Crop und Fit2Picturebox (s.MouseUp) habe ich jetzt in eine statische Klasse ausgelagert.

Fit2PictureBox:

public static Image Fit2PictureBox(this Image image, PictureBox picBox)
        {
            Bitmap bmp = null;
            Graphics g;

            // Scale:
            double scaleY = (double)image.Width / picBox.Width;
            double scaleX = (double)image.Height / picBox.Height;
            double scale = scaleY < scaleX ? scaleX : scaleY;

            // Create new bitmap:
            bmp = new Bitmap(
                (int)((double)image.Width / scale),
                (int)((double)image.Height / scale));

            // Set resolution of the new image:
            bmp.SetResolution(
                image.HorizontalResolution,
                image.VerticalResolution);

            // Create graphics:
            g = Graphics.FromImage(bmp);

            // Set interpolation mode:
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;

            // Draw the new image:
            g.DrawImage(
                image,
                new Rectangle(          // Ziel
                    0, 0,
                    bmp.Width, bmp.Height),
                new Rectangle(          // Quelle
                    0, 0,
                    image.Width, image.Height),
                GraphicsUnit.Pixel);

            // Release the resources of the graphics:
            g.Dispose();

            // Release the resources of the origin image:
            image.Dispose();

            return bmp;
        }
    }

Jetzt fehlt mir eigentlich nur noch void FinalVideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs) anzupassen.

Kannst du mir da nochmal helfen?

Viele Grüße,
Elias

5.658 Beiträge seit 2006
vor 8 Jahren

Ich verstehe wirklich nicht, warum du so einen Aufwand betreiben willst, wo doch ein Aufruf der DrawImage-Methode ausreichen würde, um den richtigen Bildausschnitt an der richtigen Stelle darzustellen.

Christian

Weeks of programming can save you hours of planning

E
Elias1994 Themenstarter:in
54 Beiträge seit 2015
vor 8 Jahren

Verwende ich doch. 😄 (s.o.)
Das Problem ist glaube ich, dass eben ständig neue Bilder erezugt werden, deshalb wirkt es ja wie ein Stream. Für ein Bild funktioniert das Ganze problemlos.

5.658 Beiträge seit 2006
vor 8 Jahren

Du zeichnest ein Bild in ein anderes Bild, dafür verwendest du die Methode. Aber dann verwendest du zusätzlich noch die PictureBox, um das Bild darzustellen. In dem von mir verlinkten Artikel wird beschrieben, wie man stattdessen vorgehen sollte. Evtl. solltest du nochmal dort nachlesen, denn es erspart dir am Ende eine Menge Arbeit.

Daß in einem Video ständig neue Bilder angezeigt werden, ist ja irgendwie klar 🤔
In deinem ursprünglichen Code-Beispiel reagierst du doch auch darauf... Du mußt halt nur die Zuweisung des Bildes an die PictureBox ändern (bzw. stattdessen in der OnPaint-Methode zeichnen).

Irgendwie macht es den Eindruck, als würdest du lediglich Codeschnipsel aus dem Internet copy & pasten, ohne zu wissen, was der Code eigentlich genau macht.

Christian

Weeks of programming can save you hours of planning

E
Elias1994 Themenstarter:in
54 Beiträge seit 2015
vor 8 Jahren

Konnte das Problem jetzt lösen. Wer den Code brauch und in Zukunft auf dieses Thema stößt kann mir gerne eine PN schreiben.

J
251 Beiträge seit 2012
vor 8 Jahren

Theo. wäre es vom Vorteil die Lösung des Problems hier zu erläutern falls jemand auf diese Problematik stößt.

Immerhin wurde Dir wohl erfolgreich geholfen bzw. wurdest Du zur Lösung erfolgreich begleitet.