Android OpenCV(二)主体识别 位置检测

news2024/11/14 15:40:05

前言

  工作中遇到需要通过OpenCV找到图片主体体积占图片百分比的比例,这里做一个问题解决思路的记录。该方面新手小白,有不对的地方可以评论指出哈 。

重要API

Sobel算法

Sobel 计算参考文章

索贝尔算子是计算机视觉领域的一种重要处理方法。
主要用于获得数字图像的一阶梯度,常见的应用和物理意义是边缘检测。
索贝尔算子是把图像中每个像素的上下左右四领域的灰度值加权差,在边缘处达到极值从而检测边缘。在技术上,它是一离散性差分算子,用来运算图像亮度函数的梯度之近似值。在图像的任何一点使用此算子,将会产生对应的梯度矢量或是其法矢量。索贝尔算子不但产生较好的检测效果,而且对噪声具有平滑抑制作用,但是得到的边缘较粗,且可能出现伪边缘。
该算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以A代表原始图像,Gx及Gy分别代表经横向及纵向边缘检测的图像,其公式如下:
image.png
图像的每一个像素的横向及纵向梯度近似值可用以下的公式结合,来计算梯度的大小。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nJRhDdGQ-1674892594274)(https://upload-images.jianshu.io/upload_images/6188347-f1dde384106a4b75.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/124)]
然后可用以下公式计算梯度方向。 image.png
在以上例子中,如果以上的角度θ等于零,即代表图像该处拥有纵向边缘,左方较右方暗 【引用:百度百科】

//src : 输入图像  dst: 输出图像
//ddepth: 输出图像的深度(可以理解为数据类型),-1表示与原图像相同的深度
//dx:  dy: 当组合为dx=1,dy=0时求x方向的一阶导数,当组合为dx=0,dy=1时求y方向的一阶导数
//ksize: (可选参数)Sobel算子的大小,必须是1,3,5或者7,默认为3。
//scale: 对导数计算结果进行缩放的缩放因子,默认系数为1,不进行缩放
//delta: 偏值,在计算结果中加上偏值。
//borderType: 像素外推法选择标志。默认参数为BORDER_DEFAULT,表示不包含边界值倒序填充。
public static void Sobel(Mat src, Mat dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType) 
  • 注意点
  1. 图像深度是指存储每个像素值所用的位数,例如cv2.CV_8U,指的是8位无符号数,取值范围为0~255,超出范围则会被截断(截断指的是,当数值大于255保留为255,当数值小于0保留为0,其余不变)。
      具体还有:CV_16S(16位无符号数),CV_16U(16位有符号数),CV_32F(32位浮点数),CV_64F(64位浮点数)
      当ddepth 输出图像深度采用CV_8U,由于Sobel算子在计算X方向梯度时,如果某像素点右侧像素值大于左侧像素值,则梯度大小为正保留,相反梯度大小为负被截断,梯度大小保存为0。这里可以使用 CV_32F 防止数据存在负数情况。

  2. 在我们使用CV_32F数据类型求出XY阶后,需要配合使用函数convertScaleAbs()将图像深度为CV_64F的梯度图像重新转化为CV_8U,这是由于函数cv2.imshow()的默认显示为8位无符号数,即[0,255]。

具体思路

  第一步,使用OpenCV的 Sobel算子来计算x,y方向上的梯度,在x方向上减去y方向上的梯度,通过这个减法,我们会留下有高水平梯度和低垂直梯度的图像区域。

        Mat gradX = new Mat();
        Mat gradY = new Mat();
        Mat binary = new Mat();
        //求X Y 阶 转换为32位浮点数个数
        Imgproc.Sobel(grayImage, gradX, CvType.CV_32F, 1, 0, -1);
        Imgproc.Sobel(grayImage, gradY, CvType.CV_32F, 0, 1, -1);
        //相减
        Core.subtract(gradX, gradY, binary);
        //转换数据格式CV_8U
        Core.convertScaleAbs(binary, binary);

以上步骤我们可以得到一个带有很多噪点的边界图,为了剔除掉那些噪点对于主体的判断,我们需要使用 blur 方法 和黑白两极化对图片进行处理

  第二步,使用低通滤泼器平滑图像(9 x 9内核),这将有助于平滑图像中的高频噪声。低通滤波器的目标是降低图像的变化率。如将每个像素替换为该像素周围像素的均值。这样就可以平滑并替代那些强度变化明显的区域。

//去噪
Imgproc.blur(binary, binary, new Size(9.0, 9.0));
//对模糊图像二值化。梯度图像中不大于90的任何像素都设置为0(黑色)。 否则,像素设置为255(白色)为第五步做准备工作
Imgproc.threshold(binary, binary, 90.0, 255.0, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);

  第三步,通过上述方法可以得到一个黑白图,但是图片中可能会存在很多空白空隙, 我们要用白色填充这些空余,使得后面的程序更容易识别昆虫区域,这需要做一些形态学方面的操作。

//为形态学操作返回指定大小和形状的结构元素 用于形态学处理
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(25.0, 25.0));
// 使用腐蚀和膨胀作为基本操作来执行高级形态学转换
Imgproc.morphologyEx(binary,binary,Imgproc.MORPH_CLOSE,kernel);

  第四步, 通过上述处理,可能还会存在一些 大的噪点, 可以通过形态学腐化和膨胀进行消除

