How to build a C# IP camera software that enables Pan-Tilt-Zoom (PTZ) motion control

Timo.Walker
Posted by in C# category on for Intermediate level | Points: 250 | Views : 46361 red flag
Rating: 5 out of 5  
 1 vote(s)

In this guide I would like to present an easy solution on how to increase the efficiency of your IP-based surveillance system by building your own camera software. I will show how to implement PTZ (Pan-Tilt-Zoom) motion control in C# by using prewritten Onvif-based components.


 Download source code for How to build a C# IP camera software that enables Pan-Tilt-Zoom (PTZ) motion control

Introduction

Ever since I installed some IP cameras in my workplace, I am more and more interested in getting the most out of this smart video surveillance technology. As a first step on this way, I looked for a solution that enables to control the PTZ (Pan-Tilt-Zoom) functionality through my own C# application. Concerning to the huge importance of security technology, I decided to share my first wing-beats with my fellow developers – hoping that it could be useful for you and trusting that we can exchange further ides related to IP camera programming. So, wishing you good reading, have fun and do not hesitate to share your ideas!



Technical background - Glossary

For better understanding, let's see the most important terms and definitions related to this topic. Take a moment to study the following brief glossary to find out more about the IP camera tecnology:

IP camera: An IP camera can be described as a camera and computer combined in one unit. It is also called ’network camera’. IP camera is a type of digital video cameras. ’IP’ refers to the IP cameras’ characteristics that they can send and receive data over the Internet Protocol.  The main components of an IP camera are the followings:  a lens, an image sensor, one or several processors, and memory. The processors are used for image processing, compression, video analysis and networking functionalities. Like a computer, an IP camera also has its own IP address, that is used to connect the device directly to a network (Source [1]).

IP surveillance system: IP surveillance is a digitized and networked version of CCTV. An IP camera connected to an IP surveillance system can be used to record video footage that will be transmitted through an IP-based network. Digitization provides easy-to-use user interface, better image quality, video recording functionality and the abilty to compress content for improved storage (Source [2]).

CCTV: CCTV is the acronym for Closed-circuit television. It is the use of video cameras to transmit a signal to a specific place on monitors. The CCTV cameras are commonly used to for surveillance in areas that may need monitoring as well as banks, casinos, airports, military installations, and convenience stores. The most common field of use: crime prevention, industrial processes, traffic monitoring, transport safety, control of retail, use in school, etc. A growing branch in CCTV is IP cameras (Source [3]).

PTZ: PTZ is the acronym for Pan-Tilt-Zoom. It refers tot he movement options of the camera: panning horizontally, tilting vertically and zooming in to enlarge an object (Source [4]).

PTZ IP camera: This is an IP camera that is capable of remote directional and zoom control. A special type of PTZ IP cameras is ePTZ (or VPTZ – Virtual Pan-Tilt-Zoom) where a high-resolution camera digitally zooms and pans into portions of the image, with no physical camera movement (Source [4]).

ONVIF: ONVIF is an open industry forum that is intended to facilitate the development and use of a global open standard for the interface of physical IP-based security products. ONVIF has been established in 2008 by Axis Communications, Bosch Security Systems and Sony with the goal to achieve interoperability between network video products regardless of manufacturer. The keystones of ONVIF are the following: standardization of communication between IP-based video devices; interoperability between IP-based security devices regardless of manufacturer; open to all companies and organizations (Source [5], [6]).


What you need

To be able to start the implementation of your C# IP camera software that enables Pan-Tilt-Zoom (PTZ) motion control, your system needs to meet with some special hardware and software requirements.

Hardware requirements: A computer is essentially needed of course. You need one or more IP cameras as well. (Be sure that your PC and your IP cameras are connected to the same network.) To be able to implement this application your IP cameras have to be capable of PTZ functionality.

Software requirements: For programming a Windows Forms Application like mine, Visual Studio (Download link [7]) and .NET Framework 4 (Download link [8]) should be installed on your PC. You also need a software development kit that supports the ONVIF standardization. I used Ozeki Camera SDK (Download link [9]) that provides instant ONVIF components for IP camera developments. (It is important to know that you need to add the DLL file offered by the SDK to your references in Visual Studio, and you also need to change your target framework to ’.NET Framwork 4.0’.)

