使用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> 先讲讲思路,图片是一组庞大的矩阵数据,每一个像素点有用数据为五个分别为RGB(三原色),以及XY坐标。也就是说我们能将整张图片每一个像素点的数据提取出来加以分析。那么就可以做到图片识别。</p>
<p> 源代码会在最下方贴出。</p>
<p>首先整个流程思想是这杨</p>
<p> </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> 二级化以后,这张图片的数据就只剩黑色和白色,如果二级化时没有损坏到目标特征像素点,那么接下来提取目标特征像素点会很容易,因为只有黑白两色</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> </p>
<p><img src="https://img2024.cnblogs.com/blog/948036/202509/948036-20250928133344089-1808926729.png"> <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> 因为当初代码里设定生成的图片是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> 经过我进行数据处理后的图片内提取出了三条鱼的中心点位数据</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> </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> </p>
<p> </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)"><summary></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)"></summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="oldpath"></param></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="newPath"></param></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)"><summary></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)"></summary></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 & 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 < 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 < <span style="color: rgba(128, 0, 128, 1)">150</span> || contours.Length > <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)"><summary></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)"></summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="oldpath"></param></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="newPath"></param></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><Bgr, Byte> src = <span style="color: rgba(0, 0, 255, 1)">new</span> Image<Bgr, <span style="color: rgba(0, 0, 255, 1)">byte</span>><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 > <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 > <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 > <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><Bgr, Byte> srcNewSize = <span style="color: rgba(0, 0, 255, 1)">new</span> Image<Bgr, <span style="color: rgba(0, 0, 255, 1)">byte</span>><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 ><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)"><summary></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)"></summary></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)"><summary></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)"></summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="img"></param></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><returns></returns></span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> List<<span style="color: rgba(0, 0, 255, 1)">string</span>> 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><<span style="color: rgba(0, 0, 255, 1)">int</span>> R = <span style="color: rgba(0, 0, 255, 1)">new</span> List<<span style="color: rgba(0, 0, 255, 1)">int</span>><span style="color: rgba(0, 0, 0, 1)">();
List</span><<span style="color: rgba(0, 0, 255, 1)">int</span>> G = <span style="color: rgba(0, 0, 255, 1)">new</span> List<<span style="color: rgba(0, 0, 255, 1)">int</span>><span style="color: rgba(0, 0, 0, 1)">();
List</span><<span style="color: rgba(0, 0, 255, 1)">int</span>> B = <span style="color: rgba(0, 0, 255, 1)">new</span> List<<span style="color: rgba(0, 0, 255, 1)">int</span>><span style="color: rgba(0, 0, 0, 1)">();
List</span><<span style="color: rgba(0, 0, 255, 1)">string</span>> xyList = <span style="color: rgba(0, 0, 255, 1)">new</span> List<<span style="color: rgba(0, 0, 255, 1)">string</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> y = <span style="color: rgba(128, 0, 128, 1)">0</span>; y < 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 < 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> && a.G == <span style="color: rgba(128, 0, 128, 1)">0</span> && 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)"><summary></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)"></summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><returns></returns></span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> List<<span style="color: rgba(0, 0, 255, 1)">string</span>> FishExtract(List<<span style="color: rgba(0, 0, 255, 1)">string</span>> 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 < 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 => a.R == <span style="color: rgba(128, 0, 128, 1)">0</span> && a.G == <span style="color: rgba(128, 0, 128, 1)">0</span> && a.B == <span style="color: rgba(128, 0, 128, 1)">0</span>).Count() >= <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<FishVision.Model.Pixel> 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<FishVision.Model.Pixel><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 <= <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 <= <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 >= <span style="color: rgba(128, 0, 128, 1)">0</span> && newX < width && newY >= <span style="color: rgba(128, 0, 128, 1)">0</span> && newY <<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 < <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 < <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)"><summary></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)"></summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="listFish"></param></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><returns></returns></span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> List<FishModel> FishDistinct(List<FishModel><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> && listFish.Count() > <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 < 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)"><summary></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)"></summary></span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> List<FishModel> FishGroup(List<<span style="color: rgba(0, 0, 255, 1)">string</span>><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<FishModel><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 < 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 < 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) && !<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 => 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<<span style="color: rgba(0, 0, 255, 1)">string</span>><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)"><summary></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)"></summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="x1"></param></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="y1"></param></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="x2"></param></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="y2"></param></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><returns></returns></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) <= <span style="color: rgba(128, 0, 128, 1)">1</span> && Math.Abs(y1 - y2) <= <span style="color: rgba(128, 0, 128, 1)">1</span>) && !(x1 == x2 && 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)"><summary></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)"></summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="listFish"></param></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><returns></returns></span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> List<<span style="color: rgba(0, 0, 255, 1)">string</span>> FishCenter(List<FishModel><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<<span style="color: rgba(0, 0, 255, 1)">string</span>><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> && listFish.Count() > <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 < 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)"><summary></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)"></summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="oldpath"></param></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="newPath"></param></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)"><summary></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)"></summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="oldpath"></param></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="newPath"></param></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)"><summary></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)"></summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="mat"></span><span style="color: rgba(0, 128, 0, 1)">图片</span><span style="color: rgba(128, 128, 128, 1)"></param></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="resultMat"></span><span style="color: rgba(0, 128, 0, 1)">结果图片</span><span style="color: rgba(128, 128, 128, 1)"></param></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><returns></span><span style="color: rgba(0, 128, 0, 1)">斑点中心点数据</span><span style="color: rgba(128, 128, 128, 1)"></returns></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> </p><br><br>
来源:https://www.cnblogs.com/Gao1234/p/19113043
頁:
[1]