Point p = new Point(-1.0, -1.0);
Imgproc.erode(binary, binary, ker, p, 4);
Imgproc.dilate(binary, binary, ker, p, 4);

  第五步,通过 findContours()函数框选出主体的位置信息

List<MatOfPoint> contours = new ArrayList<>();
Mat hierarchy = new Mat();
// binary : 要检索的图片,必须是为二值图,即黑白的
//hierarchy : 结果返回值
Imgproc.findContours(binary,contours,hierarchy,
                Imgproc.RETR_EXTERNAL,Imgproc.CHAIN_APPROX_SIMPLE);

findContours 函数 最后两个参数,mode 和 method 单独拿出来列举下 不同的参数代表的含义
mode
Imgproc.RETR_EXTERNAL 表示只检测外轮廓
Imgproc.RETR_LIST 检测的轮廓不建立等级关系
Imgproc.RETR_CCOMP 建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
Imgproc.RETR_TREE 建立一个等级树结构的轮廓。

method
Imgproc.CHAIN_APPROX_NONE 存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
Imgproc.CHAIN_APPROX_SIMPLE 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息

  结果都存储在 contours 数组中,我们可以使用他进行一些业务判断。
  由于脱敏原因,这里没有demo图片,该篇文章 主要参考文章对我的帮助非常大,小白这里只是做一个开发记录,今天的这篇文章就到这里。

参考文章

识别颜色方块并提取轮廓

OpenCV自动检测图像中的物体并裁剪

Sobel()计算图像梯度的细节讲解

OpenCV API官网地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/182351.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

内网传输——解决物联网信息安全和隐私保护问题

与普通电脑系统不同&#xff0c;物联网建立在嵌入式系统的基础之上&#xff0c;其通信协议因设备和应用程序而异。目前还没有一个统一的中央系统来构建安全措施&#xff0c;那么&#xff0c;在企业物联网实际应用中&#xff0c;如何保证信息安全&#xff1f;物联网生态系统的安…

OpenHarmony社区运营报告(2022年12月)

本月快讯• 本月新增22款产品通过兼容性测评&#xff0c;累计220款产品通过兼容性测评。• 12月28日&#xff0c;OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;凭借其创新的技术特性和开源生态建设成果&#xff0c;荣膺“InfoQ 2022年度十大开源新锐项…

Redis实现用户签到 | 黑马点评

目录 一、BitMap用法 1、介绍 2、用法 3、练习 二、签到功能 1、需求 2、代码实现 三、签到统计 1、分析 2、接口实现 一、BitMap用法 1、介绍 我们完全可以通过数据库签到表来实现签到功能&#xff0c;但是假如我们的用户达到千万&#xff0c;每年平均签到10次&am…

基于微信小程序的网络安全科普系统小程序

文末联系获取源码 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.…

设计模式之简单工厂

现在有一个这样的需求&#xff1a;控制台输入俩个数&#xff0c;并输入运算符&#xff0c;计算并输出结果。上述需求乍一看&#xff0c;特别像一个小型的计算器&#xff0c;记得初学Java时&#xff0c;实现过。 实现一&#xff1a; 创建计算器类&#xff0c;控制台输入俩个数…

windows 10 本地配置Oracle19+用navicat连接

文章目录0.背景环境0.背景知识1.卸载旧版本、安装 oracle 192.配置3.用 Navicat 连接3.1 下载instantclient193.2 配置dll使能连接高版本oracle3.3 配置连接4. 相关操作命令5.本地命令行登录orclpdb下的用户0.背景环境 本机已安装oracle12和Navicat15&#xff0c;需要先彻底卸载…

【docker】基础知识梳理与使用

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 docker基础知识的梳理与使用 1. docker的理解 Registry&#xff08;仓库&#xff09;&#xff1a;是一个集中存储与分发镜像的服务。最常用的Registry是…

油井远程监控解决方案

1.项目背景 油田生产过程中&#xff0c;由于井筒内存在着不同程度的缺陷&#xff0c;会产生各种问题。而油井开采设备的连续稳定运行是保证石油开采的首要条件&#xff0c;但是由于油田地域广阔&#xff0c;油井分布广泛&#xff0c;没有规则性的油井工作状况的监测和控制&…

