Hallo Kollegen,
ich hatte 2007 einen Client für einen bestimmten Chat entwickelt. Er funktioniert aber inzwischen nicht mehr, da sich der Chat natürlich auch weiterentwickelt hat.
Da ich immer noch viele kontakte darüber herstelle und inzwischen wieder viel in diesem Chat drin bin, würde ich diesen gerne wieder zum Laufen bringen.
Inzwischen ist die Situation so:
1.)
Über ein Java-Applet in dem die Texte dargestellt werden, wird alles angezeigt. Hier laufen die Nachrichten nach unten die aus dem Channel kommen, in dem man sich befindet. Jede Nachricht eines Users verschiebt diesen Text nach unten.
2.)
Zusätzlich gibt es noch eine Textbox für die eigenen Eingaben.
Jetzt mein Problem:
Ich möchte das bei 1.) beschriebene Fenster mit dem Text auslesen.
Ich hab das aber noch nie auf diese Art im Browser ausprobiert. Versucht habe ich es in IE und im FireFox. Ich finde zwar das Fenster (Hab ich zuerst per Spy++) ausprobiert, aber wenn ich mir über ein WM_GETTEXT den Inhalt des textfensters holen möchte ist der String leer.
Jetzt hab ich schon öfter gelesen, dass Firefox und andere Browser alles selbst zeichnen. (Den Inhalt). Ist das der Grund warum ich keinen text bekomme?
Oder ermittle ich das Fenster falsch?
Das Fenster das ich erhalte ist vom Typ MozillaWindowClass wenn ich den FireFox benutze.
Momentan habe ich auch probiert, direkt die ID des Handles anzugeben, dass mir Spy++ ermittelt. Denn das sollte ja das richtige Fenster sein, oder evtl. ein Untercontrol davon. Beides funktioniert bisher nicht.
Für alle die es noch nicht kennen, weil ich vor kurzem darauf aufmerksam wurde:
Auszug der Beschreibung:
Let’s face it, no library has it all, and the BCL is no exception. If you’re anything like me, then you occasionally find yourself re-writing some utility methods over and over again for each project that you work on. Even though you know it’s wrong, you probably re-invent the wheel from time to time for “simple” things. Maybe you carry around your own “MyUtilities.cs” file from project to project. Either way, in the back of your mind, you know that there has to be a better way.
For C++ programmers, this void is filled with Boost. Boost contains a lot of functionality that is missing from the C++ STL for one reason or another. It’s a great library for C++ development. But what about us poor C# developers?
That’s where Elevate comes in. Elevate is a Boost-like library for .NET. Our goal at SRT Solutions is to capture the things that we think are missing from the BCL and put them in Elevate so that we can share them between our project groups and the rest of the world. By devoting some of our weekly learning time to add these common bits of code to Elevate, we can save ourselves, our clients, and hopefully other .NET developers time and money.
Kurz in eigenen Worten ein paar konkrete Beispiele:
Wenn ein paar Werte und eine "Sequenz" von Werten in eine neue "Sequenz" kopiert werden sollen, dann kann das mit Elevate folgendermaßen geschehen:
//if you have a couple sequences of values
var first = Seq.Build("alpha", "beta");
var second = Seq.Build("delta", "epsilon");
//you can combine them along with some other values to create a new sequence
var result = Seq.Build(first, "gamma", second, "zeta");
Schön ist das man ein IEnumerable des generischen Typs erhält, dann man durchiterieren kann.
Komfortabel sind auch die Option Types, mit denen man einen Programmieraspekt von F# bezüglich des Patternmatchings für C# verfügbar gemacht hat.
var values = 0.Through(10);
Option<int> result = values.TryFind(x => x == 5);
Zeile 1 im obenstehenden Code generiert eine aufsteigende Zeichenfolge.
(0,1,2,3,4,5,6,7,8,9,10)
Zeile 2 findet in dieser Sequenz den Wert 5.
Option Types nochmal kurz zur Erklärung Auszug aus einem Artikel über F#:
Simply put, an option type wraps a value with information indicating whether or not the value exists. For C# or VB programmers, it may be convenient to think of option types as a mutant cross between .NET 2.0 nullable types and the null object design pattern.
Und der Link dazu, falls jemand bei F# nachlesen möchte, was Option Types sind:
Ein weiteres interessantes Konstrukt bilden dabei die LINQ-Erweiterungen.
//we can apply a selector function to each element based
//on the element's value and it's index
var result = values.SelectWithIndex((index, value) =>
value / (index + 1));
@Fzelle: Genau auf diese Lösung bin ich inzwischen auch gekommen.
Und zwar mache ich das per Script.
Am Anfang wird jetzt:
use master
benutzt.
Ich werde es hier als Lösung, wenn ich die kürzeste richtige Version gefunden habe, hier posten.
Alternativ dazu kannst Du auch noch hier:
[gelöst] Lambda Funktionen in einem Script bzw. zur Laufzeit kompilierten Code.
(Stichwort: ScriptCompiler2)
und hier:
LowLevelGraphicsLibrary (ebenfalls nach Stichwort ScriptCompiler2 suchen oder den Code herunterladen und darin suchen)
s. für das Prinzip auch:
Objekte an Laufzeit kompilierten Code übergeben oder auslesen (allgemeine Kommunikation)
verwendetes Datenbanksystem: MSSQL 2000
Hallo Kollegen.
Ich verwende momentan untenstehenden Code, um eine Datenbank auszuhängen:
(ausnahmsweise in VB gepostet)
Dazu benutze ich den Befehl sp_detach_db, Microsoft schreibt dazu folgendes:
Außerdem steht ja bei Microsoft:
sp_detach_db (Transact-SQL)
Detaches a database that is currently not in use from a server instance and, optionally, runs UPDATE STATISTICS on all tables before detaching.
Der Befehl funktioniert an sich, aber ich bekomme folgende Meldung:
Cannot detach DB 'xxx' that is currently in use.
Und im Microsoft Zitat steht ja auch, dass das nur geht, wenn die Datenbank momentan nicht in Benutzung ist.
Seh ich alles ein, nur da ich gerade selber nicht direkt auf die DB zugreife, wie bekomme ich es hin, dass diese DB nicht in Benutzung ist?
Public Function DetachDatabase(ByVal _sDatabaseName As String) As Integer Dim sQuery As New StringBuilder(string.Format("EXEC sp_detach_db @DBName = N'{0}'",_sDatabaseName)) Dim command As New SqlCommand(sQuery.ToString(), CreateSQLConnection()) Dim nResult As Integer = command.ExecuteNonQuery() Return nResult End Function
Alternative ist:
sp_helpdb
Ausgabe, s. Screenshot
Interessant dürfte für viele zu Lesen sein, dass Postsharp inzwischen als Version 2.0 zur Verfügung steht
hier ein Auszug der interessantesten Features:
New features of PostSharp 2.0 over 1.5 include:
* Visual Studio Extension – for easier code reading
* Composite Aspects (Advices and Pointcuts) – for more powerful aspects
* Adaptive Code Generation – for better runtime performance
* Aspect Dependencies – to prevent conflicts between aspects in large projects
* Interception Aspects for Fields, Properties, and Events
* Instance-Scoped Aspects
* Build-Time Performance Improvements
For a detailed list of these features, see What’s New in PostSharp 2.0.
How To Upgrade from 1.5?
PostSharp 2.0 contains a library called PostSharp.Laos.dll. This is an emulation layer, and is meant to be used during the migration of 1.5 to 2.0. When you’ll build your project, you’ll get a lot of obsolescence warnings. When all these warnings are gone, you can remove the PostSharp.Laos.dll reference from your project. It’s only after complete migration that you will see improvements in runtime performance.
What’s New Since RC2?
The following issues were fixed:
* Invalid code generation when two MethodInterceptionAspects are applied on a method containing an anonymous method.
* Invalid code generation for pointer types ('valuetype' or 'class' keyword missing)
* Invalid code generation when an interception aspect is applied to a method containing a '.constrained' prefix
* Invalid code generation when multiple MethodInterceptionAspects are applied to a generic method
* When a method-level aspect is applied to an interface, it is not multicast to interface methods
* ILASM failure with symbol sequence points with a document but without a column
* KeyNotFoundException from MulticastAttributeTask.ImportCustomAttribute
Ich würde eine Perimeteroperation benutzen. Den Code kann er sich aus der Library extrahieren.
Hatte den falschen Link. Jetzt müsstest Du drauf klicken können. Versuchs nochmal.
@Dennisspohr du kannst auch hier nachsehen:
falls Du vielleicht einige Filter verwenden möchtest, die so nicht so einfach zu realisieren sind. Allerdings verwendet diese Library an vielen Stellen eine Per-Pixel-Methode im unsafecontext.
Also als wirklich langsam würde ich das nicht gerade bezeichnen bei konkret diesen Filtern.
EDIT: Link korrigiert.
@Blackhawk5000: Danke für das Kompliment. Falls Du versuchst das mit der Lib zu lösen kannst Du auch gerne PMs schicken und wir veröffentlichen dann die Antwort hier im Forum.
An der Stelle an der Deine neue Grafik generiert wird, also wenn der User etwas verändert, wird da
InvalidateRect aufgerufen?
Mache regelmäßig Kraftsport im Fitness-Studio. Bis zu 5 Einheiten die Woche, die letzten Monate nur 2 mal pro Woche, zu viel Zeit am Projekt in der Firma verbracht.
@ingemar: s. dazu auch:
Suche Programm, das das Rucksack/Knapsack löst und visualisiert
verwendetes Datenbanksystem:MS SQL 2000
Wir benutzen in der Firma leider immer noch MS SQL 2000.
Ich möchte gerne per Notification Services Events einrichten in meiner Applikation.
Der Code existiert quasi schon.
Die Frage ist nur, wie bekomme ich die Notification Services FÜR SQL 2000 installiert?
Mir fehlen die Dateien, um es nachzuinstallieren.
Was ich bei Microsoft gelesen habe, bringt mich momentan nicht weiter, angeblich gibt es auch die Downloads noch online, aber alle Links auf die Microsoft für SQL 2000 verweise funktionieren nicht.
Habe folgende Suchbegriffe in Google benutzt:
MS SQL 2000 "Notification Services"
Microsoft SQL 200 NS
Microsoft SQL 200 "Notification Services"
u. ähnliche Varianten
P.S.: der Namespace
using Microsoft.SqlServer.NotificationServices;
ist deswegen auch noch nicht vorhanden....
Ich denke hier steht die Antwort:
Normalerweise sollte das so funktionieren, ohne zusätzliches zutun. Es reicht im Designer in ContextMenuStrip ein Hintergrundbild einzufügen.
Das Bild verschwindet normalerweise auch nicht.
unter WPF:
s. auch hier:
Unter windows forms:
hier kann in ToolTip Rectangle u anderen Properties angegeben werden, was benötigt wird:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
//using System.Windows.Forms;
using System.Collections;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace Library.Controls
{
public class CAbstractToolTip: System.ComponentModel.Component,Interfaces.IToolTip, IExtenderProvider
{
[DllImport("user32.dll")]
protected static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
protected static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll")]
protected static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32.dll")]
protected static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("gdi32.dll")]
protected static extern int ExcludeClipRect(IntPtr hdc,
int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
[DllImport("user32.dll")]
protected static extern IntPtr CreateWindowEx(int exstyle, string classname, string windowtitle, int style, int x, int y, int width, int height, IntPtr parent, int menu,
int nullvalue, int nullptr);
[DllImport("user32.dll")]
protected static extern int DestroyWindow(IntPtr hwnd);
[DllImport("User32.dll")]
protected static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
[DllImport("User32.dll")]
protected static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);
[Serializable, StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public RECT(int left_, int top_, int right_, int bottom_)
{
Left = left_;
Top = top_;
Right = right_;
Bottom = bottom_;
}
public int Height { get { return Bottom - Top; } }
public int Width { get { return Right - Left; } }
public Size Size { get { return new Size(Width, Height); } }
public Point Location { get { return new Point(Left, Top); } }
// Handy method for converting to a System.Drawing.Rectangle
public Rectangle ToRectangle()
{ return Rectangle.FromLTRB(Left, Top, Right, Bottom); }
public static RECT FromRectangle(Rectangle rectangle)
{
return new RECT(rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Bottom);
}
public override int GetHashCode()
{
return Left ^ ((Top << 13) | (Top >> 0x13))
^ ((Width << 0x1a) | (Width >> 6))
^ ((Height << 7) | (Height >> 0x19));
}
#region Operator overloads
public static implicit operator Rectangle( RECT rect )
{
return Rectangle.FromLTRB(rect.Left, rect.Top, rect.Right, rect.Bottom);
}
public static implicit operator RECT( Rectangle rect )
{
return new RECT(rect.Left, rect.Top, rect.Right, rect.Bottom);
}
#endregion
}
protected struct Toolinfo
{
public int size;
public int flag;
public IntPtr parent;
public int id;
public Rectangle rect;
public int nullvalue;
[MarshalAs(UnmanagedType.LPTStr)]
public string text;
public int param;
}
// Used by some constants values, not by the code.
protected const int WM_USER = 0x0400;
protected const int TTM_ADDTOOL = WM_USER + 50;
protected const int TTM_DELTOOL = WM_USER + 51;
protected const int TTM_ACTIVATE = WM_USER + 1;
protected const int TTM_SETMAXTIPWIDTH = WM_USER + 24;
protected const int TTM_SETTITLE = WM_USER + 33;
protected const int TTM_SETDELAYTIME = WM_USER + 3;
protected const int TTM_UPDATETIPTEXT = WM_USER + 57;
protected const int TTM_SETTIPBKCOLOR = WM_USER + 19;
protected const int TTM_SETTIPTEXTCOLOR = WM_USER + 20;
protected const int TTM_GETTOOLINFO = WM_USER + 53;
protected const int TTM_SETTOOLINFO = WM_USER + 54;
protected const int TTS_ALWAYSTIP = 0x01;
protected const int TTS_NOPREFIX = 0x02;
protected const int TTS_BALLOON = 0x40;
protected const int TTF_SUBCLASS = 0x0010;
protected const int TTF_TRANSPARENT = 0x0100;
protected const int SWP_NOSIZE = 0x0001;
protected const int SWP_NOMOVE = 0x0002;
protected const int SWP_NOACTIVATE = 0x0010;
protected const int TTDT_AUTOPOP = 2;
protected const int TTDT_INITIAL = 3;
protected const int WS_POPUP = unchecked((int)0x80000000);
protected const int CW_USEDEFAULT = unchecked((int)0x80000000);
protected IntPtr TOPMOST = new IntPtr(-1);
private Image m_Image = null;
private int m_nWidth = 0;
private int m_nHeight = 0;
private bool m_bOwnerDraw = false;
private bool m_bShowAlways = false;
private Color m_clFore = Color.Black;
private Color m_clBack = Color.Transparent;
private int m_nReshowDelay = 500;
public event EventHandler Draw; //don't delete this, needed from the caller, not in need to use it here
private System.ComponentModel.Container components = null; //this has also be here, will be called from the infrastructure of the il
private CControls m_ControlCollection = null;
public CAbstractToolTip():base()
{
//this.Draw += new DrawExtToolTipEventHandler(ExtToolTip_Draw);
}
public CControls Controls
{
get
{
if (m_ControlCollection == null)
{
m_ControlCollection = new CControls();
}
return m_ControlCollection;
}
}
public virtual IntPtr Handle
{
get{ return IntPtr.Zero;}
}
public virtual int Height
{
get { return m_nHeight; }
}
public virtual int Width
{
get { return m_nWidth; }
}
public Image Image
{
get { return m_Image; }
set { m_Image = value; }//m_Image = new Bitmap(value, Height, Width); }
}
public void ExtToolTip_Draw(object sender,DrawExtToolTipEventArgs e)
{
}
#region IToolTip Member
public virtual bool Active
{
get
{
// TODO: Getter-Implementierung für ExtToolTip.Active hinzufügen
return false;
}
set
{
// TODO: Getter-Implementierung für ExtToolTip.Active hinzufügen
}
}
public virtual int AutomaticDelay
{
get
{
// TODO: Getter-Implementierung für ExtToolTip.AutomaticDelay hinzufügen
return 0;
}
set
{
// TODO: Getter-Implementierung für ExtToolTip.AutomaticDelay hinzufügen
}
}
public virtual int AutoPopDelay
{
get
{
// TODO: Getter-Implementierung für ExtToolTip.AutoPopDelay hinzufügen
return 0;
}
set
{
// TODO: Getter-Implementierung für ExtToolTip.AutoPopDelay hinzufügen
}
}
public virtual bool CanExtend(object oTarget)
{
// TODO: Implementierung von ExtToolTip.CanExtend hinzufügen
return false;
}
public object GetLifeTimeServer()
{
// TODO: Implementierung von ExtToolTip.GetLifeTimeServer hinzufügen
return null;
}
public string GetToolTip(Control control)
{
// TODO: Implementierung von ExtToolTip.GetToolTip hinzufügen
return null;
}
public virtual int InitialDelay
{
get{ return 0;}
set{}
}
public void RemoveAll()
{
// TODO: Implementierung von ExtToolTip.RemoveAll hinzufügen
}
public int ReshowDelay
{
get { return m_nReshowDelay; }
set { m_nReshowDelay = value; }
}
public virtual void SetToolTip(Control control, string sCaption)
{
// TODO: Implementierung von ExtToolTip.SetToolTip hinzufügen
}
public bool ShowAlways
{
get{ return m_bShowAlways; }
set{ m_bShowAlways = value;}
}
public bool OwnerDraw
{
get{ return m_bOwnerDraw;}
set{ m_bOwnerDraw = value;}
}
public virtual Color ForeColor
{
get{ return m_clFore;}
set{ m_clFore = value;}
}
public virtual Color BackColor
{
get{ return m_clBack;}
set{ m_clBack = value;}
}
#endregion
public virtual Rectangle ClientRectangle
{
get{ return Rectangle.Empty;}
}
protected virtual void InitializeComponent()
{
}
#region IDisposable Member
#endregion
}
}
Ich vermute, dass die extern angebundene Anwendung Dateien benötigt, die nicht im Projekt Verzeichnis von Dir liegen. (Initialisierungsdateien, DLL, sonstiges)...
Probier mal dein Projekt in das Verzeichnis der Anwendung zu kopieren,
kann jetzt ohne Probleme gehostet werden?
Hast Du mal versucht das GIF beim ImageAnimator anzumelden? (System.Drawing)
Interessant für tests:
Microsoft VS 2008 - Spec Explorer (natürlich auch für VS2010)
@Ralfw:
Betriebswirtschaftliche Sicht, volkswirtschaftliche Auswirkung, eindeutiges Umfrageergebnis... das ist alles richtig... aber es wird Rainbird und anderen wenig helfen. Es geht einfach nicht um "Objektivität" oder "harte Fakten".
Es wird ihm vielleicht nicht direkt helfen, aber die Nachfrage Rainbirds nach einer Studie - mit Ergebnis - würde ich doch als in diese Richtung gehend werten.
Das macht das Thema so nervig. Andererseits macht es das Thema aber auch interessant. Denn ich würde gern eruieren, was das Wurzelproblem bei den heutigen "Unit Test Verweigerern" ist. Ist natürlich schwer rauszufinden. Die selbst sind ja quasi per definitionem nicht in der Lage das zu reflektieren.
Hier ein paar Aussagen, die ich bisher aus mehreren Firmen gehört habe:
"Automatische Tests? Unit-Tests? Die muss man selber schreiben? Das kostet zu viel Zeit und verzögert das Projekt"
"Bis ich das alles eingerichtet habe...Puh! Was das Zeit kostet..."
"Was bringt das?"
Wie schon erwähnt wurde: Ablehnung neuem Gegenüber, Angst vor neuem, vielleicht auch ein wenig Zurückhaltung, um es mal nicht Faulheit zu nennen.
Naja... sei´s drum. Beim Testen sehe ich zu meiner Freude, dass es auf die Branche gerechnet eigentlich kein großes Thema ist. Es tun noch nicht alle, aber das liegt eher nicht an Unverständnis oder Unwille, sondern am Umfeld.
Wir können uns daher darauf konzentieren zu überlegen, wie das Umfeld für diejenigen noch verändert werden kann, dass sie es tun können. Die anderen, die Unwilligen, sind eine schrumpfende Randgruppe.
Damit stimme ich überein. Oder anders formuliert: Immer mehr widmen sich dem Thema UnitTests und es wird geprüft, was bringt es mir und dem Projekt und damit letztendlich der Firma.
@Rainbird: Um nochmal auf Deine Fragen zu Beginn zurückzukommen:
wenn man der Fachpresse glaubt, dann gehören Unit-Tests zum Guten Ton in der Branche und sollten quasi eine Selbstverständlichkeit sein. Ist das wirklich so?
Ja, es ist so dass diese eine Selbstverständlichkeit SEIN SOLLTEN. (Aber nicht SIND).
Ich selbst habe Zeifel am Nutzen von Unit-Tests, wenn man den Aufand ins Verhältnis setzt...
Ich nenn mal ein Beispiel. Stell Dir vor Du hast ein GUI geschrieben. Es hat ein paar Methoden und macht was Du willst.
Jetzt willst Du es per Unit-Tests testen. Mußt Du etwas umschreiben, damit es testbar wird, weil vielleicht die benötigte Granularität fehlt?
Oder läßt es sich so gar nicht testen?
z.B. sind Methoden direkt abrufbar oder ist vielleicht mancher Code einfach nur direkt in den EventHandler programmiert?
Ich glaube anhand einiger solcher Fragen sieht man ob etwas umgeschrieben werden muss.
So und jetzt nochmal zurück:
Führt der sachgemäße Einsatz von Unit-Tests tatsächlich zu qualitativ hochwertiger Software?
Was geht wohl schneller, Code a little test a little and then test a little more (Bugfixes)
oder gleich "aufs Knöpfchen drücken" und sich vom Unittest aussagen lassen, wo etwas fehlgeschlagen ist?
So gesehen kann man zumindest behaupten:
Es führt zu weniger Fehler in derselben Zeit und das auf jeden Fall bei längerfristigen Projekten. Und weniger Fehler machen zumindest einen Teil der Qualität aus. Weniger Zeit heißt doch dass die Produktivität gesteigert wird.
Aber wie Du auch schon erwähntest:
Dir fehlt eben immer noch eine empirische Studie.
noch einen gefunden:
Zitat:
Versteht mich bitte nicht falsch...
Ich verstehe Dich schon richtig, denke ich. Du möchtest einfach einen stichhaltigen Beweis WAS BRINGEN UNITTESTS?
Im Abschnitt "Overview" auf der im Link genannten Seite heißt es:
A study conducted by NIST in 2002 reports that software bugs cost the U.S. economy $59.5 billion annually. More than a third of this cost could be avoided if better software testing was performed.[3]
Ich denke das könnte interessant sein:
und auch dieser Link:
EDIT: @Rainbird: Wir könnten auch selber eine Studie starten, mit 2 unabhängigen Gruppen (Das können auch einzelne Entwickler sein)
Eine Gruppe benutzt Unit Tests mit allen möglichen Vorteilen. Die andere nicht.
Was passiert?
(Unten gibts ein Bild...)
Diese Version kann benutzt werden, um von der aktuellen System.Windows.Forms.PictureBox loszukommen.
Wird der ImageLayout / BackgroundImageLayout auf None gesetzt, hat das Zoomen mit dem Zoomfaktor ebenfalls eine Auswirkung.
1.0f = Vergrößerungsfaktor 1
d.h. also alles was ScaleFactor>1 ist vergrößert, alles was ScaleFactor<1 ist verkleinert.
d.h. diese PictureBox kann sowohl gescrollt werden als auch den Fokus erhalten.
Die Fokusfarbe ist auswählbar.
Es können also auch mit dem Designer mehrere dieser PictureBoxen auf ein Form gesetzt werden und diese können dann mit TAB durchgtabbed werden.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.ComponentModel;
using System.Drawing;
namespace LowLevelGraphics.CustomControls
{
/// <summary>
///
/// </summary>
public class SelectablePictureBox : ScrollableControl, ISupportInitialize
{
protected Image m_Image = null;
protected float m_Zoom = 1.0f;
protected InterpolationMode m_InterpolationMode = InterpolationMode.High;
protected Color m_FocusColor = Color.White;
public SelectablePictureBox()
{
this.DoubleBuffered = true;
this.AutoScroll = true;
SetStyle(ControlStyles.Selectable, true);
this.TabStop = true;
}
[Category("Appearance")]
[Description("The interpolation mode used to smooth the drawing")]
public InterpolationMode InterpolationMode
{
get { return m_InterpolationMode; }
set { m_InterpolationMode = value; }
}
[Category("Appearance")]
[Description("The image to be displayed")]
public Image Image
{
get { return m_Image; }
set
{
m_Image = value;
UpdateScaleFactor();
Invalidate();
}
}
[Category("Appearance")]
[Description("The color of the focus rectangle if focused")]
public Color FocusColor
{
get { return m_FocusColor; }
set { m_FocusColor = value; }
}
[Category("Appearance")]
[Description("The zoom factor. Less than 1 to reduce, more than 1 to magnify")]
public float Zoom
{
get { return m_Zoom; }
set
{
if ((value < 0) || (value < 1E-05))
{
value = 1E-05F;
}
m_Zoom = value;
UpdateScaleFactor();
Invalidate();
}
}
public override Image BackgroundImage
{
get
{
return m_Image;
}
set
{
this.m_Image = value;
Invalidate();
}
}
protected void UpdateScaleFactor()
{
if (m_Image == null)
{
AutoScrollMargin = this.Size;
}
else
{
AutoScrollMinSize = new Size((int)(m_Image.Width * m_Zoom + 0.5f), (int)(m_Image.Height * Zoom + 0.5f));
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
//clear implementation: normally there would be a draw routine this overridance clears it
}
protected override void OnMouseDown(MouseEventArgs args)
{
base.OnMouseDown(args);
this.Focus();
}
protected override void OnKeyPress(KeyPressEventArgs args)
{
if (args.KeyChar == '\r')
{
OnClick(EventArgs.Empty);
}
else
{
base.OnKeyPress(args);
}
}
protected override void OnEnter(EventArgs args)
{
base.OnEnter(args);
this.Invalidate();
}
protected override void OnLeave(EventArgs e)
{
base.OnLeave(e);
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
if (m_Image == null)
{
OnPaintBackground(e);
return;
}
switch (this.BackgroundImageLayout)
{
case ImageLayout.Center:
Size sizeCenter = m_Image.Size;
Point ptCenter = Center(sizeCenter);
g.DrawImage(m_Image, ptCenter.X, ptCenter.Y, sizeCenter.Width, sizeCenter.Height);
break;
case ImageLayout.Stretch:
g.DrawImage(m_Image, new Rectangle(0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height), 0, 0, m_Image.Width, m_Image.Height, GraphicsUnit.Pixel);
break;
case ImageLayout.Tile:
TextureBrush texture = new TextureBrush(m_Image);
texture.WrapMode = WrapMode.Tile;
g.FillRectangle(texture,
new RectangleF(0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height));
break;
case ImageLayout.Zoom:
Size sizeAspectRatio = AspectRatio();
Point ptCenterZoom = Center(sizeAspectRatio);
g.DrawImage(m_Image, ptCenterZoom.X, ptCenterZoom.Y, sizeAspectRatio.Width, sizeAspectRatio.Height);
break;
case ImageLayout.None:
ApplyZoom(e);
g.DrawImage(m_Image, new Rectangle(0, 0, m_Image.Width, m_Image.Height), 0, 0, m_Image.Width, m_Image.Height, GraphicsUnit.Pixel);
break;
}
base.OnPaint(e);
if (this.Focused
&& this.CanFocus)
{
DrawFocusRectangle(g);
}
}
private void DrawFocusRectangle(Graphics g)
{
Brush focusBrush = new SolidBrush(m_FocusColor);
Pen focusPen = new Pen(focusBrush, g.DpiX / 12);
g.DrawRectangle(focusPen,
this.ClientRectangle);
focusPen.Dispose();
focusBrush.Dispose();
}
private Point Center(Size size)
{
int x = this.ClientRectangle.Width / 2 - size.Width / 2;
int y = this.ClientRectangle.Height / 2 - size.Height / 2;
return new Point(x, y);
}
/// <summary>
/// Ensure aspect ratio.
/// </summary>
/// <param name="size">The size.</param>
/// <returns></returns>
private Size AspectRatio()
{
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
int nSourceWidth = m_Image.Width;
int nSourceHeight = m_Image.Height;
nPercentW = ((float)Width / (float)nSourceWidth);
nPercentH = ((float)Height / (float)nSourceHeight);
int nDestinationX = 0;
int nDestinationY = 0;
if (nPercentH < nPercentW)
{
nPercent = nPercentH;
nDestinationX = System.Convert.ToInt16((Width -
(nSourceWidth * nPercent)) / 2);
}
else
{
nPercent = nPercentW;
nDestinationY = System.Convert.ToInt16((Height -
(nSourceHeight * nPercent)) / 2);
}
int nDestinationWidth = (int)(nSourceWidth * nPercent);
int nDestinationHeight = (int)(nSourceHeight * nPercent);
return new Size(nDestinationWidth, nDestinationHeight);
}
/// <summary>
/// Applies the zoom.
/// </summary>
/// <param name="e">The <see cref="System.Windows.Forms.PaintEventArgs"/> instance containing the event data.</param>
private void ApplyZoom(PaintEventArgs e)
{
Matrix mx = new Matrix(m_Zoom, 0, 0, m_Zoom, 0, 0);
mx.Translate(this.AutoScrollPosition.X / m_Zoom, this.AutoScrollPosition.Y / Zoom);
e.Graphics.Transform = mx;
e.Graphics.InterpolationMode = m_InterpolationMode;
}
#region ISupportInitialize Members
public void BeginInit()
{
}
public void EndInit()
{
}
#endregion
}
}
@Rainbird:
Ein Verweis hierauf sei noch erwähnt:
Meine Erfahrungen zu Unit-Tests
Auszug aus Clean Code:
The moral of the story is simple: Test code is just as important as production code. It
is not a second-class citizen. It requires thought, design, and care. It must be kept as clean
as production code.
Außerdem sollte inzwischen TDD state of the Art sein, wie ja hier von anderen auch schon erwähnt wurde.
Ich habe nur gute Erfahrungen mit Unit-Tests gemacht.
Und man schreibt den Code doch etwas anders. Flexibler.
Außerdem hat man den Vorteil wenn man z.B.
benutzt, bekommt man tools wie Code Coverage durch die Unit-Tests zusätzlich hinzu oder ein Visual Studio plugin mit dem man direkt nur die zu testende Methode ausführen lassen kann, egal ob im Test oder direkt im produktiven Code. Sehr zeitsparend.
Ich behaupt einfach mal dass Unit-Tests ab einem bestimmten Projektumfang IMMER den Zeitaufwand hinten raus reduzieren.
Und dass der produktive Code durch die Unittests besser wird, ist IMHO auch Tastache.
Auch die Conclusion aus Clean Code spricht für sich und kann der Aussage nur zustimmen:
Conclusion
We have barely scratched the surface of this topic. Indeed, I think an entire book could be
written about clean tests. Tests are as important to the health of a project as the production
code is. Perhaps they are even more important, because tests preserve and enhance the
flexibility, maintainability, and reusability of the production code. So keep your tests constantly
clean. Work to make them expressive and succinct. Invent testing APIs that act as
domain-specific language that helps you write the tests.
If you let the tests rot, then your code will rot too. Keep your tests clean.
@Janismac:
Eine weitere Möglichkeit ist über einen sogenannten
Eye-Dropper
Quasi den Pixel über den Desktop ermitteln ohne einen Screenshot zu machen.
s. auch:
EDIT: Anmerkung: Dieser reagiert dann natürlich auf ALLE pixel auf dem Screen.
@sevo:
Ansonsten muss eine Umrechnungsroutine programmiert werden, wie Janismac schon
richtig die Richtung gezeigt hat. Denn wenn verzerrt bzw. skaliert angezeigt wird, wirst Du sonst nicht das richtige Pixel unter dem Mauszeiger bekommen.
Ganz andere Alternative: Eingabe per Control und nicht den Mauszeiger mit Klick-Koordinaten benutzen. Ist aber eben meist nicht so komfortabel
@gfoidl: Ich mach das in diesem Fall selbst. Ich hab vorgestern angefangen und die ersten Grafiken lassen sich schon darstellen.
😃
Ich kann schon einige Verkehrsschilder bei Wikipedia von
Bildtafel der Verkehrszeichen von Deutschland
anzeigen.
@realpk:
Wenn ich das neue Projekt dann online stelle kannst Du ausprobieren ob Du es mit der LowLevelGraphicsLibrary anzeigen kannst.
Nachtrag: da ich sowieso eine SVG-Anzeige benötige,
implementiere ich diese momentan selbst. Für die Anzeige
von Verkehrsschildern.
Aforge.net: Template Matching
Halcon: Template Matching
Wolfram: Template Matching
Open CV: Template Matching
LowLevelGraphicsLibrary: Template Matching
ebenso wie fast überall "Exhaustive Template Matching"
Außerdem liefert
Programmiersprache + Template Matching auch schon einiges...
in Google
...
usw.
@Scaer: Template Matching findet sich auch hier im Forum, einfach nur den Suchbegriff eingeben.
Ich habe die Aufgabe, eine Gesichtserkennung mit Eigenface zu schreiben, habe nur absolut keine ahnung wie ich das anstellen soll.
Ich werde im Internet nicht fündig.
Es findet sich alles im Internet bis zu fertigen Ansätzen. Aber es stimmt auch die Aussage, dass man oft selber Hand an den Code anlegen muss.
Ich habe schon mit Visual Studio alles soweit geschrieben, dass ich eine/meine Webcam ansprechen kann und auch schon ein Kreis automatisch um das Gesicht gemalt wird + das es dem Gesicht folgt und die größe ändert etc.
Wie hast Du diesen Teil programmiert? Was für Methodiken hast Du angewendet.
Die große Frage ist jetzt, wie schaffe ich es, das ich ein Gesicht erkennen kann und mir dann z.B. sagt Hallo Herr XYZ, wenn ich von dem Gesicht vorher ein Bild gemacht habe und das abgespeichert hab.
Habe ich das richtig verstanden, Du kannst das Gesicht schon lokalisieren?
Wenn ja, dann berechne z.B. die verscheidenen Eigenfaces der verschiedenen Personen die erkannt werden sollen, und speichere Dir diese ab.
Dann ermittelst Du anhand einer Matching-Methode (TemplateMatching, ExhaustiveTemplateMatching, Histogrammbasiertes TemplateMatching) oder einem neuronalen Netzwerk das Ergebnis.
Wenn du fertigen Libs benutzen darfst, nimm doch z.B. Aforge.net für das neuronale Netzwerk. (Namespace neuro glaube ich).
Erkennt wird immer(!) intern, es soll auf jeden Fall möglich sein zu sagen, welches Schild es ist, d.h. es gibt auf jeden Fall einen Text dazu. z.B. Geschwindigkeitsbeschränkung 50.
Um es genauer zu formulieren, es geht um den Ansatz, quasi ob aus der lokalisierten Bildstelle das Bild direkt ausgewertet soll, oder anhand einer Datenbank mittels klaren Formen. Ob das dann mittels einem neuronalen Netzwerk gemacht wird, oder per Statistik oder sonstigen Klassifizierungsmethoden sei vorerst mal dahingestellt.
Erkannt wird so oder so, das stimmt schon. Sonst wäre der Begriff "erkennen" ja falsch gewählt.
Ich werde einfach selbst eine Methode auswählen.
So viele Fehler sind korrigiert und ich kann an die Erkennung gehen.
Hierzu noch eine Frage zum ERKENNEN:
Erstellen wir hierzu eine Bilddatenbank mit den BEKANNTEN Schildern, oder soll das Programm einfach nur die Ausschnitte aus dem Realen Bild mit dem Verkehrsschild extrahieren?
Was meint ihr?
EDIT: Nebenbei bin ich dabei auch noch auf einen Ansatz gekommen, um Autonummern extrahieren zu lassen. Das war mehr oder weniger Zufall, funktioniert aber zuverlässig, wenn sich zumindest nur ein Auto im Bild befindet. (bzw. 1 beschriftete Nummerntafel)
Bzgl.
Verkehrsschilderkennung in neuen Fahrzeugen
hab ich jetzt noch ein paar Sachen zu programmieren.
Außerdem möchte ich für später die Videos die dabei entstanden sind später auch auswerten können, nicht nur die Einzelbilder die in Echtzeit von der Webcam kommen.
Hierzu ein paar Fragen:
1.) Kann man Codecs in C# benutzen, um einzelne Frames eines Videos zu lesen?
Ich möchte nicht wissen, sondern nur ob, vielleicht weiß das ja schon jemand. 😃
2.) und ist dabei Codecs per Api anzusteuern überhaupt der richtige Weg oder bietet mir da DirectShow schon wirklich alles was ich brauche?
Im Projekt WebTV1: Web-TV-Player, TV-Streams im Web hatte ich damals schon einen Video Player(Plugin) mit DirectX programmiert, dort ging es aber nur um das Abspielen des Streams.
Jetzt geht es darum einzelne Frames auszulesen.
Eine mögliche Quelle um das Problem für AVI-Files zu lösen, habe ich hier gefunden:
Der Grund dafür ist: möglichst nicht für jedes einzelne VideoFormat einen Frameextractor zu programmieren.
Codec-Basiert habe ich hier eine Diskussion gefunden:
Ich werde auf jeden Fall noch etwas weiter suchen, zuerst muss das obere Projekt abgeschlossenen werden.
EDIT: Ich habe natürlich auch hier im Forum gesucht aber dies bezüglich nichts gefunden was mir weiterhelfen würde mich für einen der beiden Ansätze zu entscheiden.
@Quaneu: Hat dich das jetzt wirklich nur für double interessiert was schneller ist (s. Überschrift) oder allgemein der Ausdruck? Denn sonst müssten wir das für andere Fälle auch noch testen.
Quasi verschiedene Überladungen von Math.Abs(...) mitberücksichtigen.
@d3!NL:
Das seh ich im Release für die double Überladung:
double a = 3.0f;
0000009a fld dword ptr ds:[04161A50h]
000000a0 fstp qword ptr [ebp-44h]
double b = 7.0f;
000000a3 fld dword ptr ds:[04161A58h]
000000a9 fstp qword ptr [ebp-4Ch]
bool test1 = Math.Abs(a) > b;
000000ac fld qword ptr [ebp-44h]
000000af fabs
000000b1 fstp qword ptr [ebp+FFFFFF7Ch]
000000b7 fld qword ptr [ebp+FFFFFF7Ch]
000000bd fld qword ptr [ebp-4Ch]
000000c0 fcomip st,st(1)
000000c2 fstp st(0)
000000c4 jp 000000CA
000000c6 jb 000000CE
000000c8 jmp 000000CA
000000ca xor eax,eax
000000cc jmp 000000D3
000000ce mov eax,1
000000d3 mov dword ptr [ebp-50h],eax
@dN!3L:
Math.Abs internals:
public static int Abs(int value)
{
if (value >= 0)
{
return value;
}
return AbsHelper(value);
}
und AbsHelper:
private static int AbsHelper(int value)
{
if (value == -2147483648)
{
throw new OverflowException(Environment.GetResourceString("Overflow_NegateTwosCompNum"));
}
return -value;
}
@Gfoidl: Das wäre dann meiner Meinung nach der nächste Schritt für ihn gewesen.
😉
für z.B.
public void Test1()
{
int a = 7;
int b = 2904;
bool bTest1 = Math.Abs(a) < b;
}
kommt heraus:
.method public hidebysig instance void Test1() cil managed
{
// Code size 20 (0x14)
.maxstack 2
.locals init ([0] int32 a,
[1] int32 b,
[2] bool bTest1)
IL_0000: nop
IL_0001: ldc.i4.7
IL_0002: stloc.0
IL_0003: ldc.i4 0xb58
IL_0008: stloc.1
IL_0009: ldloc.0
IL_000a: call int32 [mscorlib]System.Math::Abs(int32)
IL_000f: ldloc.1
IL_0010: clt
IL_0012: stloc.2
IL_0013: ret
} // end of method Form1::Test1
und für test2:
public void Test2()
{
int a = 7;
int b = 2904;
bool bTest2 = a < b && a > -b;
}
.method public hidebysig instance void Test2() cil managed
{
// Code size 23 (0x17)
.maxstack 2
.locals init ([0] int32 a,
[1] int32 b,
[2] bool bTest2)
IL_0000: nop
IL_0001: ldc.i4.7
IL_0002: stloc.0
IL_0003: ldc.i4 0xb58
IL_0008: stloc.1
IL_0009: ldloc.0
IL_000a: ldloc.1
IL_000b: bge.s IL_0014
IL_000d: ldloc.0
IL_000e: ldloc.1
IL_000f: neg
IL_0010: cgt
IL_0012: br.s IL_0015
IL_0014: ldc.i4.0
IL_0015: stloc.2
IL_0016: ret
} // end of method Form1::Test2
EDIT: muss noch mal den richtigen Code nachliefern statement ist falsch.
EDIT: korrigiert.
Das wird aus Test 1 (Release):
public void Test1()
{
00000000 push ebp
00000001 mov ebp,esp
00000003 push edi
00000004 push esi
00000005 push ebx
00000006 sub esp,40h
00000009 mov esi,ecx
0000000b lea edi,[ebp-38h]
0000000e mov ecx,0Bh
00000013 xor eax,eax
00000015 rep stos dword ptr es:[edi]
00000017 mov ecx,esi
00000019 xor eax,eax
0000001b mov dword ptr [ebp-1Ch],eax
0000001e mov dword ptr [ebp-3Ch],ecx
00000021 cmp dword ptr ds:[04AC3D60h],0
00000028 je 0000002F
0000002a call 75F68F91
0000002f xor edx,edx
00000031 mov dword ptr [ebp-44h],edx
00000034 xor edx,edx
00000036 mov dword ptr [ebp-40h],edx
00000039 mov dword ptr [ebp-48h],0
00000040 nop
int a = 7;
00000041 mov dword ptr [ebp-40h],7
int b = 2904;
00000048 mov dword ptr [ebp-44h],0B58h
bool bTest1 = Math.Abs(a) < b;
0000004f mov ecx,dword ptr [ebp-40h]
00000052 call FF87F03C
00000057 mov dword ptr [ebp-4Ch],eax
0000005a mov eax,dword ptr [ebp-4Ch]
0000005d cmp eax,dword ptr [ebp-44h]
00000060 setl al
00000063 movzx eax,al
00000066 mov dword ptr [ebp-48h],eax
}
00000069 nop
0000006a lea esp,[ebp-0Ch]
0000006d pop ebx
0000006e pop esi
0000006f pop edi
00000070 pop ebp
00000071 ret
und das aus Test 2 (Release):
public void Test2()
{
00000000 push ebp
00000001 mov ebp,esp
00000003 push edi
00000004 push esi
00000005 push ebx
00000006 sub esp,40h
00000009 mov esi,ecx
0000000b lea edi,[ebp-38h]
0000000e mov ecx,0Bh
00000013 xor eax,eax
00000015 rep stos dword ptr es:[edi]
00000017 mov ecx,esi
00000019 xor eax,eax
0000001b mov dword ptr [ebp-1Ch],eax
0000001e mov dword ptr [ebp-3Ch],ecx
00000021 cmp dword ptr ds:[04AC3D60h],0
00000028 je 0000002F
0000002a call 75F68F09
0000002f xor edx,edx
00000031 mov dword ptr [ebp-40h],edx
00000034 xor edx,edx
00000036 mov dword ptr [ebp-44h],edx
00000039 mov dword ptr [ebp-48h],0
00000040 nop
int a = 7;
00000041 mov dword ptr [ebp-40h],7
int b = 2904;
00000048 mov dword ptr [ebp-44h],0B58h
bool bTest2 = a < b && a > -b;
0000004f mov eax,dword ptr [ebp-40h]
00000052 cmp eax,dword ptr [ebp-44h]
00000055 jge 0000006B
00000057 nop
00000058 mov eax,dword ptr [ebp-44h]
0000005b neg eax
0000005d cmp eax,dword ptr [ebp-40h]
00000060 setl al
00000063 movzx eax,al
00000066 mov dword ptr [ebp-4Ch],eax
00000069 jmp 00000070
0000006b xor edx,edx
0000006d mov dword ptr [ebp-4Ch],edx
00000070 movzx eax,byte ptr [ebp-4Ch]
00000074 mov dword ptr [ebp-48h],eax
}
00000077 nop
00000078 lea esp,[ebp-0Ch]
0000007b pop ebx
0000007c pop esi
0000007d pop edi
0000007e pop ebp
0000007f ret
@Quaneu: Solche Unterschiede herauszufinden, ist immer interessant, vor allem natürlich wenn es um die Performance geht. Oft hilft dabei auch ein Blick in den IL-Code (Byte-Code).
s. dazu auch:
Disassemblieren von Projekte, ganz einfach mit ILDASM [VS2005 Deutsch]
Hallo Zommi und danke vorerst mal.
Wenn ich dann die Zusammenfassungen (sowohl von Wikipedia als auch von Dir. 😉 in meinen Worten wiedergeben darf:
1.) Der ausgewählte Interest-Operator könnte in diesem Fall ein Eckendetektor (z.B. Plessey, Harris-Corner Detektor und weitere) sein,
Hmmm, das bietet sich besonders an, da es hier nur um Quader geht, die auf dem Bild zu sehen sein werden.
2.) Einen Matching Algorithmus ausführen (das nanntest Du Features paaren so gut es geht).
Wenn ich einen Corner-Detektor wähle, wäre das z.B. welche Corner aus Bild 1 gehört zu Bild 2.
3.) Ein paar korrespondierende Punktpaare herausgreifen, die mit 2. erzeugt wurden
4.) Geometrischen Zusammenhang berechnen
D.h. die von 3 herausgegriffenen Koordinaten mittels der Fundamentalmatrix berechnen.
Wenn ich das richtig verstanden habe, bin ich dann bei der Epipolargeometrie soweit angelangt, das ich quasi die korrespondierenden Punkte auf Epipolare Linien setzen kann.
Das Funktioniert lt. Wikipedia auch, selbst wenn die Kameraposition doch nicht bekannt gewesen sein sollte.
5.) Und 5. sind quasi Trial and Error-Operationen.
Habe ich das so weit fürs erste richtig verstanden!?
Und das alles ist quasi nichts anderes als die Zusammenfassung was in
"Epipolargeometrie" unter Wikpedia steht.
Ok, sobald ich dazu komme, werde ich mich daran versuchen.
P.S.:
Das kann dann nur 2 Sachen bedeuten:
1.) ich hab für meinen Stereomatching bei 2 stereoskopischen Bildern einen anderen Weg entdeckt
2.) die Berechnung ist doch nicht so gut wie es auf den ersten Blick den Anschein hat.
Werde ich überprüfen. 😉
Ich suche diesesmal nach einem Algorithmus um ein Stereoanaglyph in eine Depthmap umzuwandeln.
Das Anaglyph wurde dabei z.B. als Optimized Anaglyph erzeugt. Ich gehe jetzt einfach von diesem Typ aus.
Um es einfacher zu machen: Ich kann auch mit Sicherheit davon ausgehen, dass die Kameras das Bild senkrecht von oben mittig betrachtet haben.
(Beispielbild habe ich hier angefügt, das ist nicht das aktuelle Bild um das es gehen wird, das Originalbild kann ich aus Copyright Gründen hier nicht posten)
Gibt es dann tatsächlich einen Algorithmus eurer Meinung nach in der Art wie:
Für das untenstehende Bild (angenommen die Kamera würde tatsächlich von oben mittig daraufsehen:
METHODE 1
========
1.) Finde das erste rote Pixel in der aktuellen Zeile
2.) Finde das erste blaue Pixel in der selben aktuellen Zeile
3.) rechne den Abstand der beiden Pixel in einen Farbwert (z.B. Grauwert, je größer der Abstand zwischen rot und blau desto dunkler)
4.) setze das Pixel auf den entsprechenden Grauwert im Ergebnisbild (mittig in den Abstand zwischen blau und rot).
oder muss ich ausgehend von der Kamera quasi die Strahlensätze für das Bild ermitteln (ausrechnen vom Punkt in der Mitte ausserhalb über dem Bild - Kameraposition) und dann die Linien berechnen
Methode 2
=======
1.) Von Kamerapunkt zu Blau
2.) Von Kamerapunkt zu Rot
3.) Ausmessen wie weit die Strahlen auseinandergehen
4.) Mittig zwischen die aufgespannte Linie von Blau und Rot den entsprechenden Wert setzen m Ergebnisbild
Ist für euch denkbar, dass Methode 1 auch (natürlich mit Abwandlungen) möglich sein könnte?
Oder hab ich bei beiden Methoden total falsch gedacht?
Möchte einfach noch ein paar andere Gedanken hören, bevor ich das irgendwann implementiere.
Zur Hintergrundaktivität:
Momentan bin ich dabei im Bereich in dieser Richtung ziemlich viel auszuprobieren und muß sagen, es funktioniert auch jetzt schon mit der Library ziemlich gut zu lokalisieren.
Heute hab ich noch (per Zufall) eine andere Sequenz gefunden, die funktioniert und im ersten Schritt NICHT farbabhängig ist, deswegen funktioniert diese auch gut mit allen Schildern wie es auf den ersten Blick scheint. Das müßte ich noch genauer testen.
Folgende Sequenz funktioniert soweit zur Lokalisierung nahezu perfekt(Filternamen aus LowLevelGraphicsLibrary)
1.) Normalize
2.) ChannelDifferences
3.) Threshold (mit > 127)
4.) Open
5.) ImageFill (Neu programmiert, Vorbild: Matlab)
Mit dem SimpleBlobExtractor können dann die Objekte geholt und weiterbearbeitet werden.
Gut zu wissen, ich hab nämlich momentan leider keine Zeit das selber in Erfahrung zu bringen. Aber das wissen hilft mir auf jeden Fall weiter.
@iginaz: such im Forum nach CMYK und Poste die besten Treffer hier
Außerdem hatte ich angedacht das ganze in die LowLevelGraphicsLibrary einzufügen.
Ob der Code richtig sein kann hab ich nicht überprüft. Er ist auch nicht getestet bisher.
/// <summary>
/// Used to calculate new channel values from rgb
/// This is a simple formula WITHOUT ICC (Color management)
/// </summary>
protected override void CalcValues()
{
int nR = m_Color.R;
int nG = m_Color.G;
int nB = m_Color.B;
m_K = Math.Min(Math.Min(255 - nR, 255 - nG), 255 - nB);
m_C = (255 - nR - m_K) / (255 - m_K);
m_M = (255 - nG - m_K) / (255 - m_K);
m_Y = (255 - nB - m_K) / (255 - m_K);
}
@Jack30Lena und Gfoidl:
Wie sieht das ganze im Vergleich zu AddRange aus?
Was macht der Compiler daraus, wenn ich ein Array direkt in AddRange initialisiere?
List<int> aInt = new List<int>();
aInt.AddRange(new int[]{1,1,1,1,1,1,1,1});
//Vergleich
List<int> aInt2 = new List<int>(new int[]{1,1,1,1,1,1,1,1,1,})
oder ähnliches?
Oder ist das eurer Meinung nach Unsinn das mit-zu-vergleichen!?
Außerdem: ich sehe es wird "var" benutzt. Was ist wenn man direkt den benötigten Typ benutzt?
@Mansur: Die Klassen BaseColorSegmentation2, BaseColorSegmentation3 usw. habe ich rausgeworfen, da diese jetzt in BaseColorSegmentation vereint sind und mit einem Parameter der Modus eingestellt werden kann.
Das Compillieren klappt bei mir leider immer noch nicht.
Ich konnte zwar die Verweise zu AVI... und LowLevel auf Deine Dlls umstellen,
Mir fehlt aber seltsamer weise die folgenden Klassen:
BaseColorSegmentation3
BaseColorSegmentation4
OwnOptimizedConvolution... um kompillieren zu können (Wenn danach nicht noch etwas raus kommt).
Hmmm... das werde ich nochmal kontrollieren, auf jeden Fall solltest Du im VS 2008
auf die Projekte die "unavailable/nicht verfügbar" sind, einen "Reload Project/Projekt neu laden"-Befehl per Kontext-Menü ausführen.
Wenn ich einen Einstieg finden sollte, dann interessieren mich eher die Basisklassen.
Soweit ich die Beiträge gelesen habe ist ja das Projekt ImageRecognition2 nur die Frontend Anwendung, um die (komplexen) Filter entsprechend anzusprechen / zu konfigurieren.
Das ImageRecognition2 Projekt ist die Oberfläche um die Filter, Extraktoren und weiteres auszuprobieren, richtig.
Soweit ich das ganze (leider ohne Codeerklärung) mir bisher vorstellen kann ist es wohl die LowLevelGraphics Library die den Kern bildet.
LowLevelGraphicsLibraryGenau, diese Library bildet den Kern.
AcquiringLibrary
Die Acquiring Library ist dafür gedacht, um von verschiedenen Devices (z.B. Webcam) oder Online oder per Screenshot Bilder abzurufen.
ScripterLibrary
Die ScripterLibrary wird von der ImageProcessingConsole.exe benutzt.
Mit der ImageProcessingConsole können die Filter in der Console ausprobiert werden.
Ich würde gerne mal probieren, ob sich Imageprocessing für GIS Anwendungen eignet ... so als Übungsprojekt.
Dann wäre es interessant die Ergebnisse zu veröffentlichen.
Vielleicht kann man ja doch noch die LowLevelGraphics Library im Sourcecode sehen? oder war das nie so vorgesehen?
Doch die wird mit dem Projekt heruntergeladen vom Link im ersten Post,
hier nochmal der Link:
lol @Gfoidl:
Vielleicht als Ergänzung hierzu:
und mich würde auch die Implementierung des Codes interessieren @tonka. 😉