using System; using System.Linq; using System.Drawing; using System.Collections.Generic; namespace shjxCamera { /// /// 将队列中的前后两幅图像像素点进行相减,最大的10%和最小的10%视为噪点,其余值进行平均值计算 /// public class NoiseDataFilter2 { public NoiseDataFilter2() { 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(); IntRGB2 val; for (int i = 0; i < img2.Count; i++) { val = new IntRGB2( 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 (IntRGB2 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 计算阈值参数 NoiseParam2 npm = new NoiseParam2(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(); IntRGB2 val; for (int i = 0; i < img2.Count; i++) { val = new IntRGB2( 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 (IntRGB2 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 计算阈值参数 NoiseParam2 npm = new NoiseParam2(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 IntRGB2 { #region properties public int R { get; set; } public int G { get; set; } public int B { get; set; } #endregion public IntRGB2() { R = 0; G = 0; B = 0; } public IntRGB2(int r, int g, int b) { R = r; G = g; B = b; } } /// /// 噪点相关参数 /// public class NoiseParam2 { /// /// 前后两图相减法,去除上下噪点 /// /// 上下各自噪点数 public NoiseParam2(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 } }