OpenCV4.9更多形态转换

返回:OpenCV系列文章目录(持续更新中......)

上一篇:OpenCV4.9处理平滑图像

下一篇:OpenCV4.9更多形态转换

基于这两者,我们可以对图像进行更复杂的转换。在这里,我们简要讨论 OpenCV 提供的 5 个操作:

开放

它是通过图像的侵蚀和扩张获得的。

  • 可用于删除小物体(假设物体在深色前景上是明亮的)
  • 例如,请查看下面的示例。左边的图像是原始图像,右边的图像是应用开始变换后的结果。我们可以观察到小点已经消失了。

关闭

它是通过图像的扩张和侵蚀获得的。

  • 可用于去除小孔(黑暗区域)。

形态梯度

  • 它是图像的膨胀和侵蚀之间的区别。

  • 它对于查找对象的轮廓很有用,如下所示:

高顶丝质礼帽

它是输入图像与其开口之间的差异。

黑帽

这是关闭图像与其输入图像之间的差异

   

代码:
 

本教程的代码如下所示。您也可以在此处下载

C++

#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>using namespace cv;Mat src, dst;int morph_elem = 0;
int morph_size = 0;
int morph_operator = 0;
int const max_operator = 4;
int const max_elem = 2;
int const max_kernel_size = 21;const char* window_name = "Morphology Transformations Demo";void Morphology_Operations( int, void* );int main( int argc, char** argv )
{CommandLineParser parser( argc, argv, "{@input | baboon.jpg | input image}" );src = imread( samples::findFile( parser.get<String>( "@input" ) ), IMREAD_COLOR );if (src.empty()){std::cout << "Could not open or find the image!\n" << std::endl;std::cout << "Usage: " << argv[0] << " <Input image>" << std::endl;return EXIT_FAILURE;}namedWindow( window_name, WINDOW_AUTOSIZE ); // Create windowcreateTrackbar("Operator:\n 0: Opening - 1: Closing \n 2: Gradient - 3: Top Hat \n 4: Black Hat", window_name, &morph_operator, max_operator, Morphology_Operations );createTrackbar( "Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name,&morph_elem, max_elem,Morphology_Operations );createTrackbar( "Kernel size:\n 2n +1", window_name,&morph_size, max_kernel_size,Morphology_Operations );Morphology_Operations( 0, 0 );waitKey(0);return 0;
}void Morphology_Operations( int, void* )
{// Since MORPH_X : 2,3,4,5 and 6int operation = morph_operator + 2;Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );morphologyEx( src, dst, operation, element );imshow( window_name, dst );
}

