Hi, I Have created a program (see below) that enables you to use you cam. You then draw a line and calculate the angle.
The purpose is that I do alot of work with remote control cars and need to acuratley set toe and camber angles, it takes to long with the "old" method So I am creating this little program. ok, so, lets see what I want to do. Well, the first thing I would like to do is draw a line from top to bottom of my picture box dead center of left to right, this is dead center of the cam so the bottom of your item should be posistioned to meet the bottom of the centre line. I then draw a line from bottom to top of the objects angle. I then use the dead center line and the line I drew to calculate the angle.
I also want to be able to change the colour of the line to be drawn, not the dead center line.
Any help here would be greatly appreciated. To help you better understand the project I have included all the source code.
For my part, I can't understand the lines from the description (which may be because I'm in a meeting at the moment, so there's lots of talking going on). Could you draw up a quick picture?
It sounds like you want a line from top to bottom in the middle of the picture. However, I don't understand what you mean when you say that "the bottom of your item should be positioned to meet the bottom of the centre line." I also don't understand the following line about drawing a line from bottom to top of the objects angle. What object? What's the objects angle?
Ok, so we assume that the red "block" is the object in the image( the object is litterally whatever you want to calculate the angle of) The black line that sticks straight up is in the center or atleast, we need to imagine it is, not how the red "object" meets the black line. You then draw a black line over the image folowing the object. you then calculate the angle better the verticle black line and the angled black line.
Does the angled line always interesct the top of the picturebox? It always has to if it is extended long enough. The point of intersection with the top would be highly valuable for figuring out the angle. Suppose that line hits the top of the picturebox at (x,y). In that case, y will always be the height of the picturebox, so only the x matters (actually, since screen coordinates are 0,0 in the upper right corner, y will always be 0). Still, x is all that matters. Figuring the distance between the midpoint and x is really simple A = (PB.Width/2 - x), where A is the distance between the midpoint line and the angled line at the top of the picturebox. The height of the picturebox is H. With that information, you can figure the angle in radians:
You would do that in the Paint event handler for the picturebox. That gives you a graphics object automatically, and that should have a drawLine method.
You would do that in the Paint event handler for the picturebox. That gives you a graphics object automatically, and that should have a drawLine method.
ok then, cheers. lets see if i can put this lot together and tested tonight
Ok, so this is what I did. I keep on getting the wrong answer, clearly i have done something wrong but I cant see what
Code:
Dim a As Integer = start.X
Dim b As Integer = start.Y
Dim c As Integer = [end].X
Dim d As Integer = [end].Y
Dim o As Decimal
Dim n As Integer
n = (MainFrame.Width / 2 - [end].X)
If start.X = Nothing And
start.Y = Nothing And
[end].X = Nothing And
[end].Y = Nothing Then
MsgBox("please draw a line")
Else
o = Math.Atan(n / MainFrame.Height)
Me.TextBox1.Text = o
mmmkay I might be on the wrong lines then (no pun intended).
You may have changed this already since your last attachment, but in your MainFrame.MouseUp Handler you have the line Dim [end] As Point = e.Location
when I suspect you mean to use the class level variable [End]. i.e. just Me.[End] = e.Location
Ok, I am getting really frustrated with something. I am trying to get the angled line to start at the bottom point of the centre line and upon mouse move the line moves. Havent really got a clue what I am doing here but the code I used was a little crap lol
Code:
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms
Imports AForge.Video.DirectShow
Imports AForge.Video
Imports AForge.Imaging.Filters
Imports AForge.Imaging
Partial Public Class RangeFinderForm
Inherits Form
'calibration image
Private previous_image As Bitmap = Nothing
'internal flag to see if calibration mode is enbaled
Private _calibrate As Boolean = False
'stores calibration data
Private calibration_data As New CalibrationData()
'internal flag to store if color tuning form is open
Private _colortune As Boolean = False
'to store video device
Private VideoDevice As VideoCaptureDevice = Nothing
'Color filtering data(includes lower nad upper values of all three colors RGB)
Private color_data As New ColorData()
Public Sub New()
InitializeComponent()
End Sub
''' <summary>
''' Event: To open camera selection child form
''' </summary>
Private lines As New List(Of Line)
Private start As Point
Private [end] As Point
Private Sub MainFrame_mousemove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MainFrame.MouseMove
Me.[end] = e.Location
Dim area As New Rectangle(Math.Min(MainFrame.Width / 2, MainFrame.Width / 2), _
(Math.Min(0.0F / 2, MainFrame.Height)), _
Math.Abs(MainFrame.Width / 2 - [end].X), _
Math.Abs(0.0F - [end].Y))
area.Inflate(1, 1)
Me.MainFrame.Invalidate(area)
Me.MainFrame.Update()
End Sub
Private Sub Mainframe_Paint(ByVal Sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MainFrame.Paint
Me.DrawLines(e.Graphics)
Dim blackPen As New Pen(Color.Black, 3)
' Create coordinates of points that define line.
Dim x1 As Single = MainFrame.Width / 2
Dim y1 As Single = 0.0F
Dim x2 As Single = MainFrame.Width / 2
Dim y2 As Single = MainFrame.Height
e.Graphics.DrawLine(blackPen, x1, y1, x2, y2)
End Sub
Private Sub Save()
Using g As Graphics = Graphics.FromImage(Me.MainFrame.Image)
Me.DrawLines(g)
End Using
Me.Clear()
End Sub
Private Sub Clear()
Me.lines.Clear()
Me.MainFrame.Refresh()
End Sub
Private Sub DrawLines(ByVal g As Graphics)
For Each Line As Line In Me.lines
g.DrawLine(Pens.Black, Line.start, Line.end)
Next Line
End Sub
Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim a As Integer = start.X
Dim b As Integer = start.Y
Dim c As Integer = [end].X
Dim d As Integer = [end].Y
Dim o As Decimal
Dim n As Integer
Dim h As Integer
h = (MainFrame.Height)
n = (MainFrame.Width / 2)
If start.X = Nothing And
start.Y = Nothing And
[end].X = Nothing And
[end].Y = Nothing Then
MsgBox("please draw a line")
Else
o = Math.Atan(n / MainFrame.Height)
Me.TextBox1.Text = o
End If
End Sub
Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
If start.X = Nothing And
start.Y = Nothing And
[end].X = Nothing And
[end].Y = Nothing Then
MsgBox("Already Clear")
Else
start.X = Nothing
start.Y = Nothing
[end].X = Nothing
[end].Y = Nothing
Me.TextBox1.Text = Nothing
Me.lines.Clear()
Me.MainFrame.Refresh()
End If
End Sub
Private Sub VideoSource_Click(ByVal sender As Object, ByVal e As EventArgs) Handles VideoSource.Click
'creating instance of camerasource
Dim camera_child As New CameraSource()
camera_child.ShowDialog()
'if OK was't clicked or no video device found
If Not camera_child.Click Then
Return
End If
'adding video source to this form
VideoDevice = camera_child.VCD
'new frame event
AddHandler VideoDevice.NewFrame, New AForge.Video.NewFrameEventHandler(AddressOf VideoDevice_NewFrame)
VideoDevice.Start()
'enable filter editing, note by default filter is set to optimal values
End Sub
''' <summary>
''' Event: Whenever new frame for camera is ready.
''' All image processing goes here
''' </summary>
Private Sub VideoDevice_NewFrame(ByVal sender As Object, ByVal eventArgs As AForge.Video.NewFrameEventArgs)
'making clone of frame recieved
Dim image As Bitmap = DirectCast(eventArgs.Frame.Clone(), Bitmap)
'creating instance of color filtering for detectiong of laser light
Dim colr_filter As New ColorFiltering()
Dim gray_image As Bitmap = colr_filter.Apply(image)
Dim gray_filter As IFilter = New GrayscaleBT709()
gray_image = gray_filter.Apply(gray_image)
Dim th_filter As New Threshold(color_data.threshold)
th_filter.ApplyInPlace(gray_image)
'erosion filter to filter out small unwanted pixels
'initialize a blob counting object to count blobs in image
Dim bc As New BlobCounter()
'it should only one blob or no blob
MainFrame.Image = image
Return
'finding center of gravity of blob detected
'see if calibration is pressed
If _calibrate Then
previous_image = DirectCast(image.Clone(), Bitmap)
Return
End If
'NOTE: height of object from center of image is inversly propotional to range
' to find constant of propotionality we need to calibrate according to some know values
'so we need to stand at know range like 30 or 40 cm from camera and then press on calibrate
If calibration_data._calibrated Then
End If
'drawing rectangle on detected blob
MainFrame.Image = image
End Sub
''' <summary>
''' Closing video source
''' </summary>
Private Sub CloseVideoSource()
If Not (VideoDevice Is Nothing) Then
If VideoDevice.IsRunning Then
VideoDevice.[Stop]()
End If
End If
End Sub
Private Sub RangeFinderForm_FormClosed(ByVal sender As Object, ByVal e As FormClosedEventArgs) Handles MyBase.FormClosed
'close video device when form is closing
CloseVideoSource()
End Sub
'COlor tuning form
Private Sub Edit_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim child_tune As New ColorTune(color_data)
_colortune = True
child_tune.ShowDialog()
child_tune.Dispose()
_colortune = False
End Sub
#Region "calibration"
'calibrate is pressed
Private Sub Calibrate_Click(ByVal sender As Object, ByVal e As EventArgs)
_calibrate = True
'wait to see if there is any laser point or not
System.Threading.Thread.Sleep(100)
'if no then chnage the instructions
If previous_image Is Nothing Then
_calibrate = False
Return
End If
'else
CloseVideoSource()
DrawLines(previous_image, calibration_data.detected_point)
MainFrame.Image = previous_image
End Sub
''' <summary>
''' Draw intersecting lines on image at point p
''' </summary>
Private Sub DrawLines(ByRef image As Bitmap, ByVal p As Point)
' drawing horizontal line
Dim g As Graphics = Graphics.FromImage(image)
Dim p1 As New Pen(Color.Red, 1)
Dim ph As New Point(image.Width, p.Y)
Dim ph2 As New Point(0, p.Y)
g.DrawLine(p1, p, ph)
g.DrawLine(p1, p, ph2)
' drawing vertical line
ph = New Point(p.X, 0)
ph2 = New Point(p.X, image.Height)
g.DrawLine(p1, p, ph)
g.DrawLine(p1, p, ph2)
End Sub
Private Sub ButOK_Click(ByVal sender As Object, ByVal e As EventArgs)
'if string is zero length
If Text.Length = 0 Then
Return
End If
'if something non number is entred
For Each ch As Char In Text
If Not Char.IsDigit(ch) Then
Return
End If
Next
Dim y_cord As Integer = calibration_data.detected_point.Y
'to find the calibration constant
calibration_data.calibration_constant = Convert.ToDouble(Text) * (System.Math.Abs(CSng(previous_image.Height \ 2) - y_cord))
calibration_data._calibrated = True
previous_image = Nothing
'resizing the form to original
Me.Size = New Size(425, 430)
start_camera()
End Sub
Private Sub ButCancel_Click(ByVal sender As Object, ByVal e As EventArgs)
calibration_data._calibrated = False
previous_image = Nothing
'resizing the form to original
Me.Size = New Size(425, 430)
start_camera()
End Sub
Private Sub start_camera()
AddHandler VideoDevice.NewFrame, New NewFrameEventHandler(AddressOf VideoDevice_NewFrame)
VideoDevice.Start()
End Sub
#End Region
Private Sub Button3_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button3.Click
Me.ColorDialog1.ShowDialog()
End Sub
End Class
''' <summary>
''' Reseting everything
''' </summary>
Public Class Line
Private _start As Point
Private _end As Point
Public Property start() As Point
Get
Return Me._start
End Get
Set(ByVal value As Point)
Me._start = value
End Set
End Property
Public Property [end]() As Point
Get
Return Me._end
End Get
Set(ByVal value As Point)
Me._end = value
End Set
End Property
Public Sub New()
Me.New(Point.Empty, Point.Empty)
End Sub
Public Sub New(ByVal Start As Point, ByVal [end] As Point)
Me._start = Start
Me._end = [end]
End Sub
End Class