mirror of https://github.com/emgucv/emgucv.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
436 lines
16 KiB
436 lines
16 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Runtime.Serialization;
|
|
using System.Xml.Serialization;
|
|
using System.Diagnostics;
|
|
using System.Runtime.InteropServices;
|
|
using System.IO;
|
|
using zlib;
|
|
|
|
namespace Emgu.CV
|
|
{
|
|
///<summary>
|
|
///The Array class that wrap around CvArr in OpenCV
|
|
///</summary>
|
|
public abstract class CvArray<D> : UnmanagedObject, IXmlSerializable, ISerializable
|
|
{
|
|
/// <summary>
|
|
/// The pinned GcHandle to _array;
|
|
/// </summary>
|
|
protected GCHandle _dataHandle;
|
|
|
|
///<summary> The pointer to the internal structure </summary>
|
|
public new IntPtr Ptr { get { return _ptr; } set { _ptr = value; } }
|
|
|
|
#region properties
|
|
///<summary>
|
|
/// The width of the Array
|
|
///</summary>
|
|
public abstract int Width { get; }
|
|
|
|
///<summary>
|
|
/// The height of the Array
|
|
/// </summary>
|
|
public abstract int Height { get; }
|
|
|
|
/// <summary>
|
|
/// The number of rows for this array
|
|
/// </summary>
|
|
public int Rows { get { return Height; } }
|
|
|
|
/// <summary>
|
|
/// The number of cols for this array
|
|
/// </summary>
|
|
public int Cols { get { return Width; } }
|
|
|
|
/// <summary>
|
|
/// Get or Set an Array of bytes that represent the data in this array
|
|
/// </summary>
|
|
/// <remarks> Should only be used for serialization & deserialization</remarks>
|
|
[System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
|
public Byte[] Bytes
|
|
{
|
|
get
|
|
{
|
|
int size = System.Runtime.InteropServices.Marshal.SizeOf(typeof(D)) * ManagedArray.Length;
|
|
Byte[] res = new Byte[size];
|
|
Marshal.Copy(_dataHandle.AddrOfPinnedObject(), res, 0, size);
|
|
return res;
|
|
}
|
|
set
|
|
{
|
|
int size = System.Runtime.InteropServices.Marshal.SizeOf(typeof(D)) * ManagedArray.Length;
|
|
Marshal.Copy(value, 0, _dataHandle.AddrOfPinnedObject(), size);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the underneath managed array
|
|
/// </summary>
|
|
public abstract System.Array ManagedArray { get; }
|
|
|
|
/// <summary>
|
|
/// Allocate data for the array
|
|
/// </summary>
|
|
/// <param name="rows">The number of rows</param>
|
|
/// <param name="cols">The number of columns</param>
|
|
protected abstract void AllocateData(int rows, int cols);
|
|
|
|
///<summary>
|
|
///The binary data in compressed format
|
|
///</summary>
|
|
[System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
|
public Byte[] CompressedBytes
|
|
{
|
|
get
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
{
|
|
//GZipStream compressedStream = new GZipStream(ms , CompressionMode.Compress);
|
|
using (zlib.ZOutputStream compressedStream = new zlib.ZOutputStream(ms, zlib.zlibConst.Z_BEST_COMPRESSION))
|
|
{
|
|
Byte[] data = Bytes;
|
|
compressedStream.Write(data, 0, data.Length);
|
|
compressedStream.Flush();
|
|
}
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
set
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
{
|
|
using (zlib.ZOutputStream compressedStream = new zlib.ZOutputStream(ms))
|
|
{
|
|
compressedStream.Write(value, 0, value.Length);
|
|
Bytes = ms.ToArray();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// sum of diagonal elements of the matrix
|
|
/// </summary>
|
|
[System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
|
public MCvScalar Trace
|
|
{
|
|
get
|
|
{
|
|
return CvInvoke.cvTrace(Ptr);
|
|
}
|
|
}
|
|
|
|
///<summary>
|
|
///The norm of this Array
|
|
///</summary>
|
|
[System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
|
public double Norm
|
|
{
|
|
get
|
|
{
|
|
return CvInvoke.cvNorm(Ptr, IntPtr.Zero, 4, IntPtr.Zero);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Calculates and returns the Euclidean dot product of two arrays.
|
|
/// src1•src2 = sumI(src1(I)*src2(I))
|
|
/// In case of multiple channel arrays the results for all channels are accumulated. In particular, cvDotProduct(a,a), where a is a complex vector, will return ||a||2. The function can process multi-dimensional arrays, row by row, layer by layer and so on.
|
|
/// </summary>
|
|
/// <param name="src2">The other Array to apply dot product with</param>
|
|
/// <returns>src1•src2</returns>
|
|
public double DotProduct(CvArray<D> src2)
|
|
{
|
|
return CvInvoke.cvDotProduct(Ptr, src2.Ptr);
|
|
}
|
|
|
|
#region Coping and filling
|
|
///<summary>
|
|
/// Copy the current image to another one
|
|
/// </summary>
|
|
/// <param name="dest"> The destination Array</param>
|
|
public void Copy(CvArray<D> dest)
|
|
{
|
|
CvInvoke.cvCopy(Ptr, dest.Ptr, IntPtr.Zero);
|
|
}
|
|
|
|
///<summary>
|
|
///Set the element of the Array to <paramref name="val"/>
|
|
///</summary>
|
|
///<param name="val"> The value to be set for each element of the Array </param>
|
|
public void SetValue(MCvScalar val)
|
|
{
|
|
CvInvoke.cvSet( _ptr, val, IntPtr.Zero);
|
|
}
|
|
|
|
///<summary>
|
|
///Set the element of the Array to <paramref name="val"/>
|
|
///</summary>
|
|
///<param name="val"> The value to be set for each element of the Array </param>
|
|
public void SetValue(double val)
|
|
{
|
|
SetValue(new MCvScalar(val, val, val, val));
|
|
}
|
|
|
|
///<summary>
|
|
///Set the element of the Array to <paramref name="val"/>, using the specific <paramref name="mask"/>
|
|
///</summary>
|
|
///<param name="val">The value to be set</param>
|
|
///<param name="mask">The mask for the operation</param>
|
|
public void SetValue(MCvScalar val, CvArray<Byte> mask)
|
|
{
|
|
CvInvoke.cvSet( _ptr, val, mask.Ptr);
|
|
}
|
|
|
|
///<summary>
|
|
///Set the element of the Array to <paramref name="val"/>, using the specific <paramref name="mask"/>
|
|
///</summary>
|
|
///<param name="val">The value to be set</param>
|
|
///<param name="mask">The mask for the operation</param>
|
|
public void SetValue(double val, CvArray<Byte> mask)
|
|
{
|
|
SetValue(new MCvScalar(val, val, val, val), mask);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inplace fills Array with uniformly distributed random numbers
|
|
/// </summary>
|
|
/// <param name="seed">Seed for the random number generator</param>
|
|
/// <param name="floorValue">the inclusive lower boundary of random numbers range</param>
|
|
/// <param name="ceilingValue">the exclusive upper boundary of random numbers range</param>
|
|
public void _RandUniform(UInt64 seed, MCvScalar floorValue, MCvScalar ceilingValue)
|
|
{
|
|
CvInvoke.cvRandArr(ref seed, Ptr, CvEnum.RAND_TYPE.CV_RAND_UNI, floorValue, ceilingValue);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inplace fills Array with uniformly distributed random numbers
|
|
/// </summary>
|
|
/// <param name="floorValue">the inclusive lower boundary of random numbers range</param>
|
|
/// <param name="ceilingValue">the exclusive upper boundary of random numbers range</param>
|
|
public void _RandUniform(MCvScalar floorValue, MCvScalar ceilingValue)
|
|
{
|
|
_RandUniform((UInt64) DateTime.Now.Ticks, floorValue, ceilingValue);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inplace fills Array with normally distributed random numbers
|
|
/// </summary>
|
|
/// <param name="seed">Seed for the random number generator</param>
|
|
/// <param name="mean">the mean value of random numbers</param>
|
|
/// <param name="std"> the standard deviation of random numbers</param>
|
|
public void _RandNormal(UInt64 seed, MCvScalar mean, MCvScalar std)
|
|
{
|
|
CvInvoke.cvRandArr(ref seed, Ptr, CvEnum.RAND_TYPE.CV_RAND_NORMAL, mean, std);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inplace fills Array with normally distributed random numbers
|
|
/// </summary>
|
|
/// <param name="mean">the mean value of random numbers</param>
|
|
/// <param name="std"> the standard deviation of random numbers</param>
|
|
public void _RandNormal(MCvScalar mean, MCvScalar std)
|
|
{
|
|
_RandNormal( (UInt64) DateTime.Now.Ticks, mean, std);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializs scaled identity matrix
|
|
/// </summary>
|
|
/// <param name="value"></param>
|
|
public void _SetIdentity(MCvScalar value)
|
|
{
|
|
CvInvoke.cvSetIdentity(Ptr, value);
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Inplace multiply elements of the Array by <paramref name="scale"/>
|
|
/// </summary>
|
|
/// <param name="scale">The scale to be multiplyed</param>
|
|
public void _Mul(double scale)
|
|
{
|
|
CvInvoke.cvConvertScale(Ptr, Ptr, scale, 0.0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inplace elementwise multiply the current Array with <paramref name="src2"/>
|
|
/// </summary>
|
|
/// <param name="src2">The other array to be elementwise multiplied with</param>
|
|
public void _Mul(CvArray<D> src2)
|
|
{
|
|
CvInvoke.cvMul(Ptr, src2.Ptr, Ptr, 1.0);
|
|
}
|
|
|
|
#region UnmanagedObject
|
|
/// <summary>
|
|
/// Free the _dataHandle if it is set
|
|
/// </summary>
|
|
protected override void FreeUnmanagedObjects()
|
|
{
|
|
if (_dataHandle.IsAllocated)
|
|
{
|
|
_dataHandle.Free();
|
|
};
|
|
}
|
|
#endregion
|
|
|
|
#region Comparison
|
|
///<summary>
|
|
///Inplace compute the elementwise minimum value
|
|
///</summary>
|
|
public void _Min(double val)
|
|
{
|
|
CvInvoke.cvMinS(Ptr, val, Ptr);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inplace elementwise minimize the current Array with <paramref name="src2"/>
|
|
/// </summary>
|
|
/// <param name="src2">The other array to be elementwise minimized with this array</param>
|
|
public void _Min(CvArray<D> src2)
|
|
{
|
|
CvInvoke.cvMin(Ptr, src2.Ptr, Ptr);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inplace compute the elementwise maximum value with <paramref name="val"/>
|
|
/// </summary>
|
|
/// <param name="val">The value to be compare with</param>
|
|
public void _Max(double val)
|
|
{
|
|
CvInvoke.cvMaxS(Ptr, val, Ptr);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inplace elementwise maximize the current Array with <paramref name="src2"/>
|
|
/// </summary>
|
|
/// <param name="src2">The other array to be elementwise maximized with this array</param>
|
|
public void _Max(CvArray<D> src2)
|
|
{
|
|
CvInvoke.cvMax(Ptr, src2.Ptr, Ptr);
|
|
}
|
|
|
|
///<summary>
|
|
///Determine if the size (width and height) of <i>this</i> Array
|
|
///equals the size of <paramref name="src2"/>
|
|
///</summary>
|
|
///<param name="src2"> The other Array to compare size with</param>
|
|
///<returns> True if the two Array has the same size</returns>
|
|
public bool EqualSize<D2>(CvArray<D2> src2)
|
|
{
|
|
return (Width == src2.Width && Height == src2.Height);
|
|
}
|
|
#endregion
|
|
|
|
#region Inplace Logic Operators
|
|
/// <summary>
|
|
/// Inplace And operation with <paramref name="src2"/>
|
|
/// </summary>
|
|
/// <param name="src2">The other array to perform And operation</param>
|
|
public void _And(CvArray<D> src2)
|
|
{
|
|
CvInvoke.cvAnd(Ptr, src2.Ptr, Ptr, IntPtr.Zero);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inplace Or operation with <paramref name="src2"/>
|
|
/// </summary>
|
|
/// <param name="src2">The other array to perform And operation</param>
|
|
public void _Or(CvArray<D> src2)
|
|
{
|
|
CvInvoke.cvOr(Ptr, src2.Ptr, Ptr, IntPtr.Zero);
|
|
}
|
|
|
|
///<summary>
|
|
///Inplace compute the complement for all Array Elements
|
|
///</summary>
|
|
public void _Not()
|
|
{
|
|
CvInvoke.cvNot(Ptr, Ptr);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IXmlSerializable Members
|
|
|
|
/// <summary>
|
|
/// Get the xml schema
|
|
/// </summary>
|
|
/// <returns>the xml schema</returns>
|
|
public System.Xml.Schema.XmlSchema GetSchema()
|
|
{
|
|
throw new System.Exception("The method or operation is not implemented.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Function to call when deserializing this object from XML
|
|
/// </summary>
|
|
/// <param name="reader">The xml reader</param>
|
|
public void ReadXml(System.Xml.XmlReader reader)
|
|
{
|
|
#region read the size of the matrix and assign storage
|
|
reader.MoveToFirstAttribute();
|
|
int rows = reader.ReadContentAsInt();
|
|
reader.MoveToNextAttribute();
|
|
int cols = reader.ReadContentAsInt();
|
|
System.Xml.XmlNodeType type = reader.MoveToContent();
|
|
AllocateData(rows, cols);
|
|
#endregion
|
|
|
|
#region decode the data from Xml and assign the value to the matrix
|
|
int size = System.Runtime.InteropServices.Marshal.SizeOf(typeof(D)) * ManagedArray.Length;
|
|
Byte[] bytes = new Byte[size];
|
|
reader.ReadToFollowing("Bytes");
|
|
reader.ReadElementContentAsBase64(bytes, 0, bytes.Length);
|
|
Bytes = bytes;
|
|
#endregion
|
|
}
|
|
|
|
/// <summary>
|
|
/// Function to call when serializing this object to XML
|
|
/// </summary>
|
|
/// <param name="writer">The xml writer</param>
|
|
public void WriteXml(System.Xml.XmlWriter writer)
|
|
{
|
|
writer.WriteAttributeString("Rows", Rows.ToString());
|
|
writer.WriteAttributeString("Cols", Cols.ToString());
|
|
writer.WriteStartElement("Bytes");
|
|
Byte[] bytes = Bytes;
|
|
writer.WriteBase64(bytes, 0, bytes.Length);
|
|
writer.WriteEndElement();
|
|
}
|
|
#endregion
|
|
|
|
#region ISerializable Members
|
|
/// <summary>
|
|
/// A function used for runtime serilization of the object
|
|
/// </summary>
|
|
/// <param name="info">Serialization info</param>
|
|
/// <param name="context">Streaming context</param>
|
|
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
|
|
{
|
|
info.AddValue("Rows", Rows);
|
|
info.AddValue("Cols", Cols);
|
|
info.AddValue("CompressedBinary", CompressedBytes);
|
|
}
|
|
|
|
/// <summary>
|
|
/// A function used for runtime deserailization of the object
|
|
/// </summary>
|
|
/// <param name="info">Serialization info</param>
|
|
/// <param name="context">Streaming context</param>
|
|
protected void DeserializeObjectData(SerializationInfo info, StreamingContext context)
|
|
{
|
|
int rows = (int)info.GetValue("Rows", typeof(int));
|
|
int cols = (int)info.GetValue("Cols", typeof(int));
|
|
AllocateData(rows, cols);
|
|
|
|
CompressedBytes = (Byte[])info.GetValue("CompressedBinary", typeof(Byte[]));
|
|
}
|
|
#endregion
|
|
}
|
|
}
|