Others: Due the IP networks’ characteristics, broadband Internet connection is also needed.


Code explanation


For implementing this PTZ motion controller application in C# you will need the following classes: Form1.cs, Form1.Designer.cs. All of their objects have been declared at the beginning of the Form1.cs (you will see the full source code below).

The following methods allow you to move your PTZ camera physically: 

private void MouseDownMove(object sender, MouseEventArgs e)
private void MouseUpMove(object sender, MouseEventArgs e)
public void Move(string direction)

And the method below can be used to move the camera in the desired direction. This motion lasts until the camera can move. It has one parameter, the MoveDirection.

_camera.CameraMovement.ContinuousMove(MoveDirection.LeftUp)

By using the MoveDirection parameter, the direction of movement can be determined. You only need to select the correct member of the enumeration that can be one of followings:

MoveDirection.LeftUp
MoveDirection.Up
MoveDirection.RightUp
MoveDirection.Right
MoveDirection.RightDown
MoveDirection.Down
MoveDirection.LeftDown
MoveDirection.Left


Source Code for Form1.cs

As a first step, you need to create a simple IP camera viewer to be able to view the camera image that you want to move. After initializing the necessary objects mentioned above, you need to call the SetVideoViewer() method then add the VideoViewerFM object to the control collection of the panel. As you can see in the code example, a ’Connect’ button will be added to the GUI of your application that is for creating connection between your application and your IP camera. Below you can see the methods that should be called when the user presses the ’Connect’ button:

using System;
using System.Drawing;
using System.Windows.Forms;
using Ozeki.Media.MediaHandlers.Video;
using Ozeki.Media.Video.Controls;
using Ozeki.Media.MediaHandlers;
using Ozeki.Media.MediaHandlers.IPCamera;
using Ozeki.Media.MediaHandlers.IPCamera.Types;
using Ozeki.Media.IPCamera;
using Ozeki.Media.IPCamera.PTZ;

namespace PTZ_Camera_Motion_Control01
{
    public partial class Form1 : Form
    {
        private IIPCamera _camera;
        private DrawingImageProvider _imageProvider;
        private MediaConnector _connector;
        private VideoViewerWF _videoViewerWf;

        public Form1()
        {
            InitializeComponent();
            _imageProvider = new DrawingImageProvider();
            _connector = new MediaConnector();
            _videoViewerWf = new VideoViewerWF();
            SetVideoViewer();
        }

        private void SetVideoViewer()
        {
            CameraBox.Controls.Add(_videoViewerWf);
            _videoViewerWf.Size = new Size(260, 180);
            _videoViewerWf.BackColor = Color.Black;
            _videoViewerWf.TabStop = false;
            _videoViewerWf.Location = new Point(14, 19);
            _videoViewerWf.Name = "_videoViewerWf";
        }

        private void button_Connect_Click(object sender, EventArgs e)
        {
            _camera = IPCameraFactory.GetCamera("192.168.115.175:8080", "admin", "admin");
            _connector.Connect(_camera.VideoChannel, _imageProvider);
            _videoViewerWf.SetImageProvider(_imageProvider);
            _videoViewerWf.Start();
            _camera.Start();
        }

        private void MouseDownMove(object sender, MouseEventArgs e)
        {
            var button = sender as Button;
            if (button != null) Move(button.Text);
        }

        private void MouseUpMove(object sender, MouseEventArgs e)
        {
            _camera.CameraMovement.StopMovement();
        }

        private void Move(string direction)
        {
            if (_camera == null) return;
            switch (direction)
            {
                case "Up Left":
                    _camera.CameraMovement.ContinuousMove(MoveDirection.LeftUp);
                    break;
                case "Up":
                    _camera.CameraMovement.ContinuousMove(MoveDirection.Up);
                    break;
                case "Up Right":
                    _camera.CameraMovement.ContinuousMove(MoveDirection.RightUp);
                    break;
                case "Left":
                    _camera.CameraMovement.ContinuousMove(MoveDirection.Left);
                    break;
                case "Right":
                    _camera.CameraMovement.ContinuousMove(MoveDirection.Right);
                    break;
                case "Down Left":
                    _camera.CameraMovement.ContinuousMove(MoveDirection.LeftDown);
                    break;
                case "Down":
                    _camera.CameraMovement.ContinuousMove(MoveDirection.Down);
                    break;
                case "Down Right":
                    _camera.CameraMovement.ContinuousMove(MoveDirection.RightDown);
                    break;
                case "In":
                    _camera.CameraMovement.Zoom(ZoomDirection.In);
                    break;
                case "Out":
                    _camera.CameraMovement.Zoom(ZoomDirection.Out);
                    break;
            }
        }
    }
}

