上官明月 發表於 2025-10-10 08:56:00

使用OpenCvSharp , Emgu.CV 手搓 视觉识别算法 以及 成果展示

<p>举个🌰</p>
<p>一个培养皿里有若干条鱼苗,需要将它全部区分识别出来,</p>
<p>像如下图所示的小蝌蚪就是(培养皿里三个黑点是热带鱼苗,做实验用的,一毫米长)</p>
<p>用的是海康威视的黑白工业相机拍摄。</p>
<p><img src="https://img2024.cnblogs.com/blog/948036/202509/948036-20250926104018432-1507733312.png"></p>
<p>&nbsp;先讲讲思路,图片是一组庞大的矩阵数据,每一个像素点有用数据为五个分别为RGB(三原色),以及XY坐标。也就是说我们能将整张图片每一个像素点的数据提取出来加以分析。那么就可以做到图片识别。</p>
<p>&nbsp;源代码会在最下方贴出。</p>
<p>首先整个流程思想是这杨</p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 0, 255, 1)">#region</span> 6孔混合鱼苗<span style="color: rgba(0, 0, 0, 1)">

VisionHelper.Two_Level(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\右上角三只鱼的提取\小鱼图片2-单个.png</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\二级化.png</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

VisionHelper.Outline(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\二级化.png</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\轮廓检测.png</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

VisionHelper.CutCircle(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\轮廓检测.png</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\圆形剪切.bmp</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

VisionHelper.ExtractCircle(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\圆形剪切.bmp</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\圆形提取.jpg</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

</span><span style="color: rgba(0, 0, 255, 1)">var</span> data = VisionHelper.GetImagePixel(<span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\圆形提取.jpg</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

data </span>= VisionHelper.FishExtract(data, <span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\圆形提取.jpg</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

</span><span style="color: rgba(0, 0, 255, 1)">var</span> fish =<span style="color: rgba(0, 0, 0, 1)"> VisionHelper.FishGroup(data);

fish </span>=<span style="color: rgba(0, 0, 0, 1)"> VisionHelper.FishDistinct(fish);

data </span>=<span style="color: rgba(0, 0, 0, 1)"> VisionHelper.FishCenter(fish);

</span><span style="color: rgba(0, 0, 255, 1)">#endregion</span></pre>
</div>
<pre> 先将抓取的图片二级化,效果如下所示</pre>
<div class="cnblogs_code">
<pre> VisionHelper.Two_Level(<span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\右上角三只鱼的提取\小鱼图片2-单个.png</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\二级化.png</span><span style="color: rgba(128, 0, 0, 1)">"</span>);</pre>
</div>
<pre> 原图左,处理图右</pre>
<p><img src="https://img2024.cnblogs.com/blog/948036/202509/948036-20250926104018432-1507733312.png"><img src="https://img2024.cnblogs.com/blog/948036/202509/948036-20250928133344089-1808926729.png"></p>
<p>&nbsp;二级化以后,这张图片的数据就只剩黑色和白色,如果二级化时没有损坏到目标特征像素点,那么接下来提取目标特征像素点会很容易,因为只有黑白两色</p>
<p>接下来做轮廓监测,将整个培养皿扫描出来并且去除,这杨就只剩培养皿内的鱼苗和食物或者排泄物</p>
<div class="cnblogs_code">
<pre> VisionHelper.Outline(<span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\二级化.png</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\轮廓检测.png</span><span style="color: rgba(128, 0, 0, 1)">"</span>);</pre>
</div>
<pre>效果如下所示</pre>
<p>&nbsp;</p>
<p><img src="https://img2024.cnblogs.com/blog/948036/202509/948036-20250928133344089-1808926729.png">&nbsp; &nbsp; &nbsp; &nbsp;<img src="https://img2024.cnblogs.com/blog/948036/202509/948036-20250928133804001-626464691.png"></p>
<p>在图片处理的算法中,我用红圈标注了培养皿内的区域,并且用蓝点打出了中心</p>
<p>接下来呢,可以将其他无用的图片区域全部剪切掉,就是图片内圆形切割</p>
<div class="cnblogs_code">
<pre> VisionHelper.CutCircle(<span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\轮廓检测.png</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\圆形剪切.bmp</span><span style="color: rgba(128, 0, 0, 1)">"</span>);</pre>
</div>
<p>切割效果如下图所示</p>
<p><img src="https://img2024.cnblogs.com/blog/948036/202509/948036-20250928133804001-626464691.png"><img src="https://img2024.cnblogs.com/blog/948036/202509/948036-20250928134814221-887451404.png"></p>
<p>&nbsp;因为当初代码里设定生成的图片是BMP,上传不了博客,所以这粗糙的截图一下。</p>
<p>可以看到圆形剪切.bmp里只剩培养皿内区域的图片了</p>
<p>之前轮廓处理和圆形剪切形成的红色,蓝色圆圈或者中心点代码里可以设置不写入</p>
<p>那么接下来就是对圆形剪切区域的有用像素进行提取和分析</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 0, 255, 1)">var</span> data = VisionHelper.GetImagePixel(<span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\圆形提取.jpg</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

data </span>= VisionHelper.FishExtract(data, <span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">C:\Users\Administrator\Desktop\3.1\圆形提取.jpg</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

</span><span style="color: rgba(0, 0, 255, 1)">var</span> fish =<span style="color: rgba(0, 0, 0, 1)"> VisionHelper.FishGroup(data);

fish </span>=<span style="color: rgba(0, 0, 0, 1)"> VisionHelper.FishDistinct(fish);

data </span>= VisionHelper.FishCenter(fish);</pre>
</div>
<p>我先展示下最终的结果</p>
<p><img src="https://img2024.cnblogs.com/blog/948036/202509/948036-20250928140430362-1192554314.png"></p>
<p>&nbsp;经过我进行数据处理后的图片内提取出了三条鱼的中心点位数据</p>
<p>我们校验一下答案</p>
<p>下图1是原图</p>
<p><img src="https://img2024.cnblogs.com/blog/948036/202509/948036-20250926104018432-1507733312.png"></p>
<p>三个小黑点是三条鱼数据正确,坐标是否正确?我用画图工具打开校验</p>
<p>如下三图所示,为了更直观的展示结果,用鼠标浮在指定坐标,手机拍摄的,不是很清楚但是看得清,大家可以双击图片放大</p>
<p><img src="https://img2024.cnblogs.com/blog/948036/202509/948036-20250928141046923-1738887462.jpg"></p>
<p>第一条数据151,77,在图内鼠标右上角指向的小鱼苗内</p>
<p><img src="https://img2024.cnblogs.com/blog/948036/202509/948036-20250928141135450-58124379.jpg"></p>
<p>第二条数据22,88,在图内鼠标左侧指向的小鱼苗内</p>
<p><img src="https://img2024.cnblogs.com/blog/948036/202509/948036-20250928141148029-1307811872.jpg"></p>
<p>第三条数据137,148,88,在图内鼠标右下角指向的小鱼苗内</p>
<p>&nbsp;</p>
<p><span style="background-color: rgba(255, 102, 0, 1)"><em>接下来贴出我手搓的核心算法</em></span></p>
<p><span style="background-color: rgba(255, 102, 0, 1)"><em>整个VisionHelper运用了OpenCvSharp和Emgu.CV这两个第三方图片处理框架的算法,所有的方法都可以灵活运用,方法体内的参数可以随着实际需要识别的物体做调整</em></span></p>
<p><span style="background-color: rgba(255, 102, 0, 1)"><em>(源代码里有那么多注释应该就不用在讲解基础框架和算法应用了吧,嘻嘻)</em></span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Emgu.CV;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Emgu.CV.CvEnum;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Emgu.CV.Structure;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> OpenCvSharp;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Drawing.Drawing2D;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Drawing.Imaging;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> FishVision.Model;

</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> FishVision
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> VisionHelper
    {
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 1.二级化
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="oldpath"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="newPath"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Two_Level(<span style="color: rgba(0, 0, 255, 1)">string</span> oldpath,<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> newPath)
      {
            Emgu.CV.Mat image </span>=<span style="color: rgba(0, 0, 0, 1)"> CvInvoke.Imread(oldpath, Emgu.CV.CvEnum.ImreadModes.Grayscale);
            Emgu.CV.Mat mid </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Emgu.CV.Mat();
            CvInvoke.Threshold(image, mid, </span><span style="color: rgba(128, 0, 128, 1)">125</span>, <span style="color: rgba(128, 0, 128, 1)">255</span>, ThresholdType.Binary);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">180 改</span>
<span style="color: rgba(0, 0, 0, 1)">            CvInvoke.Imwrite(newPath, mid);

      }

      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 2.轮廓检测
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Outline(<span style="color: rgba(0, 0, 255, 1)">string</span> oldpath, <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> newPath)
      {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">读取图片</span>
            <span style="color: rgba(0, 0, 255, 1)">var</span> img =<span style="color: rgba(0, 0, 0, 1)"> Cv2.ImRead(oldpath);

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">转换成灰度图</span>
            OpenCvSharp.Mat gray =<span style="color: rgba(0, 0, 0, 1)"> img.CvtColor(ColorConversionCodes.BGR2GRAY);

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">阈值操作 阈值参数可以用一些可视化工具来调试得到</span>
            OpenCvSharp.Mat ThresholdImg = gray.Threshold(<span style="color: rgba(128, 0, 128, 1)">135</span>, <span style="color: rgba(128, 0, 128, 1)">255</span><span style="color: rgba(0, 0, 0, 1)">, ThresholdTypes.Binary);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Cv2.ImShow("Threshold", ThresholdImg);

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">降噪 高斯变化
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Mat gaussImg= ThresholdImg.GaussianBlur(new Size(5, 5), 0.8);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Cv2.ImShow("GaussianBlur", gaussImg);

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">中值滤波降噪
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Mat medianImg = ThresholdImg.MedianBlur(5);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Cv2.ImShow("MedianBlur", medianImg);

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">膨胀+腐蚀
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Mat kernel = new Mat(15, 15, MatType.CV_8UC1);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Mat DilateImg = ThresholdImg.Dilate(kernel);</span>
            <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)">/腐蚀处理</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Mat binary = DilateImg.Erode(kernel);</span>
<span style="color: rgba(0, 0, 0, 1)">
            OpenCvSharp.Mat element </span>= Cv2.GetStructuringElement(MorphShapes.Ellipse, <span style="color: rgba(0, 0, 255, 1)">new</span> OpenCvSharp.Size(<span style="color: rgba(128, 0, 128, 1)">3</span>, <span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">));
            OpenCvSharp.Mat openImg </span>=<span style="color: rgba(0, 0, 0, 1)"> ThresholdImg.MorphologyEx(MorphTypes.Open, element);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Cv2.ImShow("Dilate &amp; Erode", openImg);

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置感兴趣的区域</span>
            <span style="color: rgba(0, 0, 255, 1)">int</span> x = <span style="color: rgba(128, 0, 128, 1)">0</span>, y = <span style="color: rgba(128, 0, 128, 1)">0</span>, w = img.Width, h =<span style="color: rgba(0, 0, 0, 1)"> img.Height;
            Rect roi </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Rect(x, y, w, h);
            OpenCvSharp.Mat ROIimg </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> OpenCvSharp.Mat(openImg, roi);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Cv2.ImShow("ROI Image", ROIimg);

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">寻找图像轮廓</span>
<span style="color: rgba(0, 0, 0, 1)">            OpenCvSharp.Point[][] contours;
            HierarchyIndex[] hierachy;
            Cv2.FindContours(ROIimg, </span><span style="color: rgba(0, 0, 255, 1)">out</span> contours, <span style="color: rgba(0, 0, 255, 1)">out</span><span style="color: rgba(0, 0, 0, 1)"> hierachy, RetrievalModes.List, ContourApproximationModes.ApproxTC89KCOS);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">根据找到的轮廓点,拟合椭圆</span>
            <span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i &lt; contours.Length; i++<span style="color: rgba(0, 0, 0, 1)">)
            {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">拟合函数必须至少5个点,少于则不拟合</span>
                <span style="color: rgba(0, 0, 255, 1)">if</span> (contours.Length &lt; <span style="color: rgba(128, 0, 128, 1)">150</span> || contours.Length &gt; <span style="color: rgba(128, 0, 128, 1)">200</span>) <span style="color: rgba(0, 0, 255, 1)">continue</span><span style="color: rgba(0, 0, 0, 1)">;
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">椭圆拟合</span>
                <span style="color: rgba(0, 0, 255, 1)">var</span> rrt =<span style="color: rgba(0, 0, 0, 1)"> Cv2.FitEllipse(contours);

                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">ROI复原</span>
                rrt.Center.X +=<span style="color: rgba(0, 0, 0, 1)"> x;
                rrt.Center.Y </span>+=<span style="color: rgba(0, 0, 0, 1)"> y;

                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">画椭圆</span>
                Cv2.Ellipse(img, rrt, <span style="color: rgba(0, 0, 255, 1)">new</span> Scalar(<span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">255</span>), <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">, LineTypes.AntiAlias);
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">画圆心</span>
                Cv2.Circle(img, (<span style="color: rgba(0, 0, 255, 1)">int</span>)(rrt.Center.X), (<span style="color: rgba(0, 0, 255, 1)">int</span>)(rrt.Center.Y), <span style="color: rgba(128, 0, 128, 1)">4</span>, <span style="color: rgba(0, 0, 255, 1)">new</span> Scalar(<span style="color: rgba(128, 0, 128, 1)">255</span>, <span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">0</span>), -<span style="color: rgba(128, 0, 128, 1)">1</span>, LineTypes.Link8, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
            }

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Cv2.ImShow("Fit Circle", img);</span>
<span style="color: rgba(0, 0, 0, 1)">            Cv2.ImWrite(newPath, img);

      }

      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 3.圆形剪切
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="oldpath"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="newPath"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> CutCircle(<span style="color: rgba(0, 0, 255, 1)">string</span> oldpath, <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> newPath)
      {
            Image</span>&lt;Bgr, Byte&gt; src = <span style="color: rgba(0, 0, 255, 1)">new</span> Image&lt;Bgr, <span style="color: rgba(0, 0, 255, 1)">byte</span>&gt;<span style="color: rgba(0, 0, 0, 1)">(oldpath);

            </span><span style="color: rgba(0, 0, 255, 1)">int</span> scale = <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (src.Width &gt; <span style="color: rgba(128, 0, 128, 1)">500</span><span style="color: rgba(0, 0, 0, 1)">)
            {
                scale </span>= <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">;
            }
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (src.Width &gt; <span style="color: rgba(128, 0, 128, 1)">1000</span><span style="color: rgba(0, 0, 0, 1)">)
            {
                scale </span>= <span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">;
            }
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (src.Width &gt; <span style="color: rgba(128, 0, 128, 1)">10000</span><span style="color: rgba(0, 0, 0, 1)">)
            {
                scale </span>= <span style="color: rgba(128, 0, 128, 1)">100</span><span style="color: rgba(0, 0, 0, 1)">;
            }
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> size = <span style="color: rgba(0, 0, 255, 1)">new</span> System.Drawing.Size(src.Width / scale, src.Height /<span style="color: rgba(0, 0, 0, 1)"> scale);
            Image</span>&lt;Bgr, Byte&gt; srcNewSize = <span style="color: rgba(0, 0, 255, 1)">new</span> Image&lt;Bgr, <span style="color: rgba(0, 0, 255, 1)">byte</span>&gt;<span style="color: rgba(0, 0, 0, 1)">(size);
            CvInvoke.Resize(src, srcNewSize, size);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">将图像转换为灰度</span>
            Emgu.CV.UMat grayImage = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Emgu.CV.UMat();
            CvInvoke.CvtColor(srcNewSize, grayImage, ColorConversion.Bgr2Gray);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">使用高斯滤波去除噪声</span>
            CvInvoke.GaussianBlur(grayImage, grayImage, <span style="color: rgba(0, 0, 255, 1)">new</span> System.Drawing.Size(<span style="color: rgba(128, 0, 128, 1)">3</span>, <span style="color: rgba(128, 0, 128, 1)">3</span>), <span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">霍夫圆检测</span>
            CircleF[] circles = CvInvoke.HoughCircles(grayImage, Emgu.CV.CvEnum.HoughModes.Gradient, <span style="color: rgba(128, 0, 128, 1)">2.0</span>, <span style="color: rgba(128, 0, 128, 1)">200.0</span>, <span style="color: rgba(128, 0, 128, 1)">100.0</span>, <span style="color: rgba(128, 0, 128, 1)">180.0</span>, <span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">);

            Rectangle rectangle </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Rectangle();
            </span><span style="color: rgba(0, 0, 255, 1)">float</span> maxRadius = <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
            </span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (CircleF circle <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> circles)
            {
                </span><span style="color: rgba(0, 0, 255, 1)">var</span> center = circle.Center;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">圆心</span>
                <span style="color: rgba(0, 0, 255, 1)">var</span> radius = circle.Radius;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">半径</span>
                <span style="color: rgba(0, 0, 255, 1)">if</span> (radius &gt;<span style="color: rgba(0, 0, 0, 1)"> maxRadius)
                {
                  maxRadius </span>=<span style="color: rgba(0, 0, 0, 1)"> radius;
                  rectangle </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Rectangle((<span style="color: rgba(0, 0, 255, 1)">int</span>)(center.X - radius) *<span style="color: rgba(0, 0, 0, 1)"> scale,
                        (</span><span style="color: rgba(0, 0, 255, 1)">int</span>)(center.Y - radius) *<span style="color: rgba(0, 0, 0, 1)"> scale,
                        (</span><span style="color: rgba(0, 0, 255, 1)">int</span>)radius * <span style="color: rgba(128, 0, 128, 1)">2</span> * scale +<span style="color: rgba(0, 0, 0, 1)"> scale,
                        (</span><span style="color: rgba(0, 0, 255, 1)">int</span>)radius * <span style="color: rgba(128, 0, 128, 1)">2</span> * scale +<span style="color: rgba(0, 0, 0, 1)"> scale);
                }
                srcNewSize.Draw(circle, </span><span style="color: rgba(0, 0, 255, 1)">new</span> Bgr(System.Drawing.Color.Blue), <span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">);
            }

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">CvInvoke.Imwrite("原始图片.bmp", srcNewSize); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">保存原始图片</span>

            <span style="color: rgba(0, 0, 255, 1)">if</span> (maxRadius == <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
            {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">MessageBox.Show("没有圆形");</span>
<span style="color: rgba(0, 0, 0, 1)">            }
            CvInvoke.cvSetImageROI(srcNewSize.Ptr, rectangle);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置兴趣点—ROI(region of interest )</span>
            <span style="color: rgba(0, 0, 255, 1)">var</span> clone =<span style="color: rgba(0, 0, 0, 1)"> srcNewSize.Clone();
            CvInvoke.Imwrite(newPath, clone); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">保存结果图 </span>
<span style="color: rgba(0, 0, 0, 1)">            src.Dispose();
            srcNewSize.Dispose();
            grayImage.Dispose();
      }

      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 4.圆形提取
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> ExtractCircle(<span style="color: rgba(0, 0, 255, 1)">string</span> oldpath, <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> newPath)
      {

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 加载原始图片</span>
            Bitmap originalImage = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Bitmap(oldpath);
            </span><span style="color: rgba(0, 0, 255, 1)">int</span> diameter = Math.Min(originalImage.Width, originalImage.Height); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取最小边长作为直径</span>
            <span style="color: rgba(0, 0, 255, 1)">int</span> x = (originalImage.Width - diameter) / <span style="color: rgba(128, 0, 128, 1)">2</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 计算起始x坐标</span>
            <span style="color: rgba(0, 0, 255, 1)">int</span> y = (originalImage.Height - diameter) / <span style="color: rgba(128, 0, 128, 1)">2</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 计算起始y坐标

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建与圆形大小相等的bitmap</span>
            Bitmap croppedImage = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Bitmap(diameter, diameter);
            </span><span style="color: rgba(0, 0, 255, 1)">using</span> (Graphics g =<span style="color: rgba(0, 0, 0, 1)"> Graphics.FromImage(croppedImage))
            {
                g.Clear(Color.LightBlue); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置圆圈外的颜色
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置高质量插值法</span>
                g.InterpolationMode =<span style="color: rgba(0, 0, 0, 1)"> InterpolationMode.HighQualityBicubic;
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置高质量,低速度呈现平滑程度</span>
                g.SmoothingMode =<span style="color: rgba(0, 0, 0, 1)"> SmoothingMode.HighQuality;
                g.PixelOffsetMode </span>=<span style="color: rgba(0, 0, 0, 1)"> PixelOffsetMode.HighQuality;
                g.CompositingQuality </span>=<span style="color: rgba(0, 0, 0, 1)"> CompositingQuality.HighQuality;

                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建一个圆形路径</span>
                <span style="color: rgba(0, 0, 255, 1)">using</span> (GraphicsPath path = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> GraphicsPath())
                {
                  path.AddEllipse(</span><span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, diameter, diameter);
                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置裁剪区域为圆形路径</span>
<span style="color: rgba(0, 0, 0, 1)">                  g.SetClip(path);
                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 从原始图片中绘制圆形区域到新图片</span>
                  g.DrawImage(originalImage, <span style="color: rgba(0, 0, 255, 1)">new</span> Rectangle(<span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, diameter, diameter), x, y, diameter, diameter, GraphicsUnit.Pixel);
                }
            }
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 保存剪切后的图片</span>
<span style="color: rgba(0, 0, 0, 1)">            croppedImage.Save(newPath, ImageFormat.Jpeg);
      }

      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 5.像素提取(默认黑像素)
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="img"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> List&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt; GetImagePixel(<span style="color: rgba(0, 0, 255, 1)">string</span> oldpath)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">过滤</span>
<span style="color: rgba(0, 0, 0, 1)">      {
             </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 加载原始图片</span>
            Bitmap img = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Bitmap(oldpath);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">0 黑色
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">95 深灰
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">240 浅灰
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">255 白</span>
<span style="color: rgba(0, 0, 0, 1)">
            List</span>&lt;<span style="color: rgba(0, 0, 255, 1)">int</span>&gt; R = <span style="color: rgba(0, 0, 255, 1)">new</span> List&lt;<span style="color: rgba(0, 0, 255, 1)">int</span>&gt;<span style="color: rgba(0, 0, 0, 1)">();
            List</span>&lt;<span style="color: rgba(0, 0, 255, 1)">int</span>&gt; G = <span style="color: rgba(0, 0, 255, 1)">new</span> List&lt;<span style="color: rgba(0, 0, 255, 1)">int</span>&gt;<span style="color: rgba(0, 0, 0, 1)">();
            List</span>&lt;<span style="color: rgba(0, 0, 255, 1)">int</span>&gt; B = <span style="color: rgba(0, 0, 255, 1)">new</span> List&lt;<span style="color: rgba(0, 0, 255, 1)">int</span>&gt;<span style="color: rgba(0, 0, 0, 1)">();
            List</span>&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt; xyList = <span style="color: rgba(0, 0, 255, 1)">new</span> List&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt;<span style="color: rgba(0, 0, 0, 1)">();

            </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> y = <span style="color: rgba(128, 0, 128, 1)">0</span>; y &lt; img.Height; y++<span style="color: rgba(0, 0, 0, 1)">)
            {
                </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> x = <span style="color: rgba(128, 0, 128, 1)">0</span>; x &lt; img.Width; x++<span style="color: rgba(0, 0, 0, 1)">)
                {
                  </span><span style="color: rgba(0, 0, 255, 1)">var</span> a =<span style="color: rgba(0, 0, 0, 1)"> img.GetPixel(x, y);

                  </span><span style="color: rgba(0, 0, 255, 1)">if</span> (a.R == <span style="color: rgba(128, 0, 128, 1)">0</span> &amp;&amp; a.G == <span style="color: rgba(128, 0, 128, 1)">0</span> &amp;&amp; a.B == <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
                  {
                        R.Add(img.GetPixel(x, y).R);
                        G.Add(img.GetPixel(x, y).G);
                        B.Add(img.GetPixel(x, y).B);
                        xyList.Add(x </span>+ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">|</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> y);
                  }

                }
            }

            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> xyList;
      }

      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 6.鱼像素提取
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> List&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt; FishExtract(List&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt; data ,<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> circleImg)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i &lt; data.Count; i++<span style="color: rgba(0, 0, 0, 1)">)
            {
                </span><span style="color: rgba(0, 0, 255, 1)">var</span> str = data.Split(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">|</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

                </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">.IsNullOrWhiteSpace(data))
                {
                  Bitmap image2 </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Bitmap(circleImg);

                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">周边检测 6</span>
                  <span style="color: rgba(0, 0, 255, 1)">var</span> list = GetSurroundingPixels(image2, Convert.ToInt32(str[<span style="color: rgba(128, 0, 128, 1)">0</span>]), Convert.ToInt32(str[<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">]));

                  </span><span style="color: rgba(0, 0, 255, 1)">if</span> (list.Where(a =&gt; a.R == <span style="color: rgba(128, 0, 128, 1)">0</span> &amp;&amp; a.G == <span style="color: rgba(128, 0, 128, 1)">0</span> &amp;&amp; a.B == <span style="color: rgba(128, 0, 128, 1)">0</span>).Count() &gt;= <span style="color: rgba(128, 0, 128, 1)">2</span>)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这是鱼像素特征</span>
<span style="color: rgba(0, 0, 0, 1)">                  {

                  }
                  </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
                  {
                        data </span>= <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">.Empty;
                        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">非鱼</span>
<span style="color: rgba(0, 0, 0, 1)">                  }
                }
            }
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> data;
      }

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">像素周边检测</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> List&lt;FishVision.Model.Pixel&gt; GetSurroundingPixels(Bitmap bitmap, <span style="color: rgba(0, 0, 255, 1)">int</span> x, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> y)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> result = <span style="color: rgba(0, 0, 255, 1)">new</span> List&lt;FishVision.Model.Pixel&gt;<span style="color: rgba(0, 0, 0, 1)">();

            </span><span style="color: rgba(0, 0, 255, 1)">int</span> width =<span style="color: rgba(0, 0, 0, 1)"> bitmap.Width;
            </span><span style="color: rgba(0, 0, 255, 1)">int</span> height =<span style="color: rgba(0, 0, 0, 1)"> bitmap.Height;
            Color[,] surroundingPixels </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Color[<span style="color: rgba(128, 0, 128, 1)">3</span>, <span style="color: rgba(128, 0, 128, 1)">3</span>]; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 3x3 grid including the center pixel</span>

            <span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = -<span style="color: rgba(128, 0, 128, 1)">1</span>; i &lt;= <span style="color: rgba(128, 0, 128, 1)">1</span>; i++) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Loop through the 3x3 grid around the center pixel</span>
<span style="color: rgba(0, 0, 0, 1)">            {
                </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> j = -<span style="color: rgba(128, 0, 128, 1)">1</span>; j &lt;= <span style="color: rgba(128, 0, 128, 1)">1</span>; j++<span style="color: rgba(0, 0, 0, 1)">)
                {
                  </span><span style="color: rgba(0, 0, 255, 1)">int</span> newX = x +<span style="color: rgba(0, 0, 0, 1)"> i;
                  </span><span style="color: rgba(0, 0, 255, 1)">int</span> newY = y +<span style="color: rgba(0, 0, 0, 1)"> j;
                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Check if the new coordinates are within the bounds of the image</span>
                  <span style="color: rgba(0, 0, 255, 1)">if</span> (newX &gt;= <span style="color: rgba(128, 0, 128, 1)">0</span> &amp;&amp; newX &lt; width &amp;&amp; newY &gt;= <span style="color: rgba(128, 0, 128, 1)">0</span> &amp;&amp; newY &lt;<span style="color: rgba(0, 0, 0, 1)"> height)
                  {
                        surroundingPixels =<span style="color: rgba(0, 0, 0, 1)"> bitmap.GetPixel(newX, newY);
                  }
                  </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
                  {
                        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Optionally, set out-of-bounds pixels to a default color or handle them as needed</span>
                        surroundingPixels = Color.Transparent; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> or any other color you prefer</span>
<span style="color: rgba(0, 0, 0, 1)">                  }
                }
            }


            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Use surroundingPixels as needed (e.g., print colors)</span>
            <span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i &lt; <span style="color: rgba(128, 0, 128, 1)">3</span>; i++) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Printing the surrounding pixels for demonstration purposes</span>
<span style="color: rgba(0, 0, 0, 1)">            {
                </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> j = <span style="color: rgba(128, 0, 128, 1)">0</span>; j &lt; <span style="color: rgba(128, 0, 128, 1)">3</span>; j++<span style="color: rgba(0, 0, 0, 1)">)
                {
                  </span><span style="color: rgba(0, 0, 255, 1)">var</span> model = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> FishVision.Model.Pixel();

                  model.X </span>= x + i - <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;
                  model.Y </span>= y + j - <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;

                  model.R </span>=<span style="color: rgba(0, 0, 0, 1)"> surroundingPixels.R;
                  model.G </span>=<span style="color: rgba(0, 0, 0, 1)"> surroundingPixels.G;
                  model.B </span>=<span style="color: rgba(0, 0, 0, 1)"> surroundingPixels.B;

                  result.Add(model);

                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Console.WriteLine($"Pixel ({x + i - 1}, {y + j - 1}): {surroundingPixels}");</span>
<span style="color: rgba(0, 0, 0, 1)">                }
            }

            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> result;
      }

      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 7.鱼像素去重
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="listFish"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> List&lt;FishModel&gt; FishDistinct(List&lt;FishModel&gt;<span style="color: rgba(0, 0, 0, 1)"> listFish)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (listFish != <span style="color: rgba(0, 0, 255, 1)">null</span> &amp;&amp; listFish.Count() &gt; <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
            {
                </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i &lt; listFish.Count; i++<span style="color: rgba(0, 0, 0, 1)">)
                {
                  listFish.FishIndex </span>=<span style="color: rgba(0, 0, 0, 1)"> listFish.FishIndex.Distinct().ToList();
                }
            }
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> listFish;
      }

      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 8.鱼像素分组
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> List&lt;FishModel&gt; FishGroup(List&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt;<span style="color: rgba(0, 0, 0, 1)"> data)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> fish = <span style="color: rgba(0, 0, 255, 1)">new</span> List&lt;FishModel&gt;<span style="color: rgba(0, 0, 0, 1)">();
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">鱼像素分组</span>
            <span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i &lt; data.Count; i++<span style="color: rgba(0, 0, 0, 1)">)
            {
                </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> b = <span style="color: rgba(128, 0, 128, 1)">0</span>; b &lt; data.Count; b++<span style="color: rgba(0, 0, 0, 1)">)
                {

                  </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 255, 1)">string</span>.IsNullOrWhiteSpace(data) &amp;&amp; !<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">.IsNullOrWhiteSpace(data))
                  {
                        </span><span style="color: rgba(0, 0, 255, 1)">var</span> data_i_xy = data.Split(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">|</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                        </span><span style="color: rgba(0, 0, 255, 1)">var</span> data_b_xy = data.Split(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">|</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

                        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (AreAdjacent(Convert.ToInt32(data_i_xy[<span style="color: rgba(128, 0, 128, 1)">0</span>]), Convert.ToInt32(data_i_xy[<span style="color: rgba(128, 0, 128, 1)">1</span>]), Convert.ToInt32(data_b_xy[<span style="color: rgba(128, 0, 128, 1)">0</span>]), Convert.ToInt32(data_b_xy[<span style="color: rgba(128, 0, 128, 1)">1</span>])))<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">相邻的鱼像素合并一组</span>
<span style="color: rgba(0, 0, 0, 1)">                        {
                            </span><span style="color: rgba(0, 0, 255, 1)">var</span> entity = fish.Where(a =&gt; a.FishIndex.Contains(data) ||<span style="color: rgba(0, 0, 0, 1)"> a.FishIndex.Contains(data)).FirstOrDefault();
                            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (entity != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
                            {
                              entity.FishIndex.Add(data);
                              entity.FishIndex.Add(data);
                            }
                            </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
                            {
                              FishModel model </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> FishModel();
                              model.FishIndex </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> List&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt;<span style="color: rgba(0, 0, 0, 1)">();

                              model.FishIndex.Add(data);
                              model.FishIndex.Add(data);

                              fish.Add(model);
                            }
                        }
                  }
                }

            }
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> fish;
      }

      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 像素是否相邻
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="x1"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="y1"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="x2"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="y2"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> AreAdjacent(<span style="color: rgba(0, 0, 255, 1)">int</span> x1, <span style="color: rgba(0, 0, 255, 1)">int</span> y1, <span style="color: rgba(0, 0, 255, 1)">int</span> x2, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> y2)
      {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 检查x和y坐标之差是否为1,这样可以确保像素是直接相邻的</span>
            <span style="color: rgba(0, 0, 255, 1)">return</span> (Math.Abs(x1 - x2) &lt;= <span style="color: rgba(128, 0, 128, 1)">1</span> &amp;&amp; Math.Abs(y1 - y2) &lt;= <span style="color: rgba(128, 0, 128, 1)">1</span>) &amp;&amp; !(x1 == x2 &amp;&amp; y1 ==<span style="color: rgba(0, 0, 0, 1)"> y2);
      }

      

      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 9.每条鱼的像素群寻找中位值作为轨迹坐标
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="listFish"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> List&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt; FishCenter(List&lt;FishModel&gt;<span style="color: rgba(0, 0, 0, 1)"> listFish)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> result = <span style="color: rgba(0, 0, 255, 1)">new</span> List&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt;<span style="color: rgba(0, 0, 0, 1)">();
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (listFish != <span style="color: rgba(0, 0, 255, 1)">null</span> &amp;&amp; listFish.Count() &gt; <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
            {
                </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i &lt; listFish.Count; i++<span style="color: rgba(0, 0, 0, 1)">)
                {
                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">取中位值</span>
                  <span style="color: rgba(0, 0, 255, 1)">var</span> index = -<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;
                  </span><span style="color: rgba(0, 0, 255, 1)">if</span> (listFish.FishIndex.Count() % <span style="color: rgba(128, 0, 128, 1)">2</span> == <span style="color: rgba(128, 0, 128, 1)">0</span>) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 偶数长度</span>
<span style="color: rgba(0, 0, 0, 1)">                  {
                        index </span>= listFish.FishIndex.Count() / <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">;
                  }
                  </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 奇数长度</span>
<span style="color: rgba(0, 0, 0, 1)">                  {
                        index </span>= (listFish.FishIndex.Count() + <span style="color: rgba(128, 0, 128, 1)">1</span>) / <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">;
                  }

                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这条鱼中心坐标</span>
                  <span style="color: rgba(0, 0, 255, 1)">var</span> center =<span style="color: rgba(0, 0, 0, 1)"> listFish.FishIndex;
                  result.Add(center);

                }
            }
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> result;
      }

      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 反向二级化
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="oldpath"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="newPath"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Two_LevelReversal(<span style="color: rgba(0, 0, 255, 1)">string</span> oldpath, <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> newPath)
      {
            OpenCvSharp.Mat src </span>=<span style="color: rgba(0, 0, 0, 1)"> Cv2.ImRead(oldpath, OpenCvSharp.ImreadModes.Grayscale);
            OpenCvSharp.Mat dst </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> OpenCvSharp.Mat();

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 反向二值化:大于 127 的像素设为 0,其他设为 255</span>
            Cv2.Threshold(src, dst, <span style="color: rgba(128, 0, 128, 1)">135</span>, <span style="color: rgba(128, 0, 128, 1)">255</span><span style="color: rgba(0, 0, 0, 1)">, ThresholdTypes.BinaryInv);

            Cv2.ImWrite(newPath, dst);
      }

      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 96孔鱼苗高光二级化处理
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="oldpath"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="newPath"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Two_LevelHeight(<span style="color: rgba(0, 0, 255, 1)">string</span> oldpath, <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> newPath)
      {
            Emgu.CV.Mat image </span>=<span style="color: rgba(0, 0, 0, 1)"> CvInvoke.Imread(oldpath, Emgu.CV.CvEnum.ImreadModes.Grayscale);
            Emgu.CV.Mat mid2 </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Emgu.CV.Mat();
            CvInvoke.Threshold(image, mid2, </span><span style="color: rgba(128, 0, 128, 1)">180</span>, <span style="color: rgba(128, 0, 128, 1)">255</span><span style="color: rgba(0, 0, 0, 1)">, ThresholdType.Binary);
            CvInvoke.Imwrite(newPath, mid2);
      }


      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 斑点检测(用不着)
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="mat"&gt;</span><span style="color: rgba(0, 128, 0, 1)">图片</span><span style="color: rgba(128, 128, 128, 1)">&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="resultMat"&gt;</span><span style="color: rgba(0, 128, 0, 1)">结果图片</span><span style="color: rgba(128, 128, 128, 1)">&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;</span><span style="color: rgba(0, 128, 0, 1)">斑点中心点数据</span><span style="color: rgba(128, 128, 128, 1)">&lt;/returns&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> KeyPoint[] SimpleblobDetector(OpenCvSharp.Mat mat, <span style="color: rgba(0, 0, 255, 1)">out</span><span style="color: rgba(0, 0, 0, 1)"> OpenCvSharp.Mat resultMat)
      {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 转化为灰度图</span>
            OpenCvSharp.Mat gray = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> OpenCvSharp.Mat();
            Cv2.CvtColor(mat, gray, ColorConversionCodes.BGR2GRAY);

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建SimpleBlobDetector并设置参数</span>
            OpenCvSharp.SimpleBlobDetector.Params parameters = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> OpenCvSharp.SimpleBlobDetector.Params();
            parameters.BlobColor </span>= <span style="color: rgba(128, 0, 128, 1)">0</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">斑点的亮度值,取值为0或255,默认为0,表示只检测黑色斑点。</span>
            parameters.FilterByArea = <span style="color: rgba(0, 0, 255, 1)">true</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 是否根据斑点的面积进行过滤,默认为true</span>
            parameters.MinArea = <span style="color: rgba(128, 0, 128, 1)">10</span>;      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 最小的斑点面积,默认为25</span>
            parameters.MaxArea = <span style="color: rgba(128, 0, 128, 1)">6000</span>;      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 最大的斑点面积,默认为5000

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建SimpleBlobDetector</span>
            OpenCvSharp.SimpleBlobDetector detector =<span style="color: rgba(0, 0, 0, 1)"> OpenCvSharp.SimpleBlobDetector.Create(parameters);

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 检测斑点</span>
            KeyPoint[] keypoints =<span style="color: rgba(0, 0, 0, 1)"> detector.Detect(gray);

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 在图像上绘制斑点</span>
            resultMat = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> OpenCvSharp.Mat();
            Cv2.DrawKeypoints(mat, keypoints, resultMat, Scalar.All(</span>-<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">));
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> keypoints;
      }


    }
}</span></pre>
</div>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/Gao1234/p/19113043
頁: [1]
查看完整版本: 使用OpenCvSharp , Emgu.CV 手搓 视觉识别算法 以及 成果展示