opencv更多图形变换
本文目的
目的:学习使用opencv的更多图形变化操作
语言:java
版本:opencv-410
简介:使用morphologyEx(Mat src, Mat dst, int op, Mat kernel)进行更多图像变换
分解介绍
· MORPH_OPEN – 开运算(Opening operation)
先腐蚀,再膨胀,可清除一些小东西(亮的),放大局部低亮度的区域
效果如下:左侧的小亮点,通过开运算后就消除掉了

· MORPH_CLOSE – 闭运算(Closing operation)
先膨胀,再腐蚀,可清除小黑点
效果如下:左侧的小黑点,通过闭运算后就消除掉了

· MORPH_GRADIENT -形态学梯度(Morphological gradient)
膨胀图与腐蚀图之差,提取物体边缘
· MORPH_TOPHAT - "顶帽"("Top hat")
原图像-开运算图,突出原图像中比周围亮的区域
· MORPH_BLACKHAT - "黑帽"("Black hat")
闭运算图-原图像,突出原图像中比周围暗的区域
代码
package com.joe.vision.machine.vision.samples;import java.awt.BorderLayout;import java.awt.Container;import java.awt.Image;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.File;import java.io.FileNotFoundException;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;import org.springframework.util.ResourceUtils;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) throws FileNotFoundException { String imagePath = getFilePath("static/time.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 morphOpBox = buildOpBox(); //构造处理的元素类型 JComboBox elementTypeBox = buildElementType(); //构造滑动工具条 JSlider slider = buildSlider(); sliderPanel.add(morphOpBox); sliderPanel.add(elementTypeBox); sliderPanel.add(new JLabel("内核尺寸: 2n + 1")); sliderPanel.add(slider); pane.add(sliderPanel, BorderLayout.PAGE_START); imgLabel = new JLabel(new ImageIcon(img)); pane.add(imgLabel, BorderLayout.CENTER); } private JComboBox buildOpBox() { JComboBox morphOpBox = new JComboBox<>(MORPH_OP); morphOpBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @SuppressWarnings("unchecked") JComboBox cb = (JComboBox)e.getSource(); morphOpType = MORPH_OP_TYPE[cb.getSelectedIndex()]; update(); } }); return morphOpBox; } private JSlider buildSlider() { 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() { @Override public void stateChanged(ChangeEvent e) { JSlider source = (JSlider) e.getSource(); kernelSize = source.getValue(); update(); } }); return slider; } private JComboBox buildElementType() { JComboBox elementTypeBox = new JComboBox<>(ELEMENT_TYPE); elementTypeBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @SuppressWarnings("unchecked") JComboBox cb = (JComboBox)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(); } }); return elementTypeBox; } 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 String getFilePath(String filename) throws FileNotFoundException { File file = ResourceUtils.getFile(filename); return file.getAbsolutePath(); } public static void main(String[] args) { // Load the native OpenCV library System.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() { @Override public void run() { try { new MorphologyDemo2(args); } catch (FileNotFoundException e) { e.printStackTrace(); } } }); }}
效果图
本程序原图:

开运算结果:是不是放大了低亮度区域

闭运算结果:是不是消除了部分小黑点

形态学变换后效果:

顶帽操作效果:原图-开运算结果

黑帽操作效果:闭运算图-原图像

