Webcam - Camera Preview rotates wrong way - c#

I would like your help please on a WebCamera problem. I've used a library available from Nuget; WebEye.Controls.Wpf.WebCameraControl (version 1.0.0). The URL is https://www.nuget.org/packages/WebEye.Controls.Wpf.WebCameraControl/
The article and instructions are available at: http://www.codeproject.com/Articles/330177/Yet-another-Web-Camera-control
Due to project constraints, I developed a WPF application for a Linx tablet (Windows 10), rather than as a Universal Windows Application. I used the WebEye library to connect to the webcam on the tablet and take pictures with it. It works fine when I hold the tablet in landscape, but not when I hold the tablet in portrait mode. In portrait mode, the CameraPreview/VideoWindow automatically rotates -90 degrees.
I tried resolve the problem to no avail.
Rotate the control surrounding the video window via the Webcamera RenderTransform or LayoutTransform property – The control rotates but the video image does not rotate correctly.
Tried to rotate the VideoWindow inside the WebCamera Content property - I got the source code from the GitHub and set the VideoWindow available for access. Recompled the library and used it to rotate the VideoWindow via its RenderTransform property. https://github.com/jacobbo/WebEye/tree/master/WebCameraControl
No matter what I do, the camera preview is always -90 degrees.
The library is simple and it does not have many properties to manipulate the video window.
The webcontrol is in XAML.
<wpf:WebCameraControl x:Name="webCameraControl"
MouseDoubleClick="webCameraControl_MouseDoubleClick"
StylusButtonUp="webCameraControl_StylusButtonUp"
MouseUp="webCameraControl_MouseUp"
TouchUp="webCameraControl_TouchUp"
GotMouseCapture="webCameraControl_GotMouseCapture"
/>
This is how I initialised the WebCamera. When the UserControl is loaded, it will then automatically connect to the webcam on the tablet. See startViewing() function.
private WebCameraId _cameraID = null;
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
startViewing();
}
private void startViewing()
{
List<WebCameraId> cams = (List<WebCameraId>)webCameraControl.GetVideoCaptureDevices();
if (cams.Count > 0)
{
_cameraID = (WebCameraId)cams[0];
webCameraControl.StartCapture(_cameraID);
}
}
I tried to force the control to rotate it correctly when the app detects a change in the Display screen. See DisplaySettingsChanged event.
public ucWebCam()
{
InitializeComponent();
Microsoft.Win32.SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged;
}
private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
{
try
{
double angle = 0;
if (SystemParameters.PrimaryScreenWidth > SystemParameters.PrimaryScreenHeight)
{
angle = 0;
}
else
{
angle = -90;
}
webCameraControl.StopCapture();
adjustWebcamAngle(angle);
webCameraControl.StartCapture(_cameraID);
}
catch (Exception ex)
{
}
}
private void adjustWebcamAngle(double angle)
{
try
{
// IGNORE portrait boolean flag
bool portrait = false;
if (angle == 90 || angle == 180)
{
portrait = true;
}
// TRIED TO SET THE ANGLE OF THE CONTROL TO NO AVAIL
RotateTransform rotTransform = new RotateTransform(angle);
//rotTransform.Angle = angle;
ScaleTransform scaleTransform = new ScaleTransform();
//scaleTransform.ScaleX = (portrait) ? 0 : 1;
//scaleTransform.ScaleY = (portrait) ? 0 : 1;
TransformGroup tGroup = new TransformGroup();
//tGroup.Children.Add(scaleTransform);
tGroup.Children.Add(rotTransform);
// ROTATE CAMERA!
webCameraControl.RenderTransform = tGroup;
} catch (Exception ex)
{
}
}
So far I only rotated the WebCam control, not the video image.
I looked through the comments in Alexander's article with no joy at: http://www.codeproject.com/Articles/330177/Yet-another-Web-Camera-control
How can I rotate the Camera preview correctly? Can you please advise where I'm going wrong?
I have attached two images to illustrate my problem.