Source Code for Form1.Designer.cs

And finally, take a look at the following code snippet that shows the Form1.Designer.cs class. You can use this code to create a really simple GUI for your PTZ motion controller application (under the source code you will find a screenshot about the GUI):

namespace PTZ_Camera_Motion_Control01
{
    partial class Form1
    {
        private System.ComponentModel.IContainer components = null;

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void InitializeComponent()
        {
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.button_Connect = new System.Windows.Forms.Button();
            this.CameraBox = new System.Windows.Forms.GroupBox();
            this.CameraMoveBox = new System.Windows.Forms.GroupBox();
            this.buttonDownRight = new System.Windows.Forms.Button();
            this.buttonRight = new System.Windows.Forms.Button();
            this.buttonUpRight = new System.Windows.Forms.Button();
            this.buttonDown = new System.Windows.Forms.Button();
            this.buttonUp = new System.Windows.Forms.Button();
            this.buttonDownLeft = new System.Windows.Forms.Button();
            this.buttonLeft = new System.Windows.Forms.Button();
            this.buttonUpLeft = new System.Windows.Forms.Button();
            this.groupBox2 = new System.Windows.Forms.GroupBox();
            this.button_ZoomOut = new System.Windows.Forms.Button();
            this.button_ZoomIn = new System.Windows.Forms.Button();
            this.groupBox1.SuspendLayout();
            this.CameraMoveBox.SuspendLayout();
            this.groupBox2.SuspendLayout();
            this.SuspendLayout();
            // 
            // groupBox1
            // 
            this.groupBox1.Controls.Add(this.button_Connect);
            this.groupBox1.Location = new System.Drawing.Point(10, 10);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(100, 60);
            this.groupBox1.TabIndex = 0;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "Connect";
            // 
            // button_Connect
            // 
            this.button_Connect.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
            this.button_Connect.ForeColor = System.Drawing.Color.Black;
            this.button_Connect.Location = new System.Drawing.Point(10, 20);
            this.button_Connect.Name = "button_Connect";
            this.button_Connect.Size = new System.Drawing.Size(75, 25);
            this.button_Connect.TabIndex = 6;
            this.button_Connect.Text = "Connect";
            this.button_Connect.UseVisualStyleBackColor = true;
            this.button_Connect.Click += new System.EventHandler(this.button_Connect_Click);
            // 
            // CameraBox
            // 
            this.CameraBox.Location = new System.Drawing.Point(10, 90);
            this.CameraBox.Name = "CameraBox";
            this.CameraBox.Size = new System.Drawing.Size(290, 210);
            this.CameraBox.TabIndex = 3;
            this.CameraBox.TabStop = false;
            this.CameraBox.Text = "Live camera ";
            // 
            // CameraMoveBox
            // 
            this.CameraMoveBox.Controls.Add(this.buttonDownRight);
            this.CameraMoveBox.Controls.Add(this.buttonRight);
            this.CameraMoveBox.Controls.Add(this.buttonUpRight);
            this.CameraMoveBox.Controls.Add(this.buttonDown);
            this.CameraMoveBox.Controls.Add(this.buttonUp);
            this.CameraMoveBox.Controls.Add(this.buttonDownLeft);
            this.CameraMoveBox.Controls.Add(this.buttonLeft);
            this.CameraMoveBox.Controls.Add(this.buttonUpLeft);
            this.CameraMoveBox.Location = new System.Drawing.Point(10, 300);
            this.CameraMoveBox.Name = "CameraMoveBox";
            this.CameraMoveBox.Size = new System.Drawing.Size(290, 115);
            this.CameraMoveBox.TabIndex = 4;
            this.CameraMoveBox.TabStop = false;
            this.CameraMoveBox.Text = "Control";
            // 
            // buttonDownRight
            // 
            this.buttonDownRight.Location = new System.Drawing.Point(205, 80);
            this.buttonDownRight.Name = "buttonDownRight";
            this.buttonDownRight.Size = new System.Drawing.Size(75, 25);
            this.buttonDownRight.TabIndex = 7;
            this.buttonDownRight.Text = "Down Right";
            this.buttonDownRight.UseVisualStyleBackColor = true;
            this.buttonDownRight.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MouseDownMove);
            this.buttonDownRight.MouseUp += new System.Windows.Forms.MouseEventHandler(this.MouseUpMove);
            // 
            // buttonRight
            // 
            this.buttonRight.Location = new System.Drawing.Point(205, 50);
            this.buttonRight.Name = "buttonRight";
            this.buttonRight.Size = new System.Drawing.Size(75, 25);
            this.buttonRight.TabIndex = 6;
            this.buttonRight.Text = "Right";
            this.buttonRight.UseVisualStyleBackColor = true;
            this.buttonRight.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MouseDownMove);
            this.buttonRight.MouseUp += new System.Windows.Forms.MouseEventHandler(this.MouseUpMove);
            // 
            // buttonUpRight
            // 
            this.buttonUpRight.Location = new System.Drawing.Point(205, 20);
            this.buttonUpRight.Name = "buttonUpRight";
            this.buttonUpRight.Size = new System.Drawing.Size(75, 25);
            this.buttonUpRight.TabIndex = 5;
            this.buttonUpRight.Text = "Up Right";
            this.buttonUpRight.UseVisualStyleBackColor = true;
            this.buttonUpRight.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MouseDownMove);
            this.buttonUpRight.MouseUp += new System.Windows.Forms.MouseEventHandler(this.MouseUpMove);
            // 
            // buttonDown
            // 
            this.buttonDown.Location = new System.Drawing.Point(105, 80);
            this.buttonDown.Name = "buttonDown";
            this.buttonDown.Size = new System.Drawing.Size(75, 25);
            this.buttonDown.TabIndex = 4;
            this.buttonDown.Text = "Down";
            this.buttonDown.UseVisualStyleBackColor = true;
            this.buttonDown.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MouseDownMove);
            this.buttonDown.MouseUp += new System.Windows.Forms.MouseEventHandler(this.MouseUpMove);
            // 
            // buttonUp
            // 
            this.buttonUp.Location = new System.Drawing.Point(105, 20);
            this.buttonUp.Name = "buttonUp";
            this.buttonUp.Size = new System.Drawing.Size(75, 23);
            this.buttonUp.TabIndex = 3;
            this.buttonUp.Text = "Up";
            this.buttonUp.UseVisualStyleBackColor = true;
            this.buttonUp.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MouseDownMove);
            this.buttonUp.MouseUp += new System.Windows.Forms.MouseEventHandler(this.MouseUpMove);
            // 
            // buttonDownLeft
            // 
            this.buttonDownLeft.Location = new System.Drawing.Point(10, 80);
            this.buttonDownLeft.Name = "buttonDownLeft";
            this.buttonDownLeft.Size = new System.Drawing.Size(75, 25);
            this.buttonDownLeft.TabIndex = 2;
            this.buttonDownLeft.Text = "Down Left";
            this.buttonDownLeft.UseVisualStyleBackColor = true;
            this.buttonDownLeft.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MouseDownMove);
            this.buttonDownLeft.MouseUp += new System.Windows.Forms.MouseEventHandler(this.MouseUpMove);
            // 
            // buttonLeft
            // 
            this.buttonLeft.Location = new System.Drawing.Point(10, 50);
            this.buttonLeft.Name = "buttonLeft";
            this.buttonLeft.Size = new System.Drawing.Size(75, 25);
            this.buttonLeft.TabIndex = 1;
            this.buttonLeft.Text = "Left";
            this.buttonLeft.UseVisualStyleBackColor = true;
            this.buttonLeft.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MouseDownMove);
            this.buttonLeft.MouseUp += new System.Windows.Forms.MouseEventHandler(this.MouseUpMove);
            // 
            // buttonUpLeft
            // 
            this.buttonUpLeft.Location = new System.Drawing.Point(10, 20);
            this.buttonUpLeft.Name = "buttonUpLeft";
            this.buttonUpLeft.Size = new System.Drawing.Size(75, 25);
            this.buttonUpLeft.TabIndex = 0;
            this.buttonUpLeft.Text = "Up Left";
            this.buttonUpLeft.UseVisualStyleBackColor = true;
            this.buttonUpLeft.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MouseDownMove);
            this.buttonUpLeft.MouseUp += new System.Windows.Forms.MouseEventHandler(this.MouseUpMove);
            // 
            // groupBox2
            // 
            this.groupBox2.Controls.Add(this.button_ZoomOut);
            this.groupBox2.Controls.Add(this.button_ZoomIn);
            this.groupBox2.Location = new System.Drawing.Point(12, 420);
            this.groupBox2.Name = "groupBox2";
            this.groupBox2.Size = new System.Drawing.Size(290, 60);
            this.groupBox2.TabIndex = 5;
            this.groupBox2.TabStop = false;
            this.groupBox2.Text = "Zoom";
            // 
            // button_ZoomOut
            // 
            this.button_ZoomOut.Location = new System.Drawing.Point(205, 20);
            this.button_ZoomOut.Name = "button_ZoomOut";
            this.button_ZoomOut.Size = new System.Drawing.Size(75, 25);
            this.button_ZoomOut.TabIndex = 1;
            this.button_ZoomOut.Text = "Out";
            this.button_ZoomOut.UseVisualStyleBackColor = true;
            // 
            // button_ZoomIn
            // 
            this.button_ZoomIn.Location = new System.Drawing.Point(10, 20);
            this.button_ZoomIn.Name = "button_ZoomIn";
            this.button_ZoomIn.Size = new System.Drawing.Size(75, 25);
            this.button_ZoomIn.TabIndex = 0;
            this.button_ZoomIn.Text = "In";
            this.button_ZoomIn.UseVisualStyleBackColor = true;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(309, 489);
            this.Controls.Add(this.groupBox2);
            this.Controls.Add(this.CameraMoveBox);
            this.Controls.Add(this.CameraBox);
            this.Controls.Add(this.groupBox1);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
            this.MaximizeBox = false;
            this.Name = "Form1";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "PTZ Camera Motion Control";
            this.groupBox1.ResumeLayout(false);
            this.CameraMoveBox.ResumeLayout(false);
            this.groupBox2.ResumeLayout(false);
            this.ResumeLayout(false);
        }

        private System.Windows.Forms.GroupBox groupBox1;
        private System.Windows.Forms.Button button_Connect;
        private System.Windows.Forms.GroupBox CameraBox;
        private System.Windows.Forms.GroupBox CameraMoveBox;
        private System.Windows.Forms.Button buttonDownRight;
        private System.Windows.Forms.Button buttonRight;
        private System.Windows.Forms.Button buttonUpRight;
        private System.Windows.Forms.Button buttonDown;
        private System.Windows.Forms.Button buttonUp;
        private System.Windows.Forms.Button buttonDownLeft;
        private System.Windows.Forms.Button buttonLeft;
        private System.Windows.Forms.Button buttonUpLeft;
        private System.Windows.Forms.GroupBox groupBox2;
        private System.Windows.Forms.Button button_ZoomOut;
        private System.Windows.Forms.Button button_ZoomIn;
    }
}

By using the code snippet above, the following Graphical User Interface can be seen on your monitor:


The ’Connect’ button can be used to create a connection between your IP camera and your application. After pressing it, the IP camera view will be displayed. Under the live camera stream you can find some buttons that allows you to move the camera to 8 directions: up; down; left; right; up left; up right; down left and down right. You can also find two buttons to zoom in and zoom out. Due to these functionalities, our IP camera installed in the corridor can be controlled to show the door that needs to be monitored.


Conclusion

This guide was intended to present an easy solution on how to increase the efficiency of your IP-based surveillance system. You could see above how simple to implement PTZ (Pan-Tilt-Zoom) motion control in C# by using prewritten Onvif-based components. For further reading and getting the necessary software take a look at the following knowledge base that was used to compose this article:


Reference

Page copy protected against web site content infringement by Copyscape

About the Author

Timo.Walker
Full Name: Timothy Walker
Member Level: Starter
Member Status: Member
Member Since: 9/11/2014 4:18:57 AM
Country: United Kingdom



Login to vote for this post.

Comments or Responses

Login to post response

Comment using Facebook(Author doesn't get notification)