Java:

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Size;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;public class MorphologyDemo2 {private static final String[] MORPH_OP = { "Opening", "Closing", "Gradient", "Top Hat", "Black Hat" };private static final int[] MORPH_OP_TYPE = { Imgproc.MORPH_OPEN, Imgproc.MORPH_CLOSE,Imgproc.MORPH_GRADIENT, Imgproc.MORPH_TOPHAT, Imgproc.MORPH_BLACKHAT };private static final String[] ELEMENT_TYPE = { "Rectangle", "Cross", "Ellipse" };private static final int MAX_KERNEL_SIZE = 21;private Mat matImgSrc;private Mat matImgDst = new Mat();private int morphOpType = Imgproc.MORPH_OPEN;private int elementType = Imgproc.CV_SHAPE_RECT;private int kernelSize = 0;private JFrame frame;private JLabel imgLabel;public MorphologyDemo2(String[] args) {String imagePath = args.length > 0 ? args[0] : "../data/LinuxLogo.jpg";matImgSrc = Imgcodecs.imread(imagePath);if (matImgSrc.empty()) {System.out.println("Empty image: " + imagePath);System.exit(0);}// Create and set up the window.frame = new JFrame("Morphology Transformations demo");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// Set up the content pane.Image img = HighGui.toBufferedImage(matImgSrc);addComponentsToPane(frame.getContentPane(), img);// Use the content pane's default BorderLayout. No need for// setLayout(new BorderLayout());// Display the window.frame.pack();frame.setVisible(true);}private void addComponentsToPane(Container pane, Image img) {if (!(pane.getLayout() instanceof BorderLayout)) {pane.add(new JLabel("Container doesn't use BorderLayout!"));return;}JPanel sliderPanel = new JPanel();sliderPanel.setLayout(new BoxLayout(sliderPanel, BoxLayout.PAGE_AXIS));JComboBox<String> morphOpBox = new JComboBox<>(MORPH_OP);morphOpBox.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {@SuppressWarnings("unchecked")JComboBox<String> cb = (JComboBox<String>)e.getSource();morphOpType = MORPH_OP_TYPE[cb.getSelectedIndex()];update();}});sliderPanel.add(morphOpBox);JComboBox<String> elementTypeBox = new JComboBox<>(ELEMENT_TYPE);elementTypeBox.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {@SuppressWarnings("unchecked")JComboBox<String> cb = (JComboBox<String>)e.getSource();if (cb.getSelectedIndex() == 0) {elementType = Imgproc.CV_SHAPE_RECT;} else if (cb.getSelectedIndex() == 1) {elementType = Imgproc.CV_SHAPE_CROSS;} else if (cb.getSelectedIndex() == 2) {elementType = Imgproc.CV_SHAPE_ELLIPSE;}update();}});sliderPanel.add(elementTypeBox);sliderPanel.add(new JLabel("Kernel size: 2n + 1"));JSlider slider = new JSlider(0, MAX_KERNEL_SIZE, 0);slider.setMajorTickSpacing(5);slider.setMinorTickSpacing(5);slider.setPaintTicks(true);slider.setPaintLabels(true);slider.addChangeListener(new ChangeListener() {@Overridepublic void stateChanged(ChangeEvent e) {JSlider source = (JSlider) e.getSource();kernelSize = source.getValue();update();}});sliderPanel.add(slider);pane.add(sliderPanel, BorderLayout.PAGE_START);imgLabel = new JLabel(new ImageIcon(img));pane.add(imgLabel, BorderLayout.CENTER);}private void update() {Mat element = Imgproc.getStructuringElement(elementType, new Size(2 * kernelSize + 1, 2 * kernelSize + 1),new Point(kernelSize, kernelSize));Imgproc.morphologyEx(matImgSrc, matImgDst, morphOpType, element);Image img = HighGui.toBufferedImage(matImgDst);imgLabel.setIcon(new ImageIcon(img));frame.repaint();}public static void main(String[] args) {// Load the native OpenCV librarySystem.loadLibrary(Core.NATIVE_LIBRARY_NAME);// Schedule a job for the event dispatch thread:// creating and showing this application's GUI.javax.swing.SwingUtilities.invokeLater(new Runnable() {@Overridepublic void run() {new MorphologyDemo2(args);}});}
}

Python:

from __future__ import print_function
import cv2 as cv
import numpy as np
import argparsemorph_size = 0
max_operator = 4
max_elem = 2
max_kernel_size = 21
title_trackbar_operator_type = 'Operator:\n 0: Opening - 1: Closing \n 2: Gradient - 3: Top Hat \n 4: Black Hat'
title_trackbar_element_type = 'Element:\n 0: Rect - 1: Cross - 2: Ellipse'
title_trackbar_kernel_size = 'Kernel size:\n 2n + 1'
title_window = 'Morphology Transformations Demo'
morph_op_dic = {0: cv.MORPH_OPEN, 1: cv.MORPH_CLOSE, 2: cv.MORPH_GRADIENT, 3: cv.MORPH_TOPHAT, 4: cv.MORPH_BLACKHAT}def morphology_operations(val):morph_operator = cv.getTrackbarPos(title_trackbar_operator_type, title_window)morph_size = cv.getTrackbarPos(title_trackbar_kernel_size, title_window)morph_elem = 0val_type = cv.getTrackbarPos(title_trackbar_element_type, title_window)if val_type == 0:morph_elem = cv.MORPH_RECTelif val_type == 1:morph_elem = cv.MORPH_CROSSelif val_type == 2:morph_elem = cv.MORPH_ELLIPSEelement = cv.getStructuringElement(morph_elem, (2*morph_size + 1, 2*morph_size+1), (morph_size, morph_size))operation = morph_op_dic[morph_operator]dst = cv.morphologyEx(src, operation, element)cv.imshow(title_window, dst)parser = argparse.ArgumentParser(description='Code for More Morphology Transformations tutorial.')
parser.add_argument('--input', help='Path to input image.', default='LinuxLogo.jpg')
args = parser.parse_args()src = cv.imread(cv.samples.findFile(args.input))
if src is None:print('Could not open or find the image: ', args.input)exit(0)cv.namedWindow(title_window)
cv.createTrackbar(title_trackbar_operator_type, title_window , 0, max_operator, morphology_operations)
cv.createTrackbar(title_trackbar_element_type, title_window , 0, max_elem, morphology_operations)
cv.createTrackbar(title_trackbar_kernel_size, title_window , 0, max_kernel_size, morphology_operations)morphology_operations(0)
cv.waitKey()

解释

让我们检查一下 C++ 程序的一般结构:

 createTrackbar("Operator:\n 0: Opening - 1: Closing \n 2: Gradient - 3: Top Hat \n 4: Black Hat", window_name, &morph_operator, max_operator, Morphology_Operations );

如您所见,值范围为 <2-6>,这就是为什么我们在 Trackbar 输入的值中添加 (+2) 的原因: 

 int operation = morph_operator + 2;

  element:要使用的内核。我们使用函数 cv::getStructuringElement 来定义我们自己的结构。


  • 返回:OpenCV系列文章目录(持续更新中......)

  • 上一篇:OpenCV4.9侵蚀和扩张

    下一篇:OpenCV系列文章目录(持续更新中......)

    目标

    在本教程中,您将学习如何:

  • 使用 OpenCV 函数 cv::morphologyEx 应用形态转换,例如:
    • 开放
    • 关闭
    • 形态梯度
    • 高顶丝质礼帽
    • 黑帽
  • 理论

    注意

    下面的解释属于 Bradski 和 Kaehler 的 Learning OpenCV 一书。

    在上一教程中,我们介绍了两个基本的形态操作:

  • 侵蚀
  • 扩张。
  • 它是通过图像的侵蚀和扩张获得的。

      

  • 可用于删除小物体(假设物体在深色前景上是明亮的)
  • 例如,请查看下面的示例。左边的图像是原始图像,右边的图像是应用开始变换后的结果。我们可以观察到小点已经消失了。
  • 它是通过图像的扩张和侵蚀获得的。

  •   

  • 可用于去除小孔(黑暗区域)。
  • 它是图像的膨胀和侵蚀之间的区别。

  •   

  • 它对于查找对象的轮廓很有用,如下所示:
  • 它是输入图像与其开口之间的差异。

  •   

  • 这是关闭图像与其输入图像之间的差异

  • 加载图像
  • 创建一个窗口以显示形态操作的结果
  • 创建三个跟踪栏供用户输入参数:
    • 第一个跟踪栏运算符返回要使用的形态操作类型 (morph_operator
  •  

     第二个 trackbar Element 返回 morph_elem,它表示我们的内核是什么样的结构

     createTrackbar( "Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name,&morph_elem, max_elem,Morphology_Operations );

    最终的跟踪栏 Kernel Size 返回要使用的内核大小 (morph_size)

     createTrackbar( "Kernel size:\n 2n +1", window_name,&morph_size, max_kernel_size,Morphology_Operations );

     每次我们移动任何滑块时,都会调用用户的函数Morphology_Operations来执行新的形态操作,并且它将根据当前的跟踪栏值更新输出图像。

     
    void Morphology_Operations( int, void* )
    {// Since MORPH_X : 2,3,4,5 and 6int operation = morph_operator + 2;Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );morphologyEx( src, dst, operation, element );imshow( window_name, dst );
    }

    我们可以观察到,执行形态变换的关键函数是 cv::morphologyEx 。在此示例中,我们使用四个参数(其余参数保留为默认值):

  • src : 源(输入)图像
  • dst:输出图像
  • operation:要执行的形态转换类型。请注意,我们有 5 种替代方案:

  • 开幕: MORPH_OPEN : 2
  • 结束语: MORPH_CLOSE: 3
  • 梯度:MORPH_GRADIENT:4
  • 礼帽:MORPH_TOPHAT:5
  • 黑帽:MORPH_BLACKHAT:6
  •  

    结果

  • 编译上面的代码后,我们可以执行它,给出一个图像路径作为参数。使用图像的结果:baboon.png
  • 这是显示窗口的两个快照。第一张图片显示了使用带有交叉内核的运算符 Opening 后的输出。第二张图片(右侧)显示了使用带有椭圆内核的 Blackhat 运算符的结果。

参考文献:

1、《More Morphology Transformations》 ----Ana Huamán

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

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

相关文章

FreeBuf 全球网络安全产业投融资观察(3月)

综述 据不完全统计&#xff0c;2024年3月&#xff0c;全球网络安全市场共发生投融资事件53起&#xff0c;其中国内4起&#xff0c;国外49起。 3月全球络安全产业投融资统计表&#xff08;数据来源&#xff1a;航行资本、36氪&#xff09; 整体而言&#xff0c;国内4起投融资事…

EasyExcel中对图片大小及位置进行调整(自定义拦截器)

如何对我们导出的图片设置大小和位置 首先我们先丢入一张图片,这里我就直接通过URL的形式进行编写 定义一个存储图片的类 import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter;import java.net.URL;Getter Setter EqualsAndHashCode public class…

AI写作软件哪个好?这4款好评如潮

在信息时代&#xff0c;AI技术的发展的日新月异&#xff0c;AI写作软件也因此诞生。特别是人们对于高效、便捷的写作工具需求日益增长&#xff0c;AI写作软件作为一种新兴的工具&#xff0c;在帮助人们提升写作效率、拓展创作思路方面发挥着越来越重要的作用。这些AI写作软件为…

C语言 函数——代码风格

目录 基本的代码规范 程序版式 对齐&#xff08;Alignment&#xff09;与缩进&#xff08;indent&#xff09; 变量的对齐规则 空行——分隔程序段落的作用 代码行内的空格——增强单行清晰度 代码行 长行拆分 标识符命名规则 标识符命名的共性规则 windows应用程序…

PostgreSQL入门到实战-第十八弹

PostgreSQL入门到实战 PostgreSQL中表连接操作(二)官网地址PostgreSQL概述PostgreSQL中表别名命令理论PostgreSQL中表别名命令实战更新计划 PostgreSQL中表连接操作(二) 了解PostgreSQL表别名及其实际应用程序。 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容…

19c数据库/dev/shm/过小导致pga内存不够

pga_aggregate_limit已经设置了120G&#xff0c;alert还是报内存不够 查询select * from v$pgastat&#xff0c;发现MGA占了80G内存 查看/dev/shm: 发现设置了7G&#xff0c;操作系统是512G&#xff0c;正常情况下/dev/shm应该是操作系统的一半&#xff0c;修改为250G后数据库…

微信小程序 django+nodejs电影院票务售票选座系统324kd

小程序Android端运行软件 微信开发者工具/hbuiderx uni-app框架&#xff1a;使用Vue.js开发跨平台应用的前端框架&#xff0c;编写一套代码&#xff0c;可编译到Android、小程序等平台。 前端&#xff1a;HTML5,CSS3 VUE 后端&#xff1a;java(springbootssm)/python(flaskdja…

vue3:菜单、标签页和面包屑联动效果

文章目录 1.整体思路2.实现过程 概要 提示&#xff1a;这里可以添加技术概要 例如&#xff1a; openAI 的 GPT 大模型的发展历程。 1.整体思路 在之前做的后台项目中&#xff0c;菜单、标签页和面包屑之间的联动&#xff0c;自己都是通过在路由前置守卫中&#xff0c;定义b…

微服务面试题二

1.什么是雪崩 微服务之间相互调用&#xff0c;因为调用链中的一个服务故障&#xff0c;引起整个链路都无法访问的情况。 如何解决雪崩&#xff1f; 超时处理&#xff1a;请求超时就返回错误信息&#xff0c;不会无休止等待仓壁模式&#xff1a;限定每个业务能使用的线程数&a…

WPS的JS宏如何批量实现文字的超链接

表格中需要对文字进行超链接&#xff0c;每个链接指引到不同的地址。例如&#xff1a; 实现如下表格中&#xff0c;文件名称超级链接到对应的文件路径上&#xff0c;点击对应的文件名称&#xff0c;即可打开对应的文件。 序号文件名称文件路径1变更申请与处理表.xls文档\系统…

$(obj)/%.bin: $(obj)/*

$(obj)/%.bin: $(obj)/*.bin 是一个Makefile规则&#xff0c;用于指定如何生成.bin文件。这里解释一下这个规则的各个部分&#xff1a; $(obj)/%.bin 是目标文件的模式。%代表任意长度的字符串&#xff0c;$(obj)是一个变量&#xff0c;通常用来表示对象文件的输出目录。例如&a…

第十三届蓝桥杯省赛大学B组编程题(c++)

D.刷题统计 二分(AC): 注意:二分时右边界 right 的确定 #include<iostream> using namespace std; long long a,b,n; bool check(long long x){long long tx/7;x%7;long long temp0;if(x<5) tempx*a;else temp5*a(x-5)*b;long long cntt*(5*a2*b)temp;return cnt&g…

MySOL之旅--------MySQL数据库基础( 2 )

本篇碎碎念:尽自己最大的努力,直到筋疲力尽为止,加油 今日份励志文案: 别人都在前进,我为什么要停下 目录 补上一条博客缺失的内容 常用数据类型 数值类型&#xff1a; 字符串类型&#xff1a; 日期/时间类型&#xff1a; 二进制类型&#xff1a; 其他类型&#xff1a; …

抖音小店入驻有什么条件?资金少,没经验的普通人做得起吗?

大家好&#xff0c;我是电商花花。 在直播电商的推动下&#xff0c;抖音小店独特的电商模式下吸引着众多的商家&#xff0c;吸引着一波又一波的创业者入驻&#xff0c;想要在抖音小店上开垦出属于自己的电商净土。 想要入驻抖音小店还需要一些条件&#xff0c;然后才能入驻成…

Python机器学习学习线路

随着人工智能技术的飞速发展&#xff0c;机器学习已经成为计算机科学领域的热门话题。Python&#xff0c;作为一门功能强大且易于上手的编程语言&#xff0c;成为学习机器学习的理想选择。本文将为您介绍一条Python机器学习的学习线路&#xff0c;帮助您逐步掌握机器学习的基础…

题目 3038: 马走日

题目描述: 马在中国象棋以日字形规则移动。 请编写一段程序&#xff0c;给定nm大小的棋盘&#xff0c;以及马的初始位置(x&#xff0c;y)&#xff0c;要求不能重复经过棋盘上的同一个点&#xff0c;计算马可以有多少途径遍历棋盘上的所有点。 代码: package lanqiao;import …

ARM/X86+FPGA轨道交通/工程车辆行业的解决方案

深圳推出首条无人驾驶地铁—深圳地铁20号线&#xff0c;可以说是深圳地铁的一次开创性的突破。智能交通不断突破的背后&#xff0c;需要很严格的硬件软件等控制系 统&#xff1b;地铁无人驾驶意味着信号系统、通信系统、综合监控系统、站台屏蔽门工程等项目必须严格执行验收。…

Vue3项目搭建及文件结构

一. Vue3项目搭建 # 安装Vue CLI npm install -g vue/cli# 通过Vue CLI创建项目&#xff1a; vue create my-vue3-project# 当问到你想要使用哪个版本的Vue时&#xff0c;选择Vue3 # 完成配置后&#xff0c;CLI会自动安装依赖并创建项目 # 最后&#xff0c;启动你的Vue3项目cd…

C++:弃值表达式

正文 有时候需要利用某些表达式的副作用来实现某些目的&#xff1a; #include <iostream> template <typename... Args> void print(const Args &...args) {Arr{0,(std::cout << args<< ,0)...}; } int main() {print("hello", 1, 2,…

2024.03.31 校招 实习 内推 面经

绿*泡*泡VX&#xff1a; neituijunsir 交流*裙 &#xff0c;内推/实习/校招汇总表格 1、自动驾驶一周资讯 -小米SU7上市24小时&#xff0c;大定达88898台&#xff1b;小鹏汽车正式进入德国市场&#xff1b;地平线递交港股上市申请 自动驾驶一周资讯 -小米SU7上市24小时&…