In case you are not a stranger to C#, I would recommend you use the EMGUCV nuget and create your own preview application. It`s not that hard, and you could use MVVM to bind the frames to your View, making it better than using code behind your control.
PS: This is not an answer, but it is a solution to your problem. I cannot not post comments yet, as I do not have 50 points :(
Have a nice day.

Related

Camera stretched after deinitializing

I am using cardboard v1.4.1, and wanting to be able to toggle in and out of the cardboard vr. When transitioning out from cardboard the camera is stretched (I assume one of the eyes is stretched across the screen). I am using the following code that was provided in the example.
private void StopXR()
{
Debug.Log("Stopping XR...");
XRGeneralSettings.Instance.Manager.StopSubsystems();
Debug.Log("XR stopped.");
Debug.Log("Deinitializing XR...");
XRGeneralSettings.Instance.Manager.DeinitializeLoader();
Debug.Log("XR deinitialized.");
}
What would be the best way to approach this?
Try this:
void StopXR()
{
var xrManager = XRGeneralSettings.Instance.Manager;
if (!xrManager.isInitializationComplete)
return; // Safety check
xrManager.StopSubsystems();
xrManager.DeinitializeLoader();
}
And if you are experiencig a distorted or stretched screen after exiting VR:
camera.ResetAspect();
camera.fieldOfView = defaultFov;
camera.ResetProjectionMatrix();
camera.ResetWorldToCameraMatrix();

Adapting to screen rotation windows phone

I am creating a camera app using MediaCapture. I am trying to adapt to screen rotation and thus I have created the following method:
private void Current_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
{
width = Window.Current.Bounds.Width;
height = Window.Current.Bounds.Height;
//captureManager.SetPreviewRotation(VideoRotation.Clockwise90Degrees);
//if (ApplicationView.GetForCurrentView().Orientation.ToString() == "Portrait") capturePreview.Stretch = Stretch.Fill;
capturePreview.Width = width;
capturePreview.Height = height;
imagePreview.Width = width;
imagePreview.Height = height;
//if (ApplicationView.GetForCurrentView().Orientation.ToString() == "Portrait") capturePreview.Stretch = Stretch.Fill;
//else capturePreview.Stretch = Stretch.Uniform;
}
When I open my app the camera fills the whole page but when I flip the camera the capturePreview only takes half of the page, It doesn't matter if I start the app in portrait or horizontal mode, the other mode won't work but the first mode will also if flipped in to.
Another question is about the actual capturePreview layout, I found that if I keep the screen at horizontal layout the camera works great but if the device is in portrait mode I cant fill the whole page without stretching the photo, is there a way to keep only one element on the screen in a certain rotation (capturePreview) I tried rotating it with a rotation tranform but that also affects the actual place of the element.
Thank you
In WP you get the CurrentViewState through the Window.Sizechanged Event.
See this MSDN article (first result from google)

Move object in ViewportControl WP8

I'm using the ViewportControl to scroll around and zoom in and out of my Map. In this map I've got a green ellipse which I wish to move around. Previously I used a ScrollViewer where I set the manipulationMode of the ScrollViewer to control, and thus making it capable of moving my ellipse around. However I can't find a similar way for the ViewportControl. So is there a way to move my ellipse around?
The code I've got so far is:
The xaml part where I have my ViewportControl around my map
<ViewportControl x:Name="ViewPortTestTest" Bounds="0,0,1271,1381.5" Height="480" Width="800" Canvas.ZIndex="1" Grid.Row="1">
<ViewportControl.RenderTransform>
<CompositeTransform x:Name="myTransformTest"/>
</ViewportControl.RenderTransform>
<View:Map x:Name="ZoomableContent" >
<View:Map.RenderTransform>
<CompositeTransform x:Name="myTransform" />
<!-- ScaleX="{Binding Map.imageScale}" ScaleY="{Binding Map.imageScale}"/>-->
</View:Map.RenderTransform>
</View:Map>
</ViewportControl>
It is in the map where I add the ellipse. The viewModel where I manipulate my ellipse
public void ManStart(ManipulationStartedEventArgs e)
{
e.Handled = true;
ViewportControl VP = FindParentOfType<ViewportControl>(ChampViewModelSel);
}
}
public void ManDelta(ManipulationDeltaEventArgs e)
{
e.Handled = true;
Point fingerPosition = e.DeltaManipulation.Translation;
Temp.x = fingerPosition.X;
Temp.y = fingerPosition.Y;
}
}
Where Temp.x and Temp.y is the new position of the ellipse.
I think you could try to use TouchPanel from XNA and Touch.FrameReported event for this purpose. Probably Map and VieportControl handle the manipulation event so it won't fire with your code.
In my proposal Touch_FrameReported will be fired every time you touch the screen, so we have to check only for situations we need - here comes IsGestureAvailable and TouchAction. Simple code can look like this:
public MainPage()
{
InitializeComponent();
TouchPanel.EnabledGestures = GestureType.FreeDrag;
Touch.FrameReported += Touch_FrameReported;
}
private void Touch_FrameReported(object sender, TouchFrameEventArgs e)
{
if (TouchPanel.IsGestureAvailable) // check only dragging
{
// get point relative to Viewport
TouchPoint mainTouch = e.GetPrimaryTouchPoint(ViewPortTestTest);
// check if drag has completed (key up)
if (mainTouch.Action == TouchAction.Up)
{
Temp.x = mainTouch.Position.X;
Temp.y = mainTouch.Position.Y;
}
}
}
You can read more about Gestures here at MSDN and on this blog.
You can also check other GestureTypes and for example check if TouchAction.Down and user clicked on your Ellipse.
These methods give you many possibilities to read TouchPoints and their Actions so maybe it will help.
It took me a while to find a way how to disable Vieport. I've found a little 'hack' for that, it will be easier if your VieportControl was only horizontal or vertical (there is a lock property, but doesn't work for both). Here is this little 'hack' which should disable both horizontal and vertical scrolling:
Rect originalBounds = new Rect();
private void Touch_FrameReported(object sender, TouchFrameEventArgs e)
{
TouchPoint myTouchPoint = e.GetPrimaryTouchPoint(ViewPortTestTest);
// disable scrolling
if (myTouchPoint.Action == TouchAction.Down) // here probably some other statement like if user hit ellipse
{
originalBounds = ViewPortTestTest.Bounds;
ViewPortTestTest.Bounds = ViewPortTestTest.Viewport; // set current view as Bounds
}
// more logic
// enable once again
if (myTouchPoint.Action == TouchAction.Up)
ViewPortTestTest.Bounds = originalBounds;
}
When I want to disable scrolling - I set bounds of the VieportControl to the current view (and I remember original ones). When I want to enable scrolling - I bring back original bounds.
As I've tested it - it is working - of course it needs a little more logic in locking if statement, so that it won't lock every time you touch the screen.

