天天看点

opencv 边缘检测_opencv边缘检测

opencv边缘检测

本文目的

目的:学习使用opencv的边缘检测工具

语言:java

版本:opencv-410

简介:主要介绍使用边缘检测工具来处理一件衣服,允许用户调整边缘检测阈值,滤波内核大小来观察边缘识别效果

分解介绍

主要函数

Imgproc.Canny(Mat image, Mat edges, double lowThreshold, double highThreshold, int apertureSize, boolean L2gradient)
           

参数说明

  • · gray:原图像,需是灰度图像
  • · detectedEdges:检测器的输出的边缘图像
  • · lowThreshold:下限阈值,如果像素梯度低于下限阈值,则将像素不被认为边缘
  • · highThreshold:上限阈值,如果像素梯度高于上限阈值,则将像素被认为是边缘(建议上限是下限的2倍或者3倍)
  • · apertureSize:内部使用的Sobel内核的大小
  • · L2gradient:计算图像梯度幅值的标志,默认值为false

操作步骤

1.灰度变换

Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
           

2.滤波处理

这里采用中值波模糊

Imgproc.medianBlur(gray, gray,medianBlur_kenelSize % 2 == 1? medianBlur_kenelSize: medianBlur_kenelSize + 1);
           

3.边缘检测

Imgproc.Canny(gray, detectedEdges, lowThresh, lowThresh * RATIO, KERNEL_SIZE, false);
           

4.边缘检测结果和灰度图片合并

dst = new Mat(gray.size(), CvType.CV_8UC3, Scalar.all(0));gray.copyTo(dst, detectedEdges);
           

5.输出到程序窗口

Image img = HighGui.toBufferedImage(dst);imgLabel.setIcon(new ImageIcon(img));
           

代码

package com.joe.vision.machine.vision.samples;import org.opencv.core.Point;import org.opencv.core.*;import org.opencv.highgui.HighGui;import org.opencv.imgcodecs.Imgcodecs;import org.opencv.imgproc.Imgproc;import javax.swing.*;import javax.swing.event.ChangeEvent;import javax.swing.event.ChangeListener;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.FileNotFoundException;public class CannyTest {private static final int MAX_LOW_THRESHOLD = 100;private static final int RATIO = 3;private static final int KERNEL_SIZE = 3;private static final Size BLUR_SIZE = new Size(3, 3);private static int medianBlur_kenelSize = 1;private int lowThresh = 0;private Mat src;private Mat detectedEdges = new Mat();private Mat dst = new Mat();private Mat gray = new Mat();private JFrame frame;private JLabel imgLabel;private boolean iscloseOp = false;private boolean isInit = true;public CannyTest(String[] args) throws FileNotFoundException {String imagePath = FileLoadUtils.getFilePath("static/ppp.png");src = Imgcodecs.imread(imagePath);//图片太大,进行缩放Imgproc.resize(src, src, new Size(src.width() / 2, src.height() / 2));if (src.empty()) {System.out.println("Empty image: " + imagePath);System.exit(0);}// Create and set up the window.frame = new JFrame("Edge Map (Canny detector demo)");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// Set up the content pane.Image img = HighGui.toBufferedImage(src);addComponentsToPane(frame.getContentPane(), img);frame.pack();frame.setVisible(true);}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() {try {new CannyTest(args);} catch (FileNotFoundException e) {e.printStackTrace();}}});}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));sliderPanel.add(new JLabel("下限阈值"));JSlider slider = buildSlider();JSlider kenelSizeslider = buildKenelSlider();sliderPanel.add(slider);sliderPanel.add(new JLabel("滤波内核大小"));sliderPanel.add(kenelSizeslider);JButton button = buildCloseOp();sliderPanel.add(button);pane.add(sliderPanel, BorderLayout.PAGE_START);imgLabel = new JLabel(new ImageIcon(img));pane.add(imgLabel, BorderLayout.CENTER);}private JButton buildCloseOp() {JButton button = new JButton("闭运算-先膨胀再腐蚀");button.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {iscloseOp = true;update();}});return button;}private JSlider buildSlider() {JSlider slider = new JSlider(0, MAX_LOW_THRESHOLD, 0);slider.setMajorTickSpacing(10);slider.setMinorTickSpacing(5);slider.setPaintTicks(true);slider.setPaintLabels(true);slider.addChangeListener(new ChangeListener() {@Overridepublic void stateChanged(ChangeEvent e) {JSlider source = (JSlider) e.getSource();lowThresh = source.getValue();update();}});return slider;}private JSlider buildKenelSlider() {JSlider slider = new JSlider(0, MAX_LOW_THRESHOLD, 0);slider.setMajorTickSpacing(10);slider.setMinorTickSpacing(5);slider.setPaintTicks(true);slider.setPaintLabels(true);slider.addChangeListener(new ChangeListener() {@Overridepublic void stateChanged(ChangeEvent e) {JSlider source = (JSlider) e.getSource();medianBlur_kenelSize = source.getValue();update();}});return slider;}private void update() {if (isInit) {//灰度变换Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);}//滤波处理Imgproc.medianBlur(gray, gray, medianBlur_kenelSize % 2 == 1 ? medianBlur_kenelSize : medianBlur_kenelSize + 1);//边缘检测Imgproc.Canny(gray, detectedEdges, lowThresh, lowThresh * RATIO, KERNEL_SIZE, false);dst = new Mat(gray.size(), CvType.CV_8UC3, Scalar.all(0));//图像合并gray.copyTo(dst, detectedEdges);//闭运算if (iscloseOp) {Mat element = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_RECT, new Size(2 * 5 + 1, 2 * 5 + 1), new Point(5, 5));Imgproc.morphologyEx(dst, dst, Imgproc.MORPH_CLOSE, element);iscloseOp = false;}gray = dst;Image img = HighGui.toBufferedImage(dst);imgLabel.setIcon(new ImageIcon(img));frame.repaint();}}
           

效果

原图

opencv 边缘检测_opencv边缘检测

不断改变阈值以及滤波的效果

opencv 边缘检测_opencv边缘检测
opencv 边缘检测_opencv边缘检测