using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 指向手势识别
{
public class CodeBook
{
#region cede_Element
private static int CHANNELS = 3;
private class CodeElement
{
public int[] learnHigh = new int[CHANNELS];
public int[] learnLow = new int[CHANNELS];
public int[] max = new int[CHANNELS];
public int[] min = new int[CHANNELS];
public int tLastUpdate = 0;
public int stale = 0;
public CodeElement()
{
}
public CodeElement(CodeElement element)
{
this.Copy(element);
}
public void Copy(CodeElement element)
{
for (int i = 0; i < CHANNELS; i++)
{
learnHigh[i] = element.learnHigh[i];
learnLow[i] = element.learnLow[i];
max[i] = element.max[i];
min[i] = element.min[i];
}
tLastUpdate = element.tLastUpdate;
stale = element.stale;
}
}
#endregion
#region 私有字段
/// <summary>
/// 码元记录表
/// </summary>
private List<CodeElement> cb;
/// <summary>
/// 码元总数目
/// </summary>
private int numEntries;
/// <summary>
/// 当前时间
/// </summary>
private static int t;
public int NumEntries
{
get { return numEntries; }
set { numEntries = value; }
}
public static int T
{
get { return t; }
set { t = value; }
}
#endregion
public CodeBook()
{
CodeBook.t = 0;
this.NumEntries = 0;
this.cb = new List<CodeElement>();
}
public void Initial()
{
this.cb.Clear();
this.NumEntries = 0;
CodeBook.t = 0;
}
public int UpdateCodeBook(int[] pixel, int[] cbBound, int numChannels)
{
if (this.NumEntries == 0)
CodeBook.t = 0;
CodeBook.t++;
#region 记录新像素点高低范围
int[] high = new int[3];
int[] low = new int[3];
for (int i = 0; i < numChannels; i++)
{
high[i] = pixel[i] + cbBound[i];
if (high[i] > 255)
high[i] = 255;
low[i] = pixel[i] - cbBound[i];
if (low[i] < 0)
low[i] = 0;
}
#endregion
#region 寻找匹配码元并更新数值
int matchChannel, index;
for (index = 0; index < this.NumEntries; index++)
{
matchChannel = 0;
for (int i = 0; i < numChannels; i++)
{
if (this.cb[index].learnLow[i] <= pixel[i] &&
pixel[i] <= this.cb[index].learnHigh[i])
{
matchChannel++;
}
}
//找到匹配的码元,更新最大值最小值区域
if (matchChannel == numChannels)
{
CodeElement element = this.cb[index];
element.tLastUpdate = CodeBook.t;
for (int i = 0; i < numChannels; i++)
{
if (element.max[i] < pixel[i])
{
element.max[i] = pixel[i];
}
else if (element.min[i] > pixel[i])
{
element.min[i] = pixel[i];
}
}
break;
}
}
#endregion
#region 更新每个码元点的最后修改时间
for (int i = 0; i < this.NumEntries; i++)
{
int negRun = CodeBook.t - this.cb[i].tLastUpdate;
if (this.cb[i].stale < negRun)
{
CodeElement element = this.cb[i];
element.stale = negRun;
}
}
#endregion
#region 没有找到当前匹配的码元,添加一个新的码元
if (index == this.NumEntries)
{
CodeElement element = new CodeElement();
for (int i = 0; i < numChannels; i++)
{
element.learnHigh[i] = high[i];
element.learnLow[i] = low[i];
element.max[i] = pixel[i];
element.min[i] = pixel[i];
}
element.tLastUpdate = CodeBook.t;
element.stale = 0;
this.cb.Add(element);
this.NumEntries++;
}
#endregion
#region 如果发现像素在box阈值之外,但仍然在其高低范围内,缓慢调整learnHigh和learnLow的学习界限
for (int i = 0; i < numChannels; i++)
{
CodeElement element = this.cb[index];
if (element.learnHigh[i] < high[i])
{
element.learnHigh[i]++;
}
if (element.learnLow[i] > low[i])
{
element.learnLow[i]--;
}
}
#endregion
return index;
}
public int ClearStaleEntries()
{
int staleThresh = CodeBook.t >> 1;
for (int i = 0; i < this.cb.Count; i++)
{
if (this.cb[i].stale > staleThresh)
{
this.cb.RemoveAt(i);
}
}
int result = this.NumEntries;
this.NumEntries = this.cb.Count;
result -= this.NumEntries;
return result;
}
public bool BackGroundDiff(int[] pixel, int[] minMod, int[] maxMod, int numChannels)
{
bool result = true;
foreach (CodeElement element in this.cb)
{
int matchChannel = 0;
for (int i = 0; i < numChannels; i++)
{
if (element.min[i] - minMod[i] <= pixel[i] &&
pixel[i] <= element.max[i] + maxMod[i])
{
matchChannel++;
}
else
{
break;
}
}
if (matchChannel == numChannels)
{
//不是前景目标
result = false;
break;
}
}
return result;
}
}
}
OpenCV c#版 CodeBook
最新推荐文章于 2024-07-24 17:16:18 发布