は、.NETが自動的にパブリックプロパティの反射を介したからとXMLへの型のインスタンスをシリアル化できるクラスXmlSerializer
が含まれています。また、IXmlSerializable
インターフェイスをサポートしているため、型のデフォルト動作をオーバーライドし、XMLへのシリアル化の仕方を完全に制御できます。
このように、IntrinsicCameraParameters.IntrinsicMatrix
およびIntrinsicCameraParameters.DistortionCoeffs
は両方ともタイプMatrix<double>
であり、基底クラスCvArray<TDepth>
はこのインターフェイスを実装しています。したがって、このタイプのオブジェクトは、次の拡張メソッドを使用してXmlSerializer
を使用してXMLにシリアライズする必要があります:
public static partial class XmlSerializationExtensions
{
public static void SerializeToXmlFile<T>(this T obj, string fileName)
{
var settings = new XmlWriterSettings { Indent = true };
using (var writer = XmlWriter.Create(fileName, settings))
{
new XmlSerializer(typeof(T)).Serialize(writer, obj);
}
}
public static T DeserializeFromXmlFile<T>(string fileName)
{
using (var reader = XmlReader.Create(fileName))
{
return (T)new XmlSerializer(typeof(T)).Deserialize(reader);
}
}
}
次に、あなただけの行うことができます。
var fileName = "C:\\Video\\Cal\\CameraMatrix.xml";
ICP.IntrinsicMatrix.SerializeToXmlFile(fileName);
以降、行う、戻ってそれを読むために:
var newIntrinsicMatrix = XmlSerializationExtensions.DeserializeFromXmlFile<Matrix<double>>(fileName);
確認のため、XMLとの間で行列をシリアル化する別の例については、the documentationを参照してください。
論理的には、また、同じジェネリック拡張メソッドを使用して単一のXMLファイルにIntrinsicCameraParameters
全体を保存し、復元することが可能なはずである。
ICP.SerializeToXmlFile(fileName);
は残念ながら、問題があります。 CvArray<TDepth>
のReadXml()
の実装が壊れています。 Proper way to implement IXmlSerializable?
からReadXmlの説明の方法は がWriteXmlメソッドによって書かれたとの情報を使用して あなたのオブジェクトを再構築しなければなりません。
このメソッドを呼び出すと、リーダー は、タイプ の情報をラップする 要素の先頭に配置されます。すなわち、 開始タグの直前で、 のシリアル化されたオブジェクトの開始を示します。この メソッドが返された場合、その要素のすべてを含む の最初から最後まで、要素全体を で読み取る必要があります。 WriteXmlメソッド とは異なり、フレームワーク はラッパー要素 を自動的に処理しません。あなたの実装は でなければなりません。これらの 位置決めルールを守らないと、 に予期しないランタイム例外 が生成されるか、データが破損する可能性があります。
そしてCvArray<TDepth>
ためsource codeのクイックチェックは、ラッパー要素の終わりはを読んでいないであることを示しています。これにより、XML内の最初のCvArray<>
に続くデータはすべてデシリアライズされなくなります。
したがって、Matrix<T>
を大きなXMLファイルに埋め込みたい場合は、次のように、シリアライズサロゲートタイプ(またはデータ転送オブジェクトタイプ)を導入する必要があります。 (Emgu.CV.SerializationSurrogates
名前空間の導入に注意してください):
namespace Emgu.CV.SerializationSurrogates
{
using Emgu.CV;
public class Matix<TDepth> where TDepth : new()
{
[XmlAttribute]
public int Rows { get; set; }
[XmlAttribute]
public int Cols { get; set; }
[XmlAttribute]
public int NumberOfChannels { get; set; }
[XmlAttribute]
public int CompressionRatio { get; set; }
public byte[] Bytes { get; set; }
public static implicit operator Emgu.CV.SerializationSurrogates.Matix<TDepth>(Emgu.CV.Matrix<TDepth> matrix)
{
if (matrix == null)
return null;
return new Matix<TDepth>
{
Rows = matrix.Rows,
Cols = matrix.Cols,
NumberOfChannels = matrix.NumberOfChannels,
CompressionRatio = matrix.SerializationCompressionRatio,
Bytes = matrix.Bytes,
};
}
public static implicit operator Emgu.CV.Matrix<TDepth>(Matix<TDepth> surrogate)
{
if (surrogate == null)
return null;
var matrix = new Emgu.CV.Matrix<TDepth>(surrogate.Rows, surrogate.Cols, surrogate.NumberOfChannels);
matrix.SerializationCompressionRatio = surrogate.CompressionRatio;
matrix.Bytes = surrogate.Bytes;
return matrix;
}
}
public class IntrinsicCameraParameters
{
[XmlElement("IntrinsicMatrix", Type = typeof(Emgu.CV.SerializationSurrogates.Matix<double>))]
public Emgu.CV.Matrix<double> IntrinsicMatrix { get; set; }
[XmlElement("DistortionCoeffs", Type = typeof(Emgu.CV.SerializationSurrogates.Matix<double>))]
public Emgu.CV.Matrix<double> DistortionCoeffs { get; set; }
public static implicit operator Emgu.CV.SerializationSurrogates.IntrinsicCameraParameters(Emgu.CV.IntrinsicCameraParameters icp)
{
if (icp == null)
return null;
return new IntrinsicCameraParameters
{
DistortionCoeffs = icp.DistortionCoeffs,
IntrinsicMatrix = icp.IntrinsicMatrix,
};
}
public static implicit operator Emgu.CV.IntrinsicCameraParameters(Emgu.CV.SerializationSurrogates.IntrinsicCameraParameters surrogate)
{
if (surrogate == null)
return null;
return new Emgu.CV.IntrinsicCameraParameters
{
DistortionCoeffs = surrogate.DistortionCoeffs,
IntrinsicMatrix = surrogate.IntrinsicMatrix,
};
}
}
}
今、あなたは、次の拡張メソッドを使用してIntrinsicCameraParameters
を保存し、取得することができます。
public static class IntrinsicCameraParametersExtensions
{
public static void SerializeIntrinsicCameraParametersExtensionsToXmlFile(this IntrinsicCameraParameters icp, string fileName)
{
var surrogate = (Emgu.CV.SerializationSurrogates.IntrinsicCameraParameters)icp;
surrogate.SerializeToXmlFile(fileName);
}
public static IntrinsicCameraParameters DeserializeIntrinsicCameraParametersFromXmlFile(string fileName)
{
var surrogate = XmlSerializationExtensions.DeserializeFromXmlFile<Emgu.CV.SerializationSurrogates.IntrinsicCameraParameters>(fileName);
return surrogate;
}
}
すべてはIntrinsicCameraParameters
は、現在のリリースではmarked as obsoleteで、言われています:
[SerializableAttribute]
[ObsoleteAttribute("This class will be removed in the next release, please use separate camera matrix and distortion coefficient with the CvInvoke function instead.")]
public class IntrinsicCameraParameters : IEquatable<IntrinsicCameraParameters>
このデザインを考え直すとよいでしょう。なお
、CvArray<TDepth>.ReadXml()
の非破損バージョンのようになり:
public virtual void ReadXml(System.Xml.XmlReader reader)
{
#region read properties of the matrix and assign storage
int rows = Int32.Parse(reader.GetAttribute("Rows")); // Should really be using XmlConvert for this
int cols = Int32.Parse(reader.GetAttribute("Cols"));
int numberOfChannels = Int32.Parse(reader.GetAttribute("NumberOfChannels"));
SerializationCompressionRatio = Int32.Parse(reader.GetAttribute("CompressionRatio"));
AllocateData(rows, cols, numberOfChannels);
#endregion
#region decode the data from Xml and assign the value to the matrix
if (!reader.IsEmptyElement)
{
using (var subReader = reader.ReadSubtree())
{
// Using ReadSubtree guarantees we don't read past the end of the element in case the <Bytes> element
// is missing or extra unexpected elements are included.
if (subReader.ReadToFollowing("Bytes"))
{
int size = _sizeOfElement * ManagedArray.Length;
if (SerializationCompressionRatio == 0)
{
Byte[] bytes = new Byte[size];
subReader.ReadElementContentAsBase64(bytes, 0, bytes.Length);
Bytes = bytes;
}
else
{
int extraHeaderBytes = 20000;
Byte[] bytes = new Byte[size + extraHeaderBytes];
int countOfBytesRead = subReader.ReadElementContentAsBase64(bytes, 0, bytes.Length);
Array.Resize<Byte>(ref bytes, countOfBytesRead);
Bytes = bytes;
}
}
}
}
// Consume the end of the wrapper element also.
reader.Read();
#endregion
}
[ 'IntrinsicCameraParameters.DistortionCoeffs'(http://www.emgu.com/wiki/files/2.0.0.0/html /ecc3c8f8-9f92-10b1-96a2-b0b1ca6501e9.htm)は実際に['IXmlSerializable'](https://msdn2.microsoft.com/en-us/library/fhd7bk0a)を実装しているので、単純に[' XmlSerializer' ](IntrinsicCameraParameters')(https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer(v = vs.110).aspx)の[http://www.emgu .com/wiki/files/2.0.0.0/html/1ad4e83e-3c4b-d128-cd44-c9e8a9da007f.htm)? – dbc
私はそれを試していません。私はXMLにあまりよく似ていません。 XmlSerializerの使用方法を詳しく説明できますか? –