using System;
using System.Linq;
using System.Drawing;
using System.Collections.Generic;
namespace shjxCamera
{
///
/// 将队列中的前后两幅图像像素点进行相减,最大的10%和最小的10%视为噪点,其余值进行平均值计算
///
public class NoiseDataFilter
{
public NoiseDataFilter()
{
Count = 2;
lstImages = new List>();
NoiseCnt = 10;
}
#region fields
///
/// 队列中保留图像数,默认为2
///
public int Count { get; set; }
///
/// 过滤噪点数,单向
///
public int NoiseCnt { get; set; }
///
/// 用于比较的图像像素队列
///
protected List> lstImages { get; set; }
#endregion
#region methods
///
/// 加入一幅图像到队列,不做处理
///
///
public void AddImage(List newImage)
{
lstImages.Add(newImage);
while (lstImages.Count > this.Count)
{
lstImages.RemoveAt(0);
}
}
///
/// 对图像进行噪点过滤,然后计算rgb总值
///
///
///
///
///
public void CalcImage(List newImage, ref int sumR, ref int sumG, ref int sumB)
{
AddImage(newImage);
CalcAvg(ref sumR, ref sumG, ref sumB);
}
///
/// 清除队列数据
///
public void Clear()
{
if (lstImages != null)
{
lstImages.Clear();
}
}
#endregion
#region protected methods
///
/// 计算后图减前图的过滤图的总值
///
///
///
///
protected void calcAvg1(ref int sumR, ref int sumG, ref int sumB)
{
if (lstImages == null)
{
throw new Exception("队列没有数据");
}
if (lstImages.Count >= 2)
{
// 计算滤噪后的总值
List img1 = lstImages[lstImages.Count - 2]; // 上一幅
List img2 = lstImages[lstImages.Count - 1]; // 当前幅
#region 计算后图减前图的差值
string strr = "R:\r\n", strg = "G:\r\n", strb = "B:\r\n";
List imgsub = new List();
IntRGB val;
for (int i = 0; i < img2.Count; i++)
{
val = new IntRGB(
img2[i].R - img1[i].R,
img2[i].G - img1[i].G,
img2[i].B - img1[i].B);
imgsub.Add(val);
/*if (this.IsLog)
{
strr = string.Format("{0}{1},", strr, val.R.ToString().PadLeft(3, ' '));
strg = string.Format("{0}{1},", strg, val.G.ToString().PadLeft(3, ' '));
strb = string.Format("{0}{1},", strb, val.B.ToString().PadLeft(3, ' '));
if (i % this.LogWidth == 11)
{
strr = string.Format("{0}\r\n", strr);
strg = string.Format("{0}\r\n", strg);
strb = string.Format("{0}\r\n", strb);
}
}*/
}
/*if (this.IsLog)
{
//strr = string.Format("{0}\r\n", strr);
//strg = string.Format("{0}\r\n", strg);
//strb = string.Format("{0}\r\n", strb);
swLog.WriteLine("相减数据:");
swLog.WriteLine(strr);
swLog.WriteLine(strg);
swLog.WriteLine(strb);
swLog.WriteLine();
}*/
#endregion
#region 统计差值,以G值为准
Dictionary dicimg = new Dictionary();
foreach (IntRGB subval in imgsub)
{
if (dicimg.Keys.Contains(subval.G))
{
dicimg[subval.G] += 1;
}
else
{
dicimg.Add(subval.G, 1);
}
}
List> lstsub = dicimg.OrderByDescending(c => c.Key).ToList();
#endregion
#region 计算阈值参数
NoiseParam npm = new NoiseParam(NoiseCnt);
npm.Threhold = img2.Count / 10;
int tmp = 0; // 计算上阈值
for (int i = 0; i < lstsub.Count; i++)
{
tmp += lstsub[i].Value;
if (tmp < npm.Threhold)
{
//if (this.IsLog) { swLog.WriteLine("滤除噪点+:" + lstsub[i].Key.ToString() + "[" + lstsub[i].Value.ToString() + "点]"); }
continue; // 未够数,继续下一组
}
else if (tmp == npm.Threhold)
{
// 正好够数,记录阈值,退出循环
npm.Upper = lstsub[i].Key;
npm.UpCnt = lstsub[i].Value; // 该阈值需消除的点数
//if (this.IsLog) { swLog.WriteLine("滤除噪点+:" + lstsub[i].Key.ToString() + "[" + npm.UpCnt.ToString() + "点]"); }
break;
}
else
{
// 过数,计算阈值,退出循环
npm.Upper = lstsub[i].Key;
npm.UpCnt = lstsub[i].Value - (tmp - npm.Threhold);
//if (this.IsLog) { swLog.WriteLine("滤除噪点+:" + lstsub[i].Key.ToString() + "[" + npm.UpCnt.ToString() + "点]"); }
break;
}
}
tmp = 0; // 计算下阈值
for (int i = lstsub.Count - 1; i >= 0; i--)
{
tmp += lstsub[i].Value;
if (tmp < npm.Threhold)
{
//if (this.IsLog) { swLog.WriteLine("滤除噪点-:" + lstsub[i].Key.ToString() + "[" + lstsub[i].Value.ToString() + "点]"); }
continue; // 未够数,继续下一组
}
else if (tmp == npm.Threhold)
{
// 正好够数,记录阈值,退出循环
npm.Lower = lstsub[i].Key;
npm.LowCnt = lstsub[i].Value; // 该阈值需消除的点数
//if (this.IsLog) { swLog.WriteLine("滤除噪点-:" + lstsub[i].Key.ToString() + "[" + npm.LowCnt.ToString() + "点]"); }
break;
}
else
{
// 过数,计算阈值,退出循环
npm.Lower = lstsub[i].Key;
npm.LowCnt = lstsub[i].Value - (tmp - npm.Threhold);
//if (this.IsLog) { swLog.WriteLine("滤除噪点-:" + lstsub[i].Key.ToString() + "[" + npm.LowCnt.ToString() + "点]"); }
break;
}
}
#endregion
#region 滤除噪点后,计算总值
for (int i = 0; i < img2.Count; i++)
{
if (imgsub[i].G > npm.Upper || imgsub[i].G < npm.Lower)
{
continue; // 噪点,滤去
}
else if (imgsub[i].G == npm.Upper && npm.UpCnt > 0)
{
// 部分噪点,滤去部分
npm.UpCnt--;
continue;
}
else if (imgsub[i].G == npm.Lower && npm.LowCnt > 0)
{
// 部分噪点,滤去部分
npm.LowCnt--;
continue;
}
else
{
// 非噪点,计算总值
sumR += img2[i].R;
sumG += img2[i].G;
sumB += img2[i].B;
}
}
/*if (this.IsLog)
{
tmp = img2.Count - npm.Threhold * 2;
strr = string.Format("总值:(R, G, B)({0}, {1}, {2}) 数据个数:{3}", sumR, sumG, sumB, tmp);
swLog.WriteLine(strr);
strr = string.Format("均值:(R, G, B)({0}, {1}, {2})\r\n", (sumR * 1.0 / tmp).ToString("F2"), (sumG * 1.0 / tmp).ToString("F2"), (sumB * 1.0 / tmp).ToString("F2"));
swLog.WriteLine(strr);
swLog.WriteLine();
}*/
#endregion
}
else
{
#region 仅一图,无法去噪,直接计算总值
List img2 = lstImages[lstImages.Count - 1]; // 上一幅
for (int i = 0; i < img2.Count; i++)
{
sumR += img2[i].R;
sumG += img2[i].G;
sumB += img2[i].B;
}
/*if (this.IsLog)
{
int tmp = img2.Count;
string strr = string.Format("总值:(R, G, B)({0}, {1}, {2}) 数据个数:{3}", sumR, sumG, sumB, tmp);
swLog.WriteLine(strr);
strr = string.Format("均值:(R, G, B)({0}, {1}, {2})\r\n", (sumR * 1.0 / tmp).ToString("F2"), (sumG * 1.0 / tmp).ToString("F2"), (sumB * 1.0 / tmp).ToString("F2"));
swLog.WriteLine(strr);
swLog.WriteLine();
}*/
#endregion
}
}
///
/// 计算后图减前图的过滤图的总值
///
///
///
///
protected void CalcAvg(ref int sumR, ref int sumG, ref int sumB)
{
if (lstImages == null)
{
throw new Exception("队列没有数据");
}
if (lstImages.Count >= 2)
{
// 计算滤噪后的总值
List img1 = lstImages[lstImages.Count - 2]; // 上一幅
List img2 = lstImages[lstImages.Count - 1]; // 当前幅
#region 计算后图减前图的差值
string strr = "R:\r\n", strg = "G:\r\n", strb = "B:\r\n";
List imgsub = new List();
IntRGB val;
for (int i = 0; i < img2.Count; i++)
{
val = new IntRGB(
img2[i].R - img1[i].R,
img2[i].G - img1[i].G,
img2[i].B - img1[i].B);
imgsub.Add(val);
/*if (this.IsLog)
{
strr = string.Format("{0}{1},", strr, val.R.ToString().PadLeft(3, ' '));
strg = string.Format("{0}{1},", strg, val.G.ToString().PadLeft(3, ' '));
strb = string.Format("{0}{1},", strb, val.B.ToString().PadLeft(3, ' '));
if (i % this.LogWidth == LogWidth - 1)
{
strr = string.Format("{0}\r\n", strr);
strg = string.Format("{0}\r\n", strg);
strb = string.Format("{0}\r\n", strb);
}
}*/
}
/*if (this.IsLog)
{
//strr = string.Format("{0}\r\n", strr);
//strg = string.Format("{0}\r\n", strg);
//strb = string.Format("{0}\r\n", strb);
swLog.WriteLine("相减数据:");
swLog.WriteLine(strr);
swLog.WriteLine(strg);
swLog.WriteLine(strb);
swLog.WriteLine();
}*/
#endregion
#region 统计差值,以G值为准
Dictionary dicimg = new Dictionary();
foreach (IntRGB subval in imgsub)
{
if (dicimg.Keys.Contains(subval.G))
{
dicimg[subval.G] += 1;
}
else
{
dicimg.Add(subval.G, 1);
}
}
List> lstsub = dicimg.OrderByDescending(c => c.Key).ToList();
#endregion
#region 计算阈值参数
NoiseParam npm = new NoiseParam(NoiseCnt);
npm.Threhold = img2.Count / 10;
int tmp = 0; // 计算上阈值
for (int i = 0; i < lstsub.Count; i++)
{
tmp += lstsub[i].Value;
if (tmp < npm.Threhold)
{
//if (this.IsLog) { swLog.WriteLine("滤除噪点+:" + lstsub[i].Key.ToString() + "[" + lstsub[i].Value.ToString() + "点]"); }
continue; // 未够数,继续下一组
}
else if (tmp == npm.Threhold)
{
// 正好够数,记录阈值,退出循环
npm.Upper = lstsub[i].Key;
npm.UpCnt = lstsub[i].Value; // 该阈值需消除的点数
//if (this.IsLog) { swLog.WriteLine("滤除噪点+:" + lstsub[i].Key.ToString() + "[" + npm.UpCnt.ToString() + "点]"); }
break;
}
else
{
// 过数,计算阈值,退出循环
npm.Upper = lstsub[i].Key;
npm.UpCnt = lstsub[i].Value - (tmp - npm.Threhold);
//if (this.IsLog) { swLog.WriteLine("滤除噪点+:" + lstsub[i].Key.ToString() + "[" + npm.UpCnt.ToString() + "点]"); }
break;
}
}
tmp = 0; // 计算下阈值
for (int i = lstsub.Count - 1; i >= 0; i--)
{
tmp += lstsub[i].Value;
if (tmp < npm.Threhold)
{
//if (this.IsLog) { swLog.WriteLine("滤除噪点-:" + lstsub[i].Key.ToString() + "[" + lstsub[i].Value.ToString() + "点]"); }
continue; // 未够数,继续下一组
}
else if (tmp == npm.Threhold)
{
// 正好够数,记录阈值,退出循环
npm.Lower = lstsub[i].Key;
npm.LowCnt = lstsub[i].Value; // 该阈值需消除的点数
//if (this.IsLog) { swLog.WriteLine("滤除噪点-:" + lstsub[i].Key.ToString() + "[" + npm.LowCnt.ToString() + "点]"); }
break;
}
else
{
// 过数,计算阈值,退出循环
npm.Lower = lstsub[i].Key;
npm.LowCnt = lstsub[i].Value - (tmp - npm.Threhold);
//if (this.IsLog) { swLog.WriteLine("滤除噪点-:" + lstsub[i].Key.ToString() + "[" + npm.LowCnt.ToString() + "点]"); }
break;
}
}
#endregion
#region 滤除噪点后,计算总值
double tmpR = 0.0, tmpG = 0.0, tmpB = 0.0;
double tmpu = (dicimg[npm.Upper] - npm.UpCnt) * 1.0 / dicimg[npm.Upper]; // 部分过滤点保留的比率
/*if (this.IsLog)
{
swLog.WriteLine(string.Format("噪点+:{0}[{1}/{2}]={3}", npm.Upper.ToString(), npm.UpCnt, dicimg[npm.Upper], tmpu.ToString("F2")));
}*/
double tmpd = (dicimg[npm.Lower] - npm.LowCnt) * 1.0 / dicimg[npm.Lower]; // 部分过滤点保留的比率
/* if (this.IsLog)
{
swLog.WriteLine( string.Format("噪点-:{0}[{1}/{2}]={3}", npm.Lower.ToString(), npm.LowCnt, dicimg[npm.Lower], tmpd.ToString("F2")));
}*/
for (int i = 0; i < img2.Count; i++)
{
if (imgsub[i].G > npm.Upper || imgsub[i].G < npm.Lower)
{
continue; // 噪点,滤去
}
else if (imgsub[i].G == npm.Upper && npm.UpCnt > 0)
{
// 部分噪点,滤去部分
tmpR += img2[i].R * tmpu;
tmpG += img2[i].G * tmpu;
tmpB += img2[i].B * tmpu;
continue;
}
else if (imgsub[i].G == npm.Lower && npm.LowCnt > 0)
{
// 部分噪点,滤去部分
tmpR += img2[i].R * tmpd;
tmpG += img2[i].G * tmpd;
tmpB += img2[i].B * tmpd;
continue;
}
else
{
// 非噪点,计算总值
tmpR += img2[i].R;
tmpG += img2[i].G;
tmpB += img2[i].B;
}
}
sumR = Convert.ToInt32(tmpR);
sumG = Convert.ToInt32(tmpG);
sumB = Convert.ToInt32(tmpB);
/*if (this.IsLog)
{
tmp = img2.Count - npm.Threhold * 2;
strr = string.Format("处理总值:(R, G, B)({0}, {1}, {2}), 数据个数:{3}, ", sumR, sumG, sumB, tmp)
+ string.Format("均值:(R, G, B)({0}, {1}, {2})", (sumR * 1.0 / tmp).ToString("F2"), (sumG * 1.0 / tmp).ToString("F2"), (sumB * 1.0 / tmp).ToString("F2"));
swLog.WriteLine(strr);
//this.swLog.WriteLine();
}*/
#endregion
}
else
{
#region 仅一图,无法去噪,直接计算总值
List img2 = lstImages[lstImages.Count - 1]; // 上一幅
for (int i = 0; i < img2.Count; i++)
{
sumR += img2[i].R;
sumG += img2[i].G;
sumB += img2[i].B;
}
/* if (this.IsLog)
{
int tmp = img2.Count;
string strr = string.Format("处理总值:(R, G, B)({0}, {1}, {2}), 数据个数:{3}, ", sumR, sumG, sumB, tmp)
+ string.Format("均值:(R, G, B)({0}, {1}, {2})", (sumR * 1.0 / tmp).ToString("F2"), (sumG * 1.0 / tmp).ToString("F2"), (sumB * 1.0 / tmp).ToString("F2"));
swLog.WriteLine(strr);
//this.swLog.WriteLine();
}*/
#endregion
}
}
#endregion
}
///
/// 用int类型保存RGB三个值
///
public class IntRGB
{
#region properties
public int R { get; set; }
public int G { get; set; }
public int B { get; set; }
#endregion
public IntRGB()
{
R = 0;
G = 0;
B = 0;
}
public IntRGB(int r, int g, int b)
{
R = r;
G = g;
B = b;
}
}
///
/// 噪点相关参数
///
public class NoiseParam
{
///
/// 前后两图相减法,去除上下噪点
///
/// 上下各自噪点数
public NoiseParam(int threhold)
{
Threhold = threhold;
Upper = 0;
UpCnt = 0;
Lower = 0;
LowCnt = 0;
}
#region
///
/// 噪点个数
///
public int Threhold { get; set; }
///
/// 噪点上阈值
///
public int Upper { get; set; }
///
/// 上阈值噪点数个数
///
public int UpCnt { get; set; }
///
/// 噪点下阈值
///
public int Lower { get; set; }
///
/// 下阈值噪点个数
///
public int LowCnt { get; set; }
#endregion
}
}