本文共 2733 字,大约阅读时间需要 9 分钟。
纯粹阅读,请移步
边缘是图像中像素亮度变化明显的点。
将图像转为灰度图像
// 原图置灰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);
该方法只对图像做了高斯模糊,这是计算图像边缘最快的方法之一,但是,该方法的结果也不是很理想,这种方式对某些图像效果很好,但是在某些情况下可能会完全失效。
这里用到了RxJava。主要是因为图片处理是耗时操作,会阻塞线程,为了防止界面卡顿,这里使用RxJava进行了线程切换。
/** * 高斯差分算法边缘检测 * * @param bitmap 要检测的图片 */public void differenceOfGaussian(Bitmap bitmap) { if (null != mSubscriber) Observable .just(bitmap) .map(new Func1() { @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() { @Override public void onCompleted() { // 图片处理完成 dismissProgressDialog(); } @Override public void onError(Throwable e) { // 图片处理异常 dismissProgressDialog(); } @Override public void onNext(Bitmap bitmap) { // 获取到处理后的图片 mImageView.setImageBitmap(bitmap); }});// 高斯差分技术检测图像边缘mFeaturesUtil.differenceOfGaussian(mSelectImage);