123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700 |
- using AI.Common.Tools;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Runtime.InteropServices;
- using System.Runtime.Serialization;
- using System.Text;
- namespace AI.Reconstruction
- {
- ///重要说明: 项目开发时使用的AI.Common(1.0.1.22)、AI.DiagSystem(1.0.1.31) 均为老版本
- ///现替换为正式发布的Release版AI.Common(1.0.1.31)、AI.DiagSystem(1.0.1.44),
- ///但与之前版本比较,缺少Point3DF、Point2DF等结构体定义,所以在此临时添加接口
- ///等添加接口后,仍需改为release版
- /// <summary>
- /// 2维点坐标
- /// 代替System.Drawing.Point
- /// </summary>
- [DataContract]
- [StructLayout(LayoutKind.Sequential)]
- public struct Point2DF : IEquatable<Point2DF>
- {
- private float _x;
- private float _y;
- /// <summary>
- /// X坐标
- /// </summary>
- [DataMember]
- public float X { get => _x; set => _x = value; }
- /// <summary>
- /// Y坐标
- /// </summary>
- [DataMember]
- public float Y { get => _y; set => _y = value; }
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="x"></param>
- /// <param name="y"></param>
- public Point2DF(float x, float y)
- {
- _x = x;
- _y = y;
- }
- /// <summary>
- /// 空的点
- /// </summary>
- public static readonly Point2DF Empty = new Point2DF(0, 0);
- /// <summary>
- /// 判断是否相等
- /// </summary>
- /// <param name="other"></param>
- /// <returns></returns>
- public bool Equals(Point2DF other)
- {
- return Equals(this, other);
- }
- /// <summary>
- /// 判断是否相等
- /// </summary>
- /// <param name="obj"></param>
- /// <returns></returns>
- public override bool Equals(object obj)
- {
- if (obj == null || !(obj is Point2DF))
- {
- return false;
- }
- Point2DF point = (Point2DF)obj;
- return Equals(this, point);
- }
- /// <summary>
- /// 获得哈希值
- /// </summary>
- /// <returns></returns>
- public override int GetHashCode()
- {
- return string.Format("{0}-{1}", _x, _y).GetHashCode();
- }
- /// <summary>
- /// 转成字符串
- /// </summary>
- /// <returns></returns>
- public override string ToString()
- {
- return SerializeDeserializeHelper.SerializeToJsonString(this);
- }
- /// <summary>
- /// 从字符串中重建
- /// </summary>
- /// <param name="str"></param>
- /// <returns></returns>
- public static Point2DF FromString(string str)
- {
- return SerializeDeserializeHelper.DeserializeJsonResult<Point2DF>(str);
- }
- /// <summary>
- /// 转为bytes
- /// </summary>
- /// <returns></returns>
- public byte[] ToBytes()
- {
- byte[] result;
- using (var stream = new MemoryStream())
- {
- var writer = new AIStreamWriter(stream);
- writer.WriteFloat(_x);
- writer.WriteFloat(_y);
- result = stream.ToArray();
- }
- return result;
- }
- /// <summary>
- /// 从bytes里重建
- /// </summary>
- /// <param name="bytes"></param>
- /// <returns></returns>
- public static Point2DF FromBytes(byte[] bytes)
- {
- Point2DF result;
- using (var stream = new MemoryStream(bytes))
- {
- stream.Position = 0;
- var reader = new AIStreamReader(stream);
- var x = reader.ReadFloat();
- var y = reader.ReadFloat();
- result = new Point2DF(x, y);
- }
- return result;
- }
- public static bool Equals(Point2DF one, Point2DF other)
- {
- return one.X == other.X && one.Y == other.Y;
- }
- public static bool operator ==(Point2DF left, Point2DF right)
- {
- return Equals(left, right);
- }
- public static bool operator !=(Point2DF left, Point2DF right)
- {
- return !Equals(left, right);
- }
- /// <summary>
- /// 计算两点之间的距离
- /// </summary>
- /// <param name="one"></param>
- /// <param name="other"></param>
- /// <returns></returns>
- public static float Distance(Point2DF one, Point2DF other)
- {
- return (float)Math.Sqrt(Math.Pow(one.X - other.X, 2) + Math.Pow(one.Y - other.Y, 2));
- }
- /// <summary>
- /// 求两点之间的中点
- /// </summary>
- /// <param name="one"></param>
- /// <param name="other"></param>
- /// <returns></returns>
- public static Point2DF MidPoint(Point2DF one, Point2DF other)
- {
- return new Point2DF((one.X + other.X) / 2, (one.Y + other.Y) / 2);
- }
- }
- /// <summary>
- /// 3维点坐标
- /// </summary>
- [DataContract]
- [StructLayout(LayoutKind.Sequential)]
- public struct Point3DF : IEquatable<Point3DF>
- {
- private float _x;
- private float _y;
- private float _z;
- /// <summary>
- /// X坐标
- /// </summary>
- [DataMember]
- public float X { get => _x; set => _x = value; }
- /// <summary>
- /// Y坐标
- /// </summary>
- [DataMember]
- public float Y { get => _y; set => _y = value; }
- /// <summary>
- /// Z坐标
- /// </summary>
- [DataMember]
- public float Z { get => _z; set => _z = value; }
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="x"></param>
- /// <param name="y"></param>
- /// <param name="z"></param>
- public Point3DF(float x, float y, float z)
- {
- _x = x;
- _y = y;
- _z = z;
- }
- /// <summary>
- /// 空的点
- /// </summary>
- public static readonly Point3DF Empty = new Point3DF(0, 0, 0);
- /// <summary>
- /// 判断是否相等
- /// </summary>
- /// <param name="other"></param>
- /// <returns></returns>
- public bool Equals(Point3DF other)
- {
- return Equals(this, other);
- }
- /// <summary>
- /// 判断是否相等
- /// </summary>
- /// <param name="obj"></param>
- /// <returns></returns>
- public override bool Equals(object obj)
- {
- if (obj == null || !(obj is Point3DF))
- {
- return false;
- }
- Point3DF point = (Point3DF)obj;
- return Equals(this, point);
- }
- /// <summary>
- /// 获取哈希值
- /// </summary>
- /// <returns></returns>
- public override int GetHashCode()
- {
- return string.Format("{0}-{1}-{2}", _x, _y, _z).GetHashCode();
- }
- /// <summary>
- /// 转成字符串
- /// </summary>
- /// <returns></returns>
- public override string ToString()
- {
- return SerializeDeserializeHelper.SerializeToJsonString(this);
- }
- /// <summary>
- /// 从字符串中生成
- /// </summary>
- /// <param name="str"></param>
- /// <returns></returns>
- public Point3DF FromString(string str)
- {
- return SerializeDeserializeHelper.DeserializeJsonResult<Point3DF>(str);
- }
- /// <summary>
- /// 转为bytes
- /// </summary>
- /// <returns></returns>
- public byte[] ToBytes()
- {
- byte[] result;
- using (var stream = new MemoryStream())
- {
- var writer = new AIStreamWriter(stream);
- writer.WriteFloat(_x);
- writer.WriteFloat(_y);
- writer.WriteFloat(_z);
- result = stream.ToArray();
- }
- return result;
- }
- /// <summary>
- /// 从bytes里重建
- /// </summary>
- /// <param name="bytes"></param>
- /// <returns></returns>
- public static Point3DF FromBytes(byte[] bytes)
- {
- Point3DF result;
- using (var stream = new MemoryStream(bytes))
- {
- stream.Position = 0;
- var reader = new AIStreamReader(stream);
- var x = reader.ReadFloat();
- var y = reader.ReadFloat();
- var z = reader.ReadFloat();
- result = new Point3DF(x, y, z);
- }
- return result;
- }
- public static bool Equals(Point3DF one, Point3DF other)
- {
- return one.X == other.X && one.Y == other.Y && one.Z == other.Z;
- }
- public static bool operator ==(Point3DF left, Point3DF right)
- {
- return Equals(left, right);
- }
- public static bool operator !=(Point3DF left, Point3DF right)
- {
- return !Equals(left, right);
- }
- public static float Distance(Point3DF one, Point3DF other)
- {
- return (float)Math.Sqrt(Math.Pow(one.X - other.X, 2) + Math.Pow(one.Y - other.Y, 2) + Math.Pow(one.Z - other.Z, 2));
- }
- }
- /// <summary>
- /// 矩形框
- /// 代替System.Drawing.Rectangle
- /// </summary>
- [DataContract]
- public struct RectF : IEquatable<RectF>
- {
- private float _left;
- private float _top;
- private float _right;
- private float _bottom;
- private float _width;
- private float _height;
- /// <summary>
- /// 面积
- /// </summary>
- public float Area
- {
- get => _width * _height;
- }
- /// <summary>
- /// 右
- /// </summary>
- public float Right { get => _right; }
- /// <summary>
- /// 下
- /// </summary>
- public float Bottom { get => _bottom; }
- /// <summary>
- /// 左
- /// </summary>
- [DataMember]
- public float Left
- {
- get => _left;
- set { _left = value; _right = _left + _width; }
- }
- /// <summary>
- /// 上
- /// </summary>
- [DataMember]
- public float Top
- {
- get => _top;
- set { _top = value; _bottom = _top + _height; }
- }
- /// <summary>
- /// 宽度
- /// </summary>
- [DataMember]
- public float Width
- {
- get => _width;
- set
- {
- if (value < 0)
- {
- throw new ArgumentException("width", "Width should be greater than 0.");
- };
- _width = value;
- _right = _left + _width;
- }
- }
- /// <summary>
- /// 高度
- /// </summary>
- [DataMember]
- public float Height
- {
- get => _height;
- set
- {
- if (value < 0)
- {
- throw new ArgumentException("height", "Height should be greater than 0");
- };
- _height = value;
- _bottom = _top + _height;
- }
- }
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="left"></param>
- /// <param name="top"></param>
- /// <param name="width"></param>
- /// <param name="height"></param>
- public RectF(float left, float top, float width, float height)
- {
- if (width < 0)
- {
- throw new ArgumentException("width", "Width should be greater than 0.");
- }
- if (height < 0)
- {
- throw new ArgumentException("height", "Height should be greater than 0");
- }
- _left = left;
- _top = top;
- _width = width;
- _height = height;
- _right = left + width;
- _bottom = top + height;
- }
- /// <summary>
- /// 判断是否为未被初始化的Rect结构
- /// </summary>
- /// <returns></returns>
- public bool IsEmpty()
- {
- return Equals(this, Empty);
- }
- /// <summary>
- /// 空矩形框
- /// </summary>
- public static readonly RectF Empty = new RectF(0, 0, 0, 0);
- /// <summary>
- /// 判断是否相等
- /// </summary>
- /// <param name="rect"></param>
- /// <returns></returns>
- public bool Equals(RectF rect)
- {
- return Equals(this, rect);
- }
- /// <summary>
- /// 判断是否相等
- /// </summary>
- /// <param name="obj"></param>
- /// <returns></returns>
- public override bool Equals(object obj)
- {
- if (obj == null || !(obj is RectF))
- {
- return false;
- }
- RectF point = (RectF)obj;
- return Equals(this, point);
- }
- /// <summary>
- /// 获得哈希值
- /// </summary>
- /// <returns></returns>
- public override int GetHashCode()
- {
- return string.Format("{0}-{1}-{2}-{3}", _left, _right, _width, _height).GetHashCode();
- }
- /// <summary>
- /// 转成字符串
- /// </summary>
- /// <returns></returns>
- public override string ToString()
- {
- return SerializeDeserializeHelper.SerializeToJsonString(this);
- }
- /// <summary>
- /// 从字符串中生成
- /// </summary>
- /// <param name="str"></param>
- /// <returns></returns>
- public static RectF FromString(string str)
- {
- return SerializeDeserializeHelper.DeserializeJsonResult<RectF>(str);
- }
- /// <summary>
- /// 转为bytes
- /// </summary>
- /// <returns></returns>
- public byte[] ToBytes()
- {
- byte[] result;
- using (var stream = new MemoryStream())
- {
- var writer = new AIStreamWriter(stream);
- writer.WriteFloat(_left);
- writer.WriteFloat(_top);
- writer.WriteFloat(_width);
- writer.WriteFloat(_height);
- result = stream.ToArray();
- }
- return result;
- }
- /// <summary>
- /// 从bytes里重建
- /// </summary>
- /// <param name="bytes"></param>
- /// <returns></returns>
- public static RectF FromBytes(byte[] bytes)
- {
- RectF result;
- using (var stream = new MemoryStream(bytes))
- {
- stream.Position = 0;
- var reader = new AIStreamReader(stream);
- var left = reader.ReadFloat();
- var top = reader.ReadFloat();
- var width = reader.ReadFloat();
- var height = reader.ReadFloat();
- result = new RectF(left, top, width, height);
- }
- return result;
- }
- public static bool Equals(RectF one, RectF other)
- {
- return one.Left == other.Left && one.Top == other.Top && one.Width == other.Width && one.Height == other.Height;
- }
- public static bool operator ==(RectF left, RectF right)
- {
- return Equals(left, right);
- }
- public static bool operator !=(RectF left, RectF right)
- {
- return !Equals(left, right);
- }
- /// <summary>
- /// 在原来的rect的基础上,上下左右一起偏移指定像素数
- /// 当offset为正时,为一起向正方向偏移(向右或向下)
- /// 当offset为负时,为一起向负方向偏移(向左或向上)
- /// </summary>
- /// <param name="offsetX"></param>
- /// <param name="offsetY"></param>
- /// <returns></returns>
- public static RectF Offset(RectF rect, float offsetX, float offsetY)
- {
- return new RectF(rect.Left + offsetX, rect.Top + offsetY, rect.Width, rect.Height);
- }
- /// <summary>
- /// 以原来的rect中心为中心,上下左右一起向外扩张或内缩指定像素数
- /// 当offset为正时,为外扩,当offset为负时,为内缩
- /// </summary>
- /// <param name="rect"></param>
- /// <param name="offset"></param>
- /// <returns></returns>
- public static RectF AdjustRect(RectF rect, float offsetX, float offsetY)
- {
- // 往内缩时,不能缩成负的了
- if (offsetX < -rect.Width / 2)
- {
- offsetX = -rect.Width / 2;
- }
- if (offsetY < -rect.Height / 2)
- {
- offsetY = -rect.Height / 2;
- }
- var correctedLeft = rect.Left - offsetX;
- var correctedRight = rect.Right + offsetX;
- var correctedTop = rect.Top - offsetY;
- var correctedBottom = rect.Bottom + offsetY;
- var correctedWidth = correctedRight - correctedLeft;
- var correctedHeight = correctedBottom - correctedTop;
- return new RectF(correctedLeft, correctedTop, correctedWidth, correctedHeight);
- }
- /// <summary>
- /// 以clipBound为边界,截断当前rect
- /// 即,左上右下角,改为不超过clipBound所限定的范围
- /// </summary>
- /// <param name="rect"></param>
- /// <param name="clipBound"></param>
- /// <returns></returns>
- public static RectF Clip(RectF rect, RectF clipBound)
- {
- var left = Math.Min(Math.Max(rect.Left, clipBound.Left), clipBound.Right);
- var right = Math.Min(Math.Max(rect.Right, clipBound.Left), clipBound.Right);
- var top = Math.Min(Math.Max(rect.Top, clipBound.Top), clipBound.Bottom);
- var bottom = Math.Min(Math.Max(rect.Bottom, clipBound.Top), clipBound.Bottom);
- var width = right - left;
- var height = bottom - top;
- return new RectF(left, top, width, height);
- }
- /// <summary>
- /// 计算两个rect的相交部分
- /// </summary>
- /// <param name="a"></param>
- /// <param name="b"></param>
- /// <returns></returns>
- public static RectF Intersection(RectF a, RectF b)
- {
- var left = Math.Max(a.Left, b.Left);
- var top = Math.Max(a.Top, b.Top);
- var right = Math.Min(a.Right, b.Right);
- var bottom = Math.Min(a.Bottom, b.Bottom);
- if (left > right || top > bottom)
- {
- return RectF.Empty;
- }
- var width = right - left;
- var height = bottom - top;
- return new RectF(left, top, width, height);
- }
- /// <summary>
- /// 计算两个rect的并集
- /// </summary>
- /// <param name="a"></param>
- /// <param name="b"></param>
- /// <returns></returns>
- public static RectF Union(RectF a, RectF b)
- {
- var left = Math.Min(a.Left, b.Left);
- var top = Math.Min(a.Top, b.Top);
- var right = Math.Max(a.Right, b.Right);
- var bottom = Math.Max(a.Bottom, b.Bottom);
- var width = right - left;
- var height = bottom - top;
- return new RectF(left, top, width, height);
- }
- /// <summary>
- /// 计算两个rect的IOU
- /// 注意:计算IOU时,分子是a和b的交集的面积(= Intersect(a,b).Area)
- /// 分母是a和b的并集的面积(≠Union(a,b).Area,而应该是a.Area+b.Area-Intersection(a,b).Area)
- /// </summary>
- /// <param name="a"></param>
- /// <param name="b"></param>
- /// <returns></returns>
- public static float CalcIOU(RectF a, RectF b)
- {
- var intersection = Intersection(a, b);
- var areaInter = intersection.Area;
- var areaUnion = a.Area + b.Area - areaInter;
- if (areaUnion <= 0)
- {
- return 0;
- }
- else
- {
- return areaInter * 1.0f / areaUnion;
- }
- }
- }
- }
|