opencv-基本特征值检测

特征值检测

梯度计算

梯度可以反应图像的像素差异:对于图像边缘部分,梯度值会比较大;对于图像的平坦区域,梯度值比较小、OpenCv 提供了两个非常有用的计算函数Sobel与Scharr

Sobel梯度算子分为X方向与Y方向,可以分别计算X与Y方向的梯度成像

在这里插入图片描述

Sobel(Mat src,Mat dst,int ddpeth,int x,int y)

ddpeth:表示输入图像的深度,常见为CV_32SC或者CV_32F
x:x方向的梯度1为是,0为否‘
y:y方向的梯度同上

   Mat gradx = new Mat();
        Imgproc.Sobel(src, gradx, CvType.CV_32F, 1, 0);
        Core.convertScaleAbs(gradx, gradx);
        Log.i("OpenCV", "XGradient....");
        // Y方向梯度
        Mat grady = new Mat();
        Imgproc.Sobel(src, grady, CvType.CV_32F, 0, 1);
        Core.convertScaleAbs(grady, grady);
        Log.i("OpenCV", "YGradient....");

        Core.addWeighted(gradx,0.5, grady, 0.5, 0, dst);
        gradx.release();
        grady.release();
        Log.i("OpenCV", "Gradient.....");

在这里插入图片描述

Scharr梯度

Scharr梯度是sobel算子的升级加强版,只是更强的计算算子

在这里插入图片描述

Scharr(Mat src,Mat dst,int ddpeth,int x,int y)

  Mat gradx = new Mat();
        Imgproc.Scharr(src, gradx, CvType.CV_32F, 1, 0);
        Core.convertScaleAbs(gradx, gradx);

        // Y方向梯度
        Mat grady = new Mat();
        Imgproc.Scharr(src, grady, CvType.CV_32F, 0, 1);
        Core.convertScaleAbs(grady, grady);

        Core.addWeighted(gradx,0.5, grady, 0.5, 0, dst);

在这里插入图片描述

拉普拉斯算子
拉普拉斯可以增强图像,也可以用于边缘检测

      Imgproc.Laplacian(src, dst,int ddepth,int kszie,double scale,double delta);
      ddepth:图像深度,常见为CV_32fF
      kszie:3x3
      scale;是否伸缩默认为1
      delta:是否调整像素默认为0

Canny边缘检测
Canny边缘检测是对一种噪点比较敏感点边缘检测方法,通常在使用Canny边缘检测之前,首先对图像进行降噪。
完整对Canny检测步骤

  1. 高数模糊:完成噪点抑制
  2. 灰度转化:在灰度图像上计算梯度值
  3. 计算梯度:使用Sobel/Scharr
  4. 非最大信号抑制:在梯度图像上寻找局部最大值
  5. 高低阀直连接:把边缘像素连接成线段,形成完整边缘轮廓
        Imgproc.Canny(gradx, grady, edges, 50, 150);

 private void houghLinePDemo(Mat src, Mat dst) {
        Mat edges = new Mat();
        Imgproc.Canny(src, edges, 50, 150, 3, true);

        Mat lines = new Mat();
        Imgproc.HoughLinesP(edges, lines, 1, Math.PI/180.0, 100, 50, 10);

        Mat out = Mat.zeros(src.size(), src.type());
        for(int i=0; i<lines.rows(); i++) {
            int[] oneline = new int[4];
            lines.get(i, 0, oneline);
            Imgproc.line(out, new Point(oneline[0], oneline[1]),
                    new Point(oneline[2], oneline[3]),
                    new Scalar(0, 0, 255), 2, 8, 0);
        }
        out.copyTo(dst);

        // 释放内存
        out.release();
        edges.release();
    }

在这里插入图片描述

