OpenCV使用Sobel濾波器實現圖像邊緣檢測

純粹閱讀,請移步OpenCV使用Sobel濾波器實現圖像邊緣檢測

效果圖

效果圖

原圖

源碼

KqwOpenCVFeaturesDemo

Sobel濾波器也叫Sobel算子,與Canny邊緣檢測一樣,需要計算像素的灰度梯度,只不過是換用另一種方式。

使用Sobel算子計算邊緣的步驟

  1. 將圖像轉爲灰度圖像

    // 原圖置灰
    Imgproc.cvtColor(src, grayMat, Imgproc.COLOR_BGR2GRAY);
  2. 計算水平方向灰度梯度的絕對值

    Imgproc.Sobel(grayMat, grad_x, CvType.CV_16S, 1, 0, 3, 1, 0);
    Core.convertScaleAbs(grad_x, abs_grad_x);
  3. 計算垂直方法灰度梯度的絕對值

    Imgproc.Sobel(grayMat, grad_y, CvType.CV_16S, 0, 1, 3, 1, 0);
    Core.convertScaleAbs(grad_y, abs_grad_y);
  4. 計算最終梯度

    // 計算結果梯度
    Core.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 1, sobel);

最終的梯度實質上就是邊緣。

這裏用到了兩個3 * 3的核對圖像做卷積來近似地計算水平和垂直方向的灰度梯度

核

封裝

這裏用到了RxJava。主要是因爲圖片處理是耗時操作,會阻塞線程,爲了防止界面卡頓,這裏使用RxJava進行了線程切換。

/**
 * Sobel濾波器
 *
 * @param bitmap 要檢測的圖片
 */
public void sobel(Bitmap bitmap) {
    if (null != mSubscriber)
        Observable
                .just(bitmap)
                .map(new Func1<Bitmap, Bitmap>() {

                    @Override
                    public Bitmap call(Bitmap bitmap) {

                        Mat grayMat = new Mat();
                        Mat sobel = new Mat();
                        Mat grad_x = new Mat();
                        Mat grad_y = new Mat();
                        Mat abs_grad_x = new Mat();
                        Mat abs_grad_y = 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.Sobel(grayMat, grad_x, CvType.CV_16S, 1, 0, 3, 1, 0);
                        // 計算垂直方向梯度
                        Imgproc.Sobel(grayMat, grad_y, CvType.CV_16S, 0, 1, 3, 1, 0);
                        // 計算兩個方向上的梯度的絕對值
                        Core.convertScaleAbs(grad_x, abs_grad_x);
                        Core.convertScaleAbs(grad_y, abs_grad_y);
                        // 計算結果梯度
                        Core.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 1, sobel);

                        // Mat轉Bitmap
                        Bitmap processedImage = Bitmap.createBitmap(sobel.cols(), sobel.rows(), Bitmap.Config.ARGB_8888);
                        Utils.matToBitmap(sobel, 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);
    }
});

// Sobel濾波器檢測圖像邊緣
mFeaturesUtil.sobel(mSelectImage);
發佈了198 篇原創文章 · 獲贊 281 · 訪問量 87萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章