Acwing4655. 重新排序(差分模板题)

给定一个数组 A 和一些查询 Li,Ri&#xff0c;求数组中第 Li 至第 Ri 个元素之和。 小蓝觉得这个问题很无聊&#xff0c;于是他想重新排列一下数组&#xff0c;使得最终每个查询结果的和尽可能地大。 小蓝想知道相比原数组&#xff0c;所有查询结果的总和最多可以增加多少? …

【树】二叉树的非递归遍历

非递归的遍历需要使用栈保存当前不输出的结点&#xff0c;并且三种遍历顺序步骤有所不同。中序遍历1.查看其当前结点是否为空&#xff1a;若非空则将当前结点入栈&#xff0c;指针指向其左孩子&#xff1b;若当前结点为空&#xff0c;说明上一个入栈的结点没有左孩子&#xff0…

vite+vue3+elementPlus搭建项目

创建基础框架 方式一&#xff1a; 创建命令 npm create vitelatest or yarn create vite 注意&#xff1a;这里可能会出现一个坑&#xff0c;注意你的node版本&#xff08;node版本过低就会报错&#xff09; 创建成功 创建成功后运行以下命令即可 yarn yarn dev 这种创建方…

C技能树-判断语句

三个数从小到大排序并输出 任意输入3个整数&#xff0c;使用if语句对这3个整数由小到大进行升序排序。请判断下面哪一项无法实现该功能。 #include <stdio.h>/* 交换x和y */ void swap(int* x, int* y) {int temp *x;*x *y;*y temp; }int main(int argc, char** arg…

[红明谷CTF 2021]write_shell

目录 信息收集 payload 补充知识 信息收集 代码审计 <?php error_reporting(0); highlight_file(__FILE__); function check($input){if(preg_match("/| |_|php|;|~|\\^|\\|eval|{|}/i",$input)){// if(preg_match("/| |_||php/",$input)){die(h…

(二十七)Map集合体系

目录 前言: 一、Map集合的遍历方式之一:键找值 二、Map集合的遍历方式之二:键值对 三、Map集合的遍历方式之三:Lambda表达式 四、Map集合的实现类HashMap 五、Map集合的实现类LinkedHashMap 六、Map集合的实现类TreeMap 七、不可变集合 前言: ①Map集合是一种双列集合&a…

机器学习中的聚类算法

1. 概述根据所拥有的数据&#xff0c;可以使用三种不同的机器学习方法&#xff0c;包括监督学习、半监督学习和无监督学习。在监督学习中&#xff0c;根据已标记数据&#xff0c;因此可以确定输出是关于输入的正确值。通过半监督学习&#xff0c;用户将拥有一个大型数据集&…

提高mysql性能:设计阶段

合适的表设计 基本原则 避免太多的列 太多的列会导致mysql从行缓存中将编码过的列转换为行数据时花费大量大代价。 减少太多的关联 为减少太多的关联造成解析和查询的性能影响&#xff0c;应该将单表的关联控制在12个之内。 合理使用枚举 枚举只适用于值相对固定&#x…

go入门——基础语法

go环境安装 1、安装 go官网&#xff1a;Downloads - The Go Programming Language (google.cn) go中文网&#xff1a;Go下载 - Go语言中文网 - Golang中文社区 (studygolang.com) 这里我是amd64位win10系统&#xff0c;所以我下载这个 下载完成之后安装到自己喜欢的目录就好…

Java:基于XML的Spring使用【IOC容器】

基于XML的Spring使用一、Spring IOC 底层实现1.1 BeanFactory与ApplicationContexet1.2 图解IOC类的结构二、 Spring依赖注入数值问题【重点】2.1 字面量数值2.2 CDATA区2.3 外部已声明bean及级联属性赋值2.4 内部bean2.5 集合三、 Spring依赖注入方式【基于XML】3.1 set注入3.…

电子技术——MOS管的CV特性

电子技术——MOS管的CV特性 MOS管是一种压控晶体管&#xff0c;本节我们学习MOS管的CV特性&#xff0c;即电压-电流特性。MOS管的特性曲线有两种&#xff0c;分别是伏安特性和传导特性。 iD−vDSi_D-v_{DS}iD​−vDS​ 特性曲线 为了测量MOS管的 iD−vDSi_D-v_{DS}iD​−vDS​…

ctfshow黑盒测试篇

文章目录web380web381web382web383web384web385web386web387web388web389web390web391web392web393web394、395web380 目录扫出来了page.php $id应该是传的参数&#xff0c;是php的文件名 page.php?idflag 访问源码拿到flag web381 就是这个目录 /alsckdfy/ 访问就是flag …