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