I need a way to track the mouse coordinates more precisely than this code. If you run this code and move your mouse really fast or change directions fast, the coordinates might look this: 50 and then 40. It seems that when the mouse moves fast it doesn't track all the points the pointer covers, like in this example there are 10 coordinates that it skips. If I move it slowly, there's no problem. I need a way to track all the pointer coordinates with no skips. I've tried the sample on Code Project that uses global hooks, with the same result. How can I do this? Is there a registry change that can be made that forces windows to track all the coordinates. Is it possible? I would prefer to do it with C# but will consider other ways too. Thanks.
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (num != 1)
{
listBox1.Items.Add(e.X.ToString());
}
}
Are you sure that the mouse covers all the coordinates that lie on the journey from A to B?
The mouse input from the OS is sampled, discreet data. This means that the mouse pointer can skip coordinates, just as you are seeing.
Consider interpolation over your data if it isn't hi-res enough.
IIRC, you can increase the sample-rate of the mouse. Can't remember how though. I'm sure the web can though.
The mouse pointer doesn't move across every pixel, if you move the mouse fast, it will move a whole bunch of pixels between events. The hardware simply doesn't send a signal for each pixel that the mouse moves, it reports the distance that the mouse has moved since the last report.
Instead of trying to track where the mouse is, use the Cursor.Clip property to limit the movement of the mouse:
var rect = someControl.RectangleToScreen(new Rectangle(Point.Empty, someControl.ClientSize));
Cursor.Position = new Point(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2);
Cursor.Clip = rect;
Use an empty rectangle to release the mouse:
Cursor.Clip = new Rectangle(0, 0, 0, 0);
Iv been asked this several times over the years. You generally cant tell mouse event listeners to tell you every single pixel the mouse passes though. Even the OS may skip large areas of the screen if you are moving the mouse fast enough. The only reliable way would be to plot the points yourself from the history of mouse positions you are given. The simple method would be to draw a line between the current point and the last one. More complex solutions would involve storing the last few coordinates and using sine / tangent math to plot a smooth curve.
Related
I'm trying to write some image detection code for a pick and place machine. I'm new to OpenCV and have been going through a lot of examples - but still ahve two outstanding questions. The first one I think I have a solution for but I'm lost on the second.
I'm trying to detect the offset and angle of the bottom of a part. Essentially, how far is the object from the cross (just an indicator of the center of the frame), and what the angle of rotation the part has about the part's center. I've used filters to show the pads of the components.
I'm pretty sure that I want to implement something like this http://felix.abecassis.me/2011/10/opencv-bounding-box-skew-angle/ - but I'm not sure how to translate the code into C# (http://www.emgu.com/wiki/index.php/Main_Page). Any pointers would be helpful.
One issue is if the part is smaller than the needle that's holding it and you can see both the part and the needle.
The square bit is the part I want to detect. The round part is part of the needle that is still exposed. I've got no clue how to approach this - I'm thinking something along the lines of detecting the straight lines and discarding the curved ones to generate a shape. Again, I'm interested in the offset from the center and the angle of rotation.
First you should detect every Object with findContours. Then you can use the minimum area rectangle function on every found contour. I assume you know the size and coordiantes of your cross so you can use the Center Coordinates of the MCvBox2D to get the Offset to it. Furthermore you can read the angle property of the box so it should fit your purpose.
For the second part i would try to fit a least square reactangle. The round part seems to be very small compared to the square one so maybe it will work.
Maybe the Detection of Quadrilaterlas in the AForge Library could help you too.
Edit:
To merge your the contours i would try something like this:
Rectangle merged = New Rectangle(New Point(img.Width, img.Height), New Size(0, 0)); //img is your binarized image
Contour<Point> Pad_contours= img.FindContours(CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,CvEnum.RETR_TYPE.CV_RETR_LIST);
while(Pad_contours !=null)
{
if(Pad_contours.Area <Pad_Area_max &&Pad_contours>Pad_Area_min)//Filter Pads to avoid false positive Contours
{
//Merge Pad contours into a single rectangle
if(merged.Height >0)
merged.Bottom=Math.Max(merged.Bottom,Pad_Contours.BoundingRectangle.Bottom);
else
merged.Height = contours.BoundingRectangle.Height;
merged.Top=Math.Min(merged.Top,Pad_Contours.BoundingRectangle.Top);
merged.Left=math.Min(merged.Left,Pad_Contours.BoundingRectangle.Left);
if(merged.Width>0)
merged.Right=Max(merged.Right,pad_Contours.BoundingRectangle.Right);
else
merged.Width=Pad_Contours.BoundingRectangle.Width;
}
//get next Pad
If(Pad_contours.VNext==null)
Pad_contours=Pad_contours.HNext;
else
Pad_contours = Pad_contours.VNext;
}
The rectangle "merged" should enclose all your Pads now. The problem is you wont get an angle this way because the rectangle is always vertically 90°. To solve this I would iterate through the contours like shown above and store every point of every contour in an extra datacontainer. Then I would use the minimum area rectangle function mentioned above and apply it on all gathered points. This should give you a bounding rectangle with an angle property.
Hi I'm trying to get a particular coordinate on texture (under mouse cursor). So on mouse event I'm performing:
Ray outRay = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit clickRayHit = new RaycastHit();
if (!Physics.Raycast(outRay, out clickRayHit))
{
return;
}
Vector2 textureCoordinate = clickRayHit.textureCoord;
Texture2D objectTexture = gameObject.GetComponent<Renderer>().material.mainTexture as Texture2D;
int xCord = (int)(objectTexture.width * textureCoordinate.x);
int yCord = (int)(objectTexture.height * textureCoordinate.y);
But the problem is that the coordinate I'm getting is not preciesly under the cursor but "somewhat near it". And it's not like coordinates are consistently shifted in one way but shifting is not random as well. They are shifted differently in different points of the texture but:
they remain somwhere in the area of real cursor
and coordinates shifted in the same way when cursor is above the same point.
Here is part of coordinates log: http://pastebin.ca/3029357
If i haven't described problem good enough I can record a short screencast.
GameObject is a Plane.
If it is relevant mouseEvent is generated by windows mouseHook. (Application specific thing)
What am I doing wrong?
UPD: I've decided to record screencast - https://youtu.be/LC71dAr_tCM?t=42. Here you can see Paint window image through my application. On the bottom left corner you can see that Paint is displaying coordinates of the mouse (I'm getting this coordinates in a way I've described earlier - location of a point on a texture). So as I move mouse cursor you can see how coordinates are changing.
UPD2:
I just want to emphasize one more time that this shift is not constant or linear. There could be "jumps" around the mouse coordinates (but not only jumps). The video above explains it better.
So it was scaling problem after all. One of the scale values were negative and was causing this behaviour.
I am writing a paint program of sorts, using C# .Net/WinForms and pressure sensitivity is a must. I have everything set up and am getting pressure information from the tablet pen. None of this is an issue.
What I am having trouble approaching is, how would I take your typical, simple paint program (i.e., 'Scribble') and draw using the pressure data I am getting? Scribble-type simple apps track current and previous cursor positions, while drawing is enabled, and draws lines between them. But each point laid down by capturing cursor positions is drawn between using a fixed width line.
Assuming I have all the data I need: x y positions and pen pressure, how would I begin to think about drawing between points that should be different widths?
I would break your total xy positions in to many smaller xy positions (maybe a pixel or two in length) and apply the width accordingly corresponding to the pen pressure.
The easiest way to do it is to keep track of the previous point and the previous size (based on pressure) and then draw a lineto from the previous point to the current point, using the previous size for the line size.
Even using GDI+ is fast this way, if you make sure not to create new objects in the event handler code.
The other way I mentioned is much more advanced (though may yield better results) and I may end up implementing it at a later date, when I do everything vector-based.
Is there a way to smooth out the mouse movements? I want to remove all the small jitter in normal mouse moving with the hand, like you can never draw a clean line in paint because of you hand doing small jittering movements.
This might be hard to understand what I mean, but if you know zbrush they have a feature that is called lazy mouse http://www.pixologic.com/docs/index.php/Lazy_Mouse im looking for a way to recreate this inside my app. I can read the mouse position with Cursor.Position but I don't find a way to average out these numbers before they get sent to the pointer on the screen.
This is only possible if you can delay the effect of the mouse movement slightly. You record the points of the mouse movement at a certain frequency and then average them out to a line. Then use that line to draw whatever you need. You wont be able to directly set the mouse cursor to the averaged position as that would then feedback into your program as a new mouse movement.
Make sure you build it so you can tweak how long you delay the mouse movement, and how aggressive the averaging is (say by restricting the number of points it includes), and the frequency at which you record mouse movements (this is could affect cpu usage if its too frequent).
You will of course have to create some sort of abstraction for the mouse in your application and create a way for the application to get hold of it. (I would be trying to keep this as similar as possible to normal winforms/wpf so I could revert the change and just use mouse movement directly if needed).
I am working on wpf project, I want to know how to measure the angle of the stroke on the ink canvas? whether the stroke is right inclined or left inclined?
When you get a mouse down on the canvas, save away the current mouse position. Later, when you receive a mouse up event, you know the stroke is finished. Get the mouse position a second time and calculate the difference between the second position and the first position. Then you just have some simple math to do, and there are a couple cases to consider.
Note that this will not work so well for complex, curved strokes (because you will only receive a mouse-up event at the end of the stroke). This will work best in the case of single, straight lines.