1. 程式人生 > >OpenCV高斯差分技術實現影象邊緣檢測

OpenCV高斯差分技術實現影象邊緣檢測

效果圖

邊緣檢測結果

原圖

原始碼

邊緣是影象中畫素亮度變化明顯的點。

高斯差分演算法步驟

  1. 將影象轉為灰度影象

    // 原圖置灰
    Imgproc.cvtColor(src, grayMat, Imgproc.COLOR_BGR2GRAY);
  2. 用兩個不同的模糊半徑對灰度影象執行高斯模糊(取得兩幅高斯模糊影象)

    // 以兩個不同的模糊半徑對影象做模糊處理
    Imgproc.GaussianBlur(grayMat, blur1, new Size(15, 15), 5);
    Imgproc.GaussianBlur(grayMat, blur2, new Size(21, 21), 5);
  3. 將兩幅高斯模糊影象做減法,得到一幅包含邊緣點的結果影象

    // 將兩幅模糊後的影象相減
    Mat diff = new Mat();
    Core.absdiff(blur1, blur2, diff);

該方法只對影象做了高斯模糊,這是計算影象邊緣最快的方法之一,但是,該方法的結果也不是很理想,這種方式對某些影象效果很好,但是在某些情況下可能會完全失效。

封裝

這裡用到了RxJava。主要是因為圖片處理是耗時操作,會阻塞執行緒,為了防止介面卡頓,這裡使用RxJava進行了執行緒切換。

/**
 * 高斯差分演算法邊緣檢測
 *
 * @param bitmap 要檢測的圖片
 */
public void differenceOfGaussian
(Bitmap bitmap) { if (null != mSubscriber) Observable .just(bitmap) .map(new Func1<Bitmap, Bitmap>() { @Override public Bitmap call(Bitmap bitmap) { Mat grayMat = new Mat(); Mat blur1 = new
Mat(); Mat blur2 = new Mat(); // Bitmap轉為Mat Mat src = new Mat(bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8UC4); Utils.bitmapToMat(bitmap, src); // 原圖置灰 Imgproc.cvtColor(src, grayMat, Imgproc.COLOR_BGR2GRAY); // 以兩個不同的模糊半徑對影象做模糊處理 Imgproc.GaussianBlur(grayMat, blur1, new Size(15, 15), 5); Imgproc.GaussianBlur(grayMat, blur2, new Size(21, 21), 5); // 將兩幅模糊後的影象相減 Mat diff = new Mat(); Core.absdiff(blur1, blur2, diff); // 反轉二值閾值化 Core.multiply(diff, new Scalar(100), diff); Imgproc.threshold(diff, diff, 50, 255, Imgproc.THRESH_BINARY_INV); // Mat轉Bitmap Bitmap processedImage = Bitmap.createBitmap(grayMat.cols(), grayMat.rows(), Bitmap.Config.ARGB_8888); Utils.matToBitmap(diff, processedImage); return processedImage; } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(mSubscriber); }

使用

// 圖片特徵提取的工具類
mFeaturesUtil = new FeaturesUtil(new Subscriber<Bitmap>() {
    @Override
    public void onCompleted() {
        // 圖片處理完成
        dismissProgressDialog();
    }

    @Override
    public void onError(Throwable e) {
        // 圖片處理異常
        dismissProgressDialog();
    }

    @Override
    public void onNext(Bitmap bitmap) {
        // 獲取到處理後的圖片
        mImageView.setImageBitmap(bitmap);
    }
});

// 高斯差分技術檢測影象邊緣
mFeaturesUtil.differenceOfGaussian(mSelectImage);