| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using o0.Geometry2D;
- using System;
- using UnityEngine.UIElements;
- using o0.Num;
- using Unity.VisualScripting;
- using System.Threading.Tasks;
- using System.Linq;
- using o0;
- using o0.Project;
- namespace ZIM.Image
- {
- // 灰度图处理(float)
- public class ImgProcessGray
- {
- int width, height;
- float[] pixels;
- public float this[int index]
- {
- get
- {
- if (index >= 0 && index < pixels.Count())
- return pixels[index];
- else
- return 0f;
- }
- }
- public float this[int i, int j] => this[i + j * width];
- public ImgProcessGray(float[] pixels, int width, int height)
- {
- if (pixels.Length != width * height)
- throw new ArgumentException("Input array length must be equal to width * height");
- this.width = width;
- this.height = height;
- this.pixels = pixels;
- }
- public (float[] p, int w, int h) FindLines()
- //public List<o0.Geometry.Line<float>> FindLines()
- {
- int kernel_size = 3;
- int half_size = kernel_size / 2;
- int conv_width = width - kernel_size + 1;
- int conv_height = height - kernel_size + 1;
- var edgeArray = new ConvEdge[conv_width * conv_height];
- var result = new float[conv_width * conv_height];
- Parallel.For(0, conv_width, (i) =>
- //for (int i = 0; i < conv_width; i++)
- {
- for (int j = 0; j < conv_height; j++)
- {
- var e = new ConvEdge(this, (i + half_size, j + half_size), kernel_size);
- edgeArray[i + j * conv_width] = e;
- result[i + j * conv_width] = e.Variance;
- }
- });
- //return default;
- LevelEqualization(result, 10240);
- return (result, conv_width, conv_height);
-
- }
- void SigmodAdjust(float[] p)
- {
- var mean = p.Mean();
- Parallel.For(0, p.Length, (i) =>
- {
- p[i] = 1 / (1 + (float)Math.Exp(-p[i]/mean));
- });
- }
- void LevelAdjust(float[] p)
- {
- var max = p.Max();
- var scale = 1 / (float)Math.Sqrt(max);
- Parallel.For(0, p.Length, (i) =>
- {
- p[i] = (float)Math.Sqrt(p[i]) * scale;
- });
- //var scale = 1 / max;
- //Parallel.For(0, p.Length, (i) =>
- //{
- // p[i] = Math.Min(p[i] * scale, 1);
- //});
- }
- void LevelEqualization(float[] p, int bit = 256)
- {
- bit -= 1;
- var scale = 1 / p.Max();
- Parallel.For(0, p.Length, (i) => p[i] *= scale); // 归一化
- int[] pint = new int[p.Length];
- Parallel.For(0, p.Length, i => pint[i] = (int)(p[i] * bit)); // 映射到256色彩
- int[] H = new int[bit+1];
- for (int i = 0; i < p.Length; i++)
- H[pint[i]]++;
- float[] HF = new float[bit+1];
- for (int i = 0; i <= bit; i++)
- HF[i] = H[i] / (float)p.Length; // 概率
- float[] D = new float[bit + 1];
- float temp = 0;
- for (int i = 1; i <= bit; i++) // 不取颜色为0的概率
- {
- temp += HF[i];
- D[i] = temp; // 累计密度
- }
- Parallel.For(0, p.Length, i => p[i] = D[pint[i]] / D.Last()); // 去密度为颜色,并归一化
- }
- }
- public class ConvEdge
- {
- public Vector<float> EdgePoint;
- public Vector<float> EdgeDirection;
- public float Variance;
- public int noiseCount;
- // kernel_size应是奇数,偶数没测试
- public ConvEdge(ImgProcessGray imgGray, (int, int) pixel, int kernel_size, int scale = 1)
- {
- EdgePoint = new Vector<float>(pixel.Item1, pixel.Item2);
- noiseCount = 0;
- var convList = new List<(float, Vector<float>)>();
- var mean = 0f;
- for (int i = pixel.Item1 - kernel_size / 2 * scale; i <= pixel.Item1 + kernel_size / 2 * scale; i += scale)
- {
- for (int j = pixel.Item2 - kernel_size / 2 * scale; j <= pixel.Item2 + kernel_size / 2 * scale; j += scale)
- {
- var value = imgGray[i, j];
- convList.Add((value, new Vector<float>(i, j)));
- mean += value;
- }
- }
- mean /= convList.Count;
- convList.Sort((a, b) => a.Item1.CompareTo(b.Item1));
- var vMean0 = Vector<float>.Zero; // 暗区
- var vMean1 = Vector<float>.Zero; // 明区
- for (int k = 0; k < convList.Count / 2; k++)
- {
- Variance += (float)Math.Pow((convList[k].Item1 - mean), 2) / convList.Count;
- vMean0 += convList[k].Item2;
- if (AreaOfPoint(convList[k].Item2) == 1)
- noiseCount++;
- }
- vMean0 /= convList.Count / 2;
- for (int k = convList.Count / 2; k < convList.Count; k++)
- {
- Variance += (float)Math.Pow((convList[k].Item1 - mean), 2) / convList.Count;
- vMean1 += convList[k].Item2;
- if (AreaOfPoint(convList[k].Item2) == 0)
- noiseCount++;
- }
- vMean1 /= convList.Count - convList.Count / 2;
- GetEdgeDirection(vMean0, vMean1);
- }
- // 返回 1 在明区,返回 0 在暗区, -1 在边界上
- public int AreaOfPoint(Vector<float> v)
- {
- var ev = v - EdgePoint;
- var dot = ev.x * EdgeDirection.y - ev.y * EdgeDirection.x;
- if (dot == 0)
- return -1;
- return dot < 0 ? 1 : 0;
- }
- void GetEdgeDirection(Vector<float> v0, Vector<float> v1) // v0 是暗部平均点,v1 是亮部平均点
- {
- var dir = v1 - v0;
- EdgeDirection = new Vector<float>(dir.y, -dir.x);
- }
- //public void ConvEdge(int[] pixels, Vector2Int vec, int kernel_size, int scale)
- //{
- // var sum = 0f;
- // for (int i = vec.x - kernel_size / 2 * scale; i < vec.x + kernel_size / 2 * scale; i += scale)
- // {
- // for (int j = vec.y - kernel_size / 2 * scale; j < vec.y + kernel_size / 2 * scale; j += scale)
- // {
- // var index2 = webCamera.cameraInfo.Vector2ToIndex(i, j);
- // if (index2 > 0 && index2 < pixels.Length) // 超出边缘不计算
- // sum += pixels[index2];
- // }
- // }
- // return sum / kernel_size / kernel_size;
- //}
- }
- }
|