Which is faster when animating the UI: a Control or a Picture?

/I'm working with and testing on a computer that is built with the following:
{1 GB RAM (now 1.5 GB), 1.7 GHz Intel Pentium Processor, ATI Mobility Radeon X600 GFX}
I need scale / transform controls and make it flow smoothly. Currently I'm manipulating the size and location of a control every 24-33ms (30fps), ±3px. When I add a 'fade' effect to an image, it fades in and out smoothly, but it is only 25x25 px in size. The control is 450x75 px to 450x250 px in size. In 2D games such as Bejeweled 3, the sprites animate with no choppy animation.
So as the title would suggest: which is easier/faster on the processor: animating a bitmap (rendering it to the parent control during animation) or animating the control it's self?
EDIT:
Hey, I thought this was a helpful community, not one that down-rates questions that don't seem challenging! (And I've seen more ridiculous questions here with better ratings too!) Please drop me a line first before negatively rating my questions!
I managed to find some free-time in my heck-tick scheduled, to quickly whip up a new project. I'm sure my time could have been better spent else where but hopefully someone else in my shoes may find this of use out there...
The answer is: a Picture over a Control. When rendering a bitmap onto the canvas, there are very little events that will fire, if any. As for the control, it is filled with events - some chained, some looped, and the addition of recursion, so a simple 'LocationChanged' event wouldn't even cover the half of what actually is taking place under the hood.
What I would do for controls that have lots of dynamic animations applied to them during runtime, is to develop a two piece set: a control [rendering] template or active interface (for when the control is at a stand-still or before the play of an animation), and a the animating structure with basic defining properties such as the display image [the rendered control], the rectangle bounds, and any animation algorithms that may be applied latter.
Edit: As Requested, here are the before and after code examples:
// This is the triggering event of the translating animation
private void object_Click(object sender, EventArgs e)
{
// the starting point is at (75,75)
element.Transform(new Point(500, 250));
}
Before:
public class ControlElement : UserControl
{
private Timer tick;
private Point pT0;
public ControlElement() : base()
{
tick = new Timer();
tick.Interval = 30; // about 30fps
tick.Tick += new EventHandler(tick_Tick);
}
void tick_Tick(object sender, EventArgs e)
{
// get the new point from distance and current location/destination
this.Location = Utils.Transform(this.Location, pT0, 3);
if ((pT0.X - this.Location.X)+(pT0.Y - this.Location.Y) <= 0)
{
this.Location = pT0;
tick.Stop();
//this.Visible = true;
}
}
public void Transform(Point destination)
{
pT0 = destination;
//this.Visible = false;
tick.Start();
}
}
After: I create a class that holds a picture of what the control would look like using the DrawToBitmap feature. It still contains the same animation methods as above. I had to add the Location and LocationChanged elements since this class was no longer a control. If and when the actual control needed to be accessed, I would stop rendering and display an instance of the control it's self.
Here is the rendering call:
void element_LocationChanged(object sender, EventArgs e)
{
canvas.Invalidate();
}
void canvas_Paint(object sender, PaintEventArgs e)
{
if (element != null)
{
Bitmap bmp = new Bitmap(element.Display);
Pen p = new Pen(Color.FromArgb(128, 128, 128), 1);
e.Graphics.DrawImage(bmp, element.Location);
e.Graphics.DrawRectangle(p,
element.Location.X, element.Location.Y,
bmp.Width, bmp.Height);
}
}