霍夫曼直线检测

    private void houghLinesDemo(Mat src, Mat dst) {
        Mat edges = new Mat();
        Imgproc.Canny(src, edges, 50, 150, 3, true);

        Mat lines = new Mat();
        Imgproc.HoughLines(edges, lines, 1,Math.PI/180.0, 200);
        Mat out = Mat.zeros(src.size(), src.type());
        float[] data = new float[2];
        for(int i=0; i<lines.rows(); i++) {
            lines.get(i, 0, data);
            float rho = data[0], theta = data[1];
            double a = Math.cos(theta), b = Math.sin(theta);
            double x0 = a*rho, y0 = b*rho;
            Point pt1 = new Point();
            Point pt2 = new Point();
            pt1.x = Math.round(x0 + 1000*(-b));
            pt1.y = Math.round(y0 + 1000*(a));
            pt2.x = Math.round(x0 - 1000*(-b));
            pt2.y = Math.round(y0 - 1000*(a));
            Imgproc.line(out, pt1, pt2, new Scalar(0,0,255), 3, Imgproc.LINE_AA, 0);
        }
        out.copyTo(dst);
        out.release();
        edges.release();
    }

在这里插入图片描述

霍夫圆检测原理
霍夫圆变换的基本原理和霍夫线变换类似, 只是点对应的二维极径极角空间被三维的圆心点x, y还有半径r空间取代.

private void houghCircleDemo(Mat src, Mat dst) {
        Mat gray = new Mat();
        Imgproc.pyrMeanShiftFiltering(src, gray, 15, 80);
        Imgproc.cvtColor(gray, gray, Imgproc.COLOR_BGR2GRAY);

        Imgproc.GaussianBlur(gray, gray, new Size(3, 3),  0);

        // detect circles
        Mat circles = new Mat();
        dst.create(src.size(), src.type());
        Imgproc.HoughCircles(gray, circles, Imgproc.HOUGH_GRADIENT, 1, 20, 100, 30, 10, 200);
        for(int i=0; i<circles.cols(); i++) {
            float[] info = new float[3];
            circles.get(0, i, info);
            Imgproc.circle(dst, new Point((int)info[0], (int)info[1]), (int)info[2],
                    new Scalar(0, 255, 0), 2, 8, 0);
        }
        circles.release();
        gray.release();
    }

轮廓发现与绘制

 private void findContoursDemo(Mat src, Mat dst) {
        Mat gray= new Mat();
        Mat binary = new Mat();

        // 二值
        Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
        Imgproc.threshold(gray, binary, 0, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);

        // 轮廓发现
        List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
        Mat hierarchy = new Mat();
        Imgproc.findContours(binary, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0));

        // 绘制轮廓
        dst.create(src.size(), src.type());
        for(int i=0; i<contours.size(); i++) {
            Imgproc.drawContours(dst, contours, i, new Scalar(0, 0, 255), 2);
        }

        // 释放内存
        gray.release();
        binary.release();
    }

图像直方图

 private void displayHistogram(Mat src, Mat dst) {
        Mat gray = new Mat();
        Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);

        // 计算直方图数据并归一化
        List<Mat> images = new ArrayList<>();
        images.add(gray);
        Mat mask = Mat.ones(src.size(), CvType.CV_8UC1);
        Mat hist = new Mat();
        Imgproc.calcHist(images, new MatOfInt(0), mask, hist, new MatOfInt(256), new MatOfFloat(0, 255));
        Core.normalize(hist, hist, 0, 255, Core.NORM_MINMAX);
        int height = hist.rows();

        dst.create(400, 400, src.type());
        dst.setTo(new Scalar(200, 200, 200));
        float[] histdata = new float[256];
        hist.get(0, 0, histdata);
        int offsetx = 50;
        int offsety = 350;

        // 绘制直方图
        Imgproc.line(dst, new Point(offsetx, 0), new Point(offsetx, offsety), new Scalar(0, 0, 0));
        Imgproc.line(dst, new Point(offsetx, offsety), new Point(400, offsety), new Scalar(0, 0, 0));
        for(int i=0; i<height-1; i++) {
            int y1 = (int)histdata[i];
            int y2 = (int)histdata[i+1];
            Rect rect = new Rect();
            rect.x = offsetx+i;
            rect.y = offsety-y1;
            rect.width = 1;
            rect.height = y1;
            Imgproc.rectangle(dst, rect.tl(), rect.br(), new Scalar(15, 15, 15));
        }

        // 释放内存
        gray.release();
    }

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值