java-opencv分水岭算法分割硬币复现关键点

前言

java-opencv分水岭算法示例网上我是没找到java版本的教程。另外网上搜关于#基于分水岭算法的图像分割用法的教程基本都是官网基于那个有粘连的硬币分割图的。因为python语法简介灵活很多,移植到java的话稍不注意就会没那个效果的还不好排查,试了很多次才复现出示例的那个效果。教程很多我就不写明细了,说下例子了解的东西吧。理论我是不懂的想了解的网上找教程。

关键点在这个步骤上

  1. 联通函数返回物体个数和对应的掩码(ret个数,markers的坐标值其实的是个数的序号0,1,2,3最大值是ret;0算是背景)
  2. markersunknown==255 = 0;这步是个关键只是python语法太简洁,unknown来源就是背景(膨胀)-前景(腐蚀)的到的,把得到的联通域中之前的未知部分变为分水岭的未知区域。
ini 复制代码
     #Marker labelling`
     ret, markers = cv.connectedComponents(sure_fg)`
     # Add one to all labels so that sure background is not 0, but 1`
     markers = markers+1`
     # Now, mark the region of unknown with zero`
     markers[unknown==255] = 0`

流程了解的东西也不知道对不对

  1. 图像的二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果,二值化后的图片是单通道的。
scss 复制代码
//背景黑色前景白色THRESH_OTSU自动二值化
Imgproc.threshold(gray,gray,0,255,Imgproc.THRESH_BINARY_INV+Imgproc.THRESH_OTSU);

2.形态学处理,二值化后由于图像存在一些噪声(即白色的点)。所以需要形态学的开运算:腐蚀与膨胀平滑边界消除一些白点。

ini 复制代码
Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3,3));
Imgproc.morphologyEx(gray,gray,Imgproc.MORPH_OPEN,element);

3.得到背景、前景、未知区域。 膨胀是内容变大背景变小,物体边界增加到背景肯定是背景;腐蚀是内容变小,背景变大,这部分内容肯定是内容;然后膨胀后的图像-腐蚀后的=得到未知区域(如果物体不相连的话应该就是所谓的边界)。这个未知区域后面会用到

ini 复制代码
Mat sure_bg=new Mat();
Imgproc.dilate(gray, sure_bg, element, new Point(-1, -1), 3);
Mat sure_fg=new Mat();
Imgproc.erode(gray, sure_fg, element, new Point(-1, -1), 3);
Mat unknown=new Mat();
Core.subtract(sure_bg, sure_fg, unknown);
  1. 物体有相连接的部分需要用到距离变换,注意这里要使用第二次二值化处理。
ini 复制代码
//上次开运算得到的
Imgproc.distanceTransform(gray, dist_transform, Imgproc.CV_DIST_L2, 5);
//归一化
Core.normalize(dist_transform, dist_transform, 0, 1, Core.NORM_MINMAX);
Mat sure_fg2=new Mat();
Core.MinMaxLocResult mmr=Core.minMaxLoc(dist_transform);
//再次二值化
Imgproc.threshold(dist_transform,sure_fg2,0.5*mmr.maxVal,255,Imgproc.THRESH_BINARY);
  1. 使用分水岭算法

markers = markers+1因为分水岭中0是未知区域 makrers在java中里面坐标表示的图像的个数

markersunknown==255 = 0把上面得到的未知区域,在得到的连通域中表示为未知的地方

unknown是第一次得到的背景-第二次二值化的大前景

css 复制代码
int count=Imgproc.connectedComponents(sure_fg2,mask);
for(int i=0;i<mask.rows();i++){
    for(int j=0;j<mask.cols();j++){
        mask.put(i,j,new int[]{(int)mask.get(i,j)[0]+1});
        if(unknown.get(i,j)[0]==255){
            mask.put(i,j,new int[]{0});
        };
    }
}
Imgproc.watershed(source,mask);
相关推荐
我可能是个假开发1 小时前
FTP Unicode 文件名导致 `550` 的问题分析与解决方案
java·开发语言·spring
caoerzhong1 小时前
中小企业上 WMS 该先上哪几块:JeeWMS 开源 Java 仓库管理系统的分批上线清单
java·python·开源
正在走向自律1 小时前
AI数据分析与可视化:从基础到应用实践
服务器·人工智能·python·机器学习·数据分析·pandas
【JAVA】玩家2 小时前
Spring核心原理全解析:从零到生产实战
java·后端·spring
for_ever_love__2 小时前
模型评估与过拟合——交叉验证、正则化与指标解读
机器学习·模型评估·交叉验证·过拟合
Wang's Blog3 小时前
Java框架 SpringCloud 快速入门: 实现 Feign 最佳实践(抽取方式)
java·spring cloud
2501_926978333 小时前
给自指系统接一个外部锚 —— 一个关于「用 AI 观察自己」的方法
人工智能·经验分享·笔记·机器学习·ai写作
MandalaO_O3 小时前
IDEA 开发(快捷键 + 调试 + 序列化)
java·ide·intellij-idea
xiaoqiMikko4 小时前
JVM 线上排查实战(七):jps 看不见它、jstack 连不上它,可它明明活得好好的
java·jvm
狼爷5 小时前
Rust/Go/Java/Python/PHP 大比拼:负载下后端框架到底差多少?
java·后端·编程语言