WPF Render Transform Behaving Weird

I am experiencing a weird problem with a render transform in WPF. The project I'm working on needs to display a clicked user point over an image. When the user clicks a point, a custom control is placed at the location of their click. The image should then be able to be scaled around any point using the mouse wheel, and the custom control should be translated (not scaled) to the correct location.
To do this, I follow the MouseWheel event as follows:
private void MapPositioner_MouseWheel(object sender, MouseWheelEventArgs e)
{
Point location = Mouse.GetPosition(MainWindow.Instance.imageMap);
MainWindow.Instance.imageMap.RenderTransform = null;
ScaleTransform st = new ScaleTransform(scale + (e.Delta < 0 ? -0.2 : 0.2), scale += (e.Delta < 0 ? -0.2 : 0.2));
st.CenterX = location.X;
st.CenterY = location.Y;
TransformGroup tg = new TransformGroup();
tg.Children.Add(st);
//tg.Children.Add(tt);
MainWindow.Instance.imageMap.RenderTransform = tg;
if (scale <= 1)
{
MainWindow.Instance.imageMap.RenderTransform = null;
}
if (TransformationChanged != null)
TransformationChanged();
}
Then, I implemented an event handler in the custom control for the TransformationChanged event seen at the end of the above code block as follows:
private void Instance_TransformationChanged()
{
//check image coords
//
if (MainWindow.Instance.imageMap.RenderTransform != null)
{
if (MainWindow.Instance.imageMap.RenderTransform != Transform.Identity)
{
Transform st = MainWindow.Instance.imageMap.RenderTransform;
Point image = MainWindow.VideoOverlayCanvas.TransformToVisual(MainWindow.Instance.MapImage).Transform(loc2);
Point trans = st.Transform(image);
Point final = MainWindow.Instance.MapImage.TransformToVisual(MainWindow.VideoOverlayCanvas).Transform(trans);
// selected = anchor2;
// final = ClipToOverlay(final);
// selected = null;
connector.X2 = final.X;
connector.Y2 = final.Y;
Canvas.SetLeft(anchor2, final.X);
Canvas.SetTop(anchor2, final.Y);
}
}
else
{
connector.X2 = loc2.X;
connector.Y2 = loc2.Y;
Canvas.SetLeft(anchor2, loc2.X);
Canvas.SetTop(anchor2, loc2.Y);
}
}
This way, I can ensure that the custom control's position is updated only after the new transform is set. Note that since I am applying the transform to the point, there is no scaling done to the control, the effect is that it is translated to the point it should. This works fine as long as the user is only scaling around one point. If they change that point, it doesnt work.
Here are some images that show the problem:
User clicks a point
user zooms out, what happened here?
after zooming out (all the way out in this case) it looks ok
I've been messing with this for about two days now, so I apologize if my code looks messy. I know this is a pretty obscure question so any help would be appreciated.
Thanks,
Max
If anyone is looking for an answer to this, because of deadlines, I had to write a workaround by having the user pan with the right mouse button and zoom with the mouse wheel. This way zooming always happens around the center of the image, so the controls are always lined up. I'm still looking for answers to the original question though if anyone can figure it out
Thanks,
Max
I'm not sure what's wrong with your transform, but have you considered an alternate approach? For example, you might want to add a transparent canvas set to stay at the same size as the image, z-order above the image (explicitly set or just put the Canvas element just after the image element). Then you can just use Canvas.SetLeft and Canvas.SetTop to place the user control where the user clicked, and to move it around. A lot easier than using a transform.

Categories

Resources