I'm trying to develop a c# windows form application that captures part of the screen and display it's mirror live video like in the windows form picturebox.
The problem that I'm facing is that when I set the form's visibility=false to capture part of the screen without capturing the form itself, then back to form visibility=true, I get this flickering mirrored and not mirrored picture displaying in the picturebox.
My issue is that I'm trying to mirror any video playing on what ever application i.e: youtube, windows media player or any other application by capturing multiple screenshots and displaying them in a picture box so that when the video is playing and the application is running in front of it, the user see's a mirror of whatever is playing behind the form live.
How do I stop the flickering and make this like video like live stream like of the back video but mirrored as the video is playing. Thank you in advance
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Mirror
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
#region Form Design and Controls
private void btnFlip_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
Bitmap myBitmap = new Bitmap(this.Size.Width, this.Size.Height);
this.Visible = false;
using (Graphics g = Graphics.FromImage(myBitmap))
{
g.CopyFromScreen(0, 0, 0, 0, myBitmap.Size, CopyPixelOperation.SourceCopy);
}
if (pictureBox1.Image != null)
{
pictureBox1.Image.Dispose();
this.pictureBox1.Image = myBitmap;
pictureBox1.Image.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipY);
GC.Collect();
}
this.Visible = true;
}
#endregion
}
}
Related
Continue from the overlay window's incorrect size problem.
So here is the minimum system:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.Size = new Size(1920, 1080);
MessageBox.Show("x:" + this.Size.Width + " y:" + this.Size.Height);
}
}
}
It says my window size is 1438x818 (even though it does appear to fill the desktop area of the screen)....
Did some new research
The problem starts to occur when my size is set larger than 14xx by 83x
Any size larger than that will be restricted to 14xx by 83x
if I say
this.size = new Size (500,500);
then it is okay...
[Final edit]
Well. I think I found the problem.
https://social.msdn.microsoft.com/Forums/vstudio/en-US/60e3b413-7746-46d4-8351-0c7f4e38378f/does-form-size-has-any-limitation-like-maximum-width-or-maximum-height?forum=netfxbcl
The form size does have a hidden limit and it seems that fixing it is out of my ability as an indie developer. I cannot find where is a hidden limitation is..
What I need to do is map the logic coordinate of anything in my form to a new world coordinate based on 1436/1920 scale ratio. Problem bypassed.
If you want to set size as 1920x1080 you can try this.
this.MinimumSize = new Size(1920, 1080);
this.MaximumSize = new Size(1920, 1080);
The size of the form must be lesser than or equal to current screen size.
Besides you can change the ClientSize of the form by
this.ClientSize = new System.Drawing.Size(1920, 1080);
I have been trying to create a test program that just displays a bitmap image on the screen for a while now. Ideally, the image would be translucent (have an alpha channel) and "click throughable." However, I have not found any way to do this.
The application that I have for this is a keyboard indicators app that runs in the background and displays a popup image onscreen for a couple seconds whenever a modifier like num lock or caps lock is pressed.
What I have found is an MSDN example for how to render an image on the screen, but I haven't been able to make this work properly in a Windows Forms app. In the Form1.cs of a blank WFA app, I have:
using System.Drawing;
using System.Windows.Forms;
namespace KeyboardIndicators
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
PictureBox pictureBox1 = new PictureBox();
pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
}
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs pe)
{
Bitmap myBitmap = new Bitmap("Profile Image.jpg");
Graphics g = pe.Graphics;
g.DrawImage(myBitmap, 100, 100);
}
}
}
I am probably missing a lot here, but I am not having much luck debugging it in Visual Studio.
I have yet to find a site online that fully describes how to do something like what I would like to do. I have seen this kind of thing done before in other apps, so I know it can be done somehow.
I found the answer to my question thanks to the initial answer by #Habeeb on this question, which inspired me to research that method. By looking at this Q/A, I realized I didn't need to create a helper function to do this. To #Idle_Mind's point also, I set the WS_EX_TRANSPARENT flag to transparent.
This is the code I ended up with in my Form1.cs file: (I ended up changing the test image to cube.png, a .png image with an alpha channel)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace KeyboardIndicators {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
PictureBox pictureBox = new PictureBox();
Image myBitmap = Image.FromFile("cube.png");
Size bitmapSize = new Size(myBitmap.Width, myBitmap.Height);
this.Size = bitmapSize;
pictureBox.ClientSize = bitmapSize;
pictureBox.Image = myBitmap;
pictureBox.Dock = DockStyle.Fill;
this.Controls.Add(pictureBox);
this.FormBorderStyle = FormBorderStyle.None;
}
protected override CreateParams CreateParams {
get {
CreateParams createParams = base.CreateParams;
createParams.ExStyle |= 0x00000020; // WS_EX_TRANSPARENT
return createParams;
}
}
}
}
When run, the following is shown onscreen:
This works for me, as it is overlayed on all apps I need, is semi-transparent and is click-throughable.
From your code, I do not see the Bitmap image is set to the PictureBox.
Please try the below code:
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage ;
MyImage = new Bitmap(fileToDisplay);
pictureBox1.ClientSize = new Size(xSize, ySize);
pictureBox1.Image = (Image) MyImage ;
If you want to add PictureBox via code, see below:
private void Form1_Load(object sender, EventArgs e)
{
var picture = new PictureBox
{
Name = "pictureBox1",
Size = new Size(xSize, ySize),
Location = new Point(100, 100),
Image = Image.FromFile("hello.jpg"),
};
this.Controls.Add(picture);
}
The first piece of code shows how to update image, but a different approach.
Here is the code i'm currently using in C# and EmguCV included:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.Util;
namespace CameraCapture
{
public partial class CameraCapture : Form
{
//declaring global variables
private Capture capture; //takes images from camera as image frames
private bool captureInProgress; // checks if capture is executing
public CameraCapture()
{
InitializeComponent();
}
private void ProcessFrame(object sender, EventArgs arg)
{
Image<Bgr, Byte> ImageFrame = capture.QueryFrame();
Image<Bgr, Byte> template = new Image<Bgr, byte>(#"D:\yugiCards\kuriboh.jpg");
Image<Bgr, Byte> imageToShow = ImageFrame.Copy();
using (Image<Gray, float> result = imageToShow.MatchTemplate(template, Emgu.CV.CvEnum.TM_TYPE.CV_TM_CCOEFF_NORMED))
{
double[] minValues, maxValues;
Point[] minLocations, maxLocations;
result.MinMax(out minValues, out maxValues, out minLocations, out maxLocations);
// You can try different values of the threshold. I guess somewhere between 0.75 and 0.95 would be good.
if (maxValues[0] > 0.9)
{
// This is a match. Do something with it, for example draw a rectangle around it.
Rectangle match = new Rectangle(maxLocations[0], template.Size);
imageToShow.Draw(match, new Bgr(Color.Red), 3);
}
}
CamImageBox.Image = imageToShow;
//ImageFrame.Save(#"E:\MyPic.jpg"); //saves to location
}
private void CameraOutput_Load(object sender, EventArgs e)
{
}
private void btnStart_Click(object sender, EventArgs e)
{
#region if capture is not created, create it now
if (capture == null)
{
try
{
capture = new Capture();
}
catch (NullReferenceException excpt)
{
MessageBox.Show(excpt.Message);
}
}
#endregion
if (capture != null)
{
if (captureInProgress)
{ //if camera is getting frames then stop the capture and set button Text
// "Start" for resuming capture
btnStart.Text = "Start!"; //
Application.Idle -= ProcessFrame;
}
else
{
//if camera is NOT getting frames then start the capture and set button
// Text to "Stop" for pausing capture
btnStart.Text = "Stop";
Application.Idle += ProcessFrame;
}
captureInProgress = !captureInProgress;
}
}
private void ReleaseData()
{
if (capture != null)
capture.Dispose();
}
}
}
I am trying to find a template in the camera capture, however, when I run the program and start camera capture my camera LED lights up and then the program becomes not responding when it's trying to capture. Maybe it has to do with the placement of the match template function or the types of variables used but I'm not really sure since I'm not that experienced so I wanted some input on the problem with my code.
I do realize the imageToShow variable isn't needed but I decided to leave it be until I can get the thing working then I can mess around with it more myself.
Code for detecting the template was found here
emgu finding image a in image b
It was mainly for detecting template between 2 static images though, but I edited the source to be from the webcam.
The webcam is working normally when I remove the using match template segment from the code.
Any input would be appreciated, thanks and sorry if it is an obvious error I'm still new to this kind of thing.
EDIT: Forgot to mention it gives this error when debugging The program
'[6164] CameraCapture.vshost.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'.
Solved, after hours of trying to mess around with the code it turned out the template being used just wasn't a good one.
After looking more into what the author of the code said, he mentioned you might want grey around your template, thought he meant the Bgr to Gray that's why I was frustrated with the code. Turned out it meant you literally needed grey around your template.
I would like to do some image processing in C# and need to align two images before applying a filter to them. I will attempt to do this by scanning the images at a fixed point in a small rectangular section, which I believe makes it necessary to use the Bitmap class.
This section has a large amount of white pixels so I would like to take an average pixel value in this area to find the shift in the y-axis, as there is a large white horizontal bar going across the images.
The x-axis will be the same in both images. I would like to setup a few test images with different shift values, from small to large, positive and negative, so I can search for the minimum value .
This will require a scroll bar on the images to move them in small amounts.
I am totally new to C#, and low level programmer. I have been trying to get the image in pictureBox1 with the following code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing.Imaging;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace imageAlign
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Bitmap myImage = (Bitmap)pictureBox1.Image;
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) ;
{
pictureBox1.Image = Image.FromFile();
// this.pictureBox1.Image = myImage;
}
}
}
}
I have left the Image.FromFile(); with nothing passed as I wish to choose the images when I click the button on the form. Currently, I only have one button and picture box.
You need to use the FileName property of the OpenFileDialog:
if (ofd.ShowDialog() == DialogResult.OK && ofd.FileName != "")
{
pictureBox1.Image = Image.FromFile(ofd.FileName);
}
From the link:
The file name includes both the file path and the extension. If no files are selected, this method returns an empty string ("").
I'm trying to display Kinect's video stream into PictureBox. The reason is, I'd like to overlay it with some images and use FillEllipse() method to add real time markers.
However, I ended up with a box with a red x (cross) in it. Could someone show me, where did I go wrong? Should I use WritableBitmap instead? I had a thought of this, but Writeable bitmap does not offer method such as FillEllipse() to place markers.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Kinect;
using System.Drawing.Imaging;
using System.Drawing;
using System.Runtime.InteropServices;
namespace fTrack_WF
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
KinectSensor myKinect;
private void Window_Loaded(object sender, EventArgs e)
{
if (KinectSensor.KinectSensors.Count == 0)
{
MessageBox.Show("No Kinects device detected", "Camera View");
Application.Exit();
return;
}
try
{
// get first Kinect device attached on computer
myKinect = KinectSensor.KinectSensors[0];
// enable depth stream
myKinect.DepthStream.Enable();
// enable color video stream
myKinect.ColorStream.Enable();
// start the sensor
myKinect.Start();
// connect up the video event handler
myKinect.ColorFrameReady += new EventHandler<ColorImageFrameReadyEventArgs>(myKinect_ColorFrameReady);
}
catch
{
MessageBox.Show("Kinect initialise failed", "Camera viewer");
Application.Exit();
}
}
#region Video Image Processing
byte[] colorData = null;
Bitmap kinectVideoBitmap = null;
IntPtr colorPtr;
void myKinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if (colorFrame == null) return;
if (colorData == null)
colorData = new byte[colorFrame.PixelDataLength];
colorFrame.CopyPixelDataTo(colorData);
Marshal.FreeHGlobal(colorPtr);
colorPtr = Marshal.AllocHGlobal(colorData.Length);
Marshal.Copy(colorData, 0, colorPtr, colorData.Length);
kinectVideoBitmap = new Bitmap(
colorFrame.Width,
colorFrame.Height,
colorFrame.Width * colorFrame.BytesPerPixel;
PixelFormat.Format32bppRgb,
colorPtr);
kinectVideoBox.Image = kinectVideoBitmap;
kinectVideoBitmap.Dispose();
}
}
#endregion
}
}
Thank you very much!
Regards,
ikel
I'm not clear why you are using a WinForms PictureBox over just using WPF.
Have you tried placing a Canvas on top of the video stream, demonstrated in the SDK examples, and simply drawn to that?
<Grid HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="320" Height="240">
<lt:KinectDepthViewer x:Name="DepthViewer" KinectSensorManager="{Binding KinectSensorManager}" />
<Canvas>
<lt:KinectSkeletonViewer
KinectSensorManager="{Binding KinectSensorManager}"
Width="{Binding ElementName=DepthViewer, Path=ActualWidth}"
Height="{Binding ElementName=DepthViewer, Path=ActualHeight}"
ShowBones="True" ShowJoints="True" ShowCenter="True" ImageType="Depth" />
</Canvas>
</Grid>
<Canvas Name="DrawingCanvas">
</Canvas>
The second canvas is at a higher z-index and any object on that will cover up your video stream.
P.S.
Although my code points to the depth viewer, the video stream is done in the same way when using the examples from the SDK.
I found the answer. Dispose is necessary to free up resources as indicated here. The problem was, I disposed too early after drawing it, and so it appeared as if nothing was drawn. However, the clearer answer, to me anyway, was given here.
Bitmap inherits from Image, which implements IDisposable, so when
you're done using an instance, you should call Dispose() on it. This
will clean up the unmanaged resource in Image.
However, Image also implements a finalizer, so if for some reason you
cannot call Dispose(), the resource will be reclaimed during
finalization of the instance, which will happen at some point after
the instance is no longer referenced.
I simply removed kinectVideoBitmap.Dispose(); and my Windows Forms displays Kinect's video stream inside PictureBox control.
Regards,
ikel