opencv更多圖形變換

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")

閉運算圖-原圖像,突出原圖像中比周圍暗的區域


代碼

<code>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<string> morphOpBox = buildOpBox(); //構造處理的元素類型 JComboBox<string> 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<string> buildOpBox() { JComboBox<string> morphOpBox = new JComboBox<>(MORPH_OP); morphOpBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @SuppressWarnings("unchecked") JComboBox<string> cb = (JComboBox<string>)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<string> buildElementType() { JComboBox<string> elementTypeBox = new JComboBox<>(ELEMENT_TYPE); elementTypeBox.addActionListener(new ActionListener() { @Override public 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(); } }); 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(); } } }); }}/<string>/<string>/<string>/<string>/<string>/<string>/<string>/<string>/<string>/<string>/<code>


效果圖

本程序原圖:


開運算結果:是不是放大了低亮度區域


閉運算結果:是不是消除了部分小黑點


形態學變換後效果:


頂帽操作效果:原圖-開運算結果


黑帽操作效果:閉運算圖-原圖像