【问题标题】:Advanced denoise Image using Opencv使用 Opencv 的高级去噪图像
【发布时间】:2016-10-19 17:13:58
【问题描述】:

我正在尝试去噪这张图片以获得更好的边缘

我尝试了bilaterFilterGaussianBlur、形态学close 和几个阈值,但每次我得到这样的图像:

当我使用边缘扩张的HoughLinesP 时,结果真的很糟糕。

有人可以帮助我改善这一点吗?有什么办法可以消除那些噪音

第一次尝试:使用 GaussianBlur,在这种情况下,我必须使用 equalizeHist 否则即使我使用非常低的阈值也无法获得边缘

public class TesteNormal {

static {
    System.loadLibrary("opencv_java310");
}


public static void main(String args[]) {

    Mat imgGrayscale = new Mat();
    Mat imgBlurred = new Mat();
    Mat imgCanny = new Mat();

    Mat image = Imgcodecs.imread("c:\\cordova\\imagens\\teste.jpg", 1);

    int imageWidth = image.width();
    int imageHeight = image.height();



    Imgproc.cvtColor(image, imgGrayscale, Imgproc.COLOR_BGR2GRAY);

    Imgproc.equalizeHist(imgGrayscale, imgGrayscale);
    Imgproc.GaussianBlur(imgGrayscale, imgBlurred, new Size(5, 5), 1.8);
    Photo.fastNlMeansDenoising(imgBlurred, imgBlurred);     
    Imshow.show(imgBlurred);


    Mat imgKernel = Imgproc.getStructuringElement(Imgproc.MORPH_CROSS, new Size(3, 3));

    Imgproc.Canny(imgBlurred, imgCanny, 0, 80);
    Imshow.show(imgCanny);
    Imgproc.dilate(imgCanny, imgCanny, imgKernel, new Point(-1, -1), 2);
    Imgproc.erode(imgCanny, imgCanny, imgKernel, new Point(-1, -1), 1);
    Imshow.show(imgCanny);

    Mat lines = new Mat();
    int threshold = 100;
    int minLineSize = imageWidth < imageHeight ? imageWidth / 3 : imageHeight / 3;
    int lineGap = 5;

    Imgproc.HoughLinesP(imgCanny, lines, 1, Math.PI / 360, threshold, minLineSize, lineGap);
    System.out.println(lines.rows());

    for(int x = 0; x < lines.rows(); x++) {
        double[] vec = lines.get(x, 0);
        double x1 = vec[0], y1 = vec[1], x2 = vec[2], y2 = vec[3];
        Point start = new Point(x1, y1);
        Point end = new Point(x2, y2);
        Imgproc.line(image, start, end, new Scalar(255, 0, 0), 1);
    }

    Imshow.show(image);
}

}

第二次尝试:使用双边过滤器:

public class TesteNormal {

static {
    System.loadLibrary("opencv_java310");
}


public static void main(String args[]) {

    Mat imgBlurred = new Mat();
    Mat imgCanny = new Mat();

    Mat image = Imgcodecs.imread("c:\\cordova\\imagens\\teste.jpg", 1);

    int imageWidth = image.width();
    int imageHeight = image.height();

    Imgproc.bilateralFilter(image, imgBlurred, 10, 35, 35);     
    Imshow.show(imgBlurred);        

    Mat imgKernel = Imgproc.getStructuringElement(Imgproc.MORPH_CROSS, new Size(3, 3));

    Imgproc.Canny(imgBlurred, imgCanny, 0, 120);
    Imshow.show(imgCanny);
    Imgproc.dilate(imgCanny, imgCanny, imgKernel, new Point(-1, -1), 2);
    Imgproc.erode(imgCanny, imgCanny, imgKernel, new Point(-1, -1), 1);
    Imshow.show(imgCanny);

    Mat lines = new Mat();
    int threshold = 100;
    int minLineSize = imageWidth < imageHeight ? imageWidth / 3 : imageHeight / 3;
    int lineGap = 5;


    Imgproc.HoughLinesP(imgCanny, lines, 1, Math.PI / 360, threshold, minLineSize, lineGap);
    System.out.println(lines.rows());

    for(int x = 0; x < lines.rows(); x++) {
        double[] vec = lines.get(x, 0);
        double x1 = vec[0], y1 = vec[1], x2 = vec[2], y2 = vec[3];
        Point start = new Point(x1, y1);
        Point end = new Point(x2, y2);
        Imgproc.line(image, start, end, new Scalar(255, 0, 0), 1);
    }

    Imshow.show(image);
}

}

按照建议,我正在尝试使用 opencv contrib,使用 StructuredEdgeDetection。我正在使用固定图像进行测试。

首先我用contrib编译opencv

Segund 我写了 C++ 代码:

JNIEXPORT jobject JNICALL Java_vi_pdfscanner_main_ScannerEngine_getRandomFlorest(JNIEnv *env, jobject thiz) {
Mat mbgra = imread("/storage/emulated/0/Resp/coco.jpg", 1);
Mat3f fsrc;
mbgra.convertTo(fsrc, CV_32F, 1.0 / 255.0); // when I run those convertTo, I got all back image, that way I got no edges.
const String model = "/storage/emulated/0/Resp/model.yml.gz";
Ptr<cv::ximgproc::StructuredEdgeDetection> pDollar = cv::ximgproc::createStructuredEdgeDetection(model);
Mat edges;
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "chamando edges");
pDollar->detectEdges(fsrc, edges);

imwrite( "/storage/emulated/0/Resp/edges.jpg", edges);

jclass java_bitmap_class = (jclass)env->FindClass("android/graphics/Bitmap");
jmethodID mid = env->GetMethodID(java_bitmap_class, "getConfig", "()Landroid/graphics/Bitmap$Config;");
jobject bitmap_config = env->CallObjectMethod(bitmap, mid);
jobject _bitmap = mat_to_bitmap(env,edges,false,bitmap_config);


return _bitmap;

}

我写了这个 java wapper

public class ScannerEngine {
private static ScannerEngine ourInstance = new ScannerEngine();


public static ScannerEngine getInstance() {
    return ourInstance;
}

private ScannerEngine() {
}

public native Bitmap getRandomFlorest(Bitmap bitmap);



static {
    System.loadLibrary("opencv_java3");
    System.loadLibrary("Scanner");
}

}

这一点是,当我运行这些行时

Mat mbgra = imread("/storage/emulated/0/Resp/coco.jpg", 1); //image is ok
Mat3f fsrc;
mbgra.convertTo(fsrc, CV_32F, 1.0 / 255.0); //now image got all back, someone have some ideia why?

非常感谢!

【问题讨论】:

  • 嗨!欢迎来到 StackOverflow。请发布您的代码,以便我们帮助您调试它
  • 检查this
  • 感谢您的回答,我是原帖中的代码。
  • 你还能显示输出图像吗?使用上述代码时,行中存储了什么?霍夫变换对参数非常敏感,如果您只期望图像中的大矩形,您基本上可以使用这些参数过滤掉小线条。
  • @Miki,感谢您的回答,我刚刚用 contrib 编译了 opencv,但是要使用该方法,我必须在 createStructuredEdgeDetection 方法中使用个人训练的数据,还是存在一些默认配置?跨度>

标签: opencv


【解决方案1】:

Result about are strong,像这样

原图: http://prntscr.com/cyd8qi

边缘图像: http://prntscr.com/cyd9ax

它在 android 4.4 (api lvl 19) 上运行在一个非常旧的设备上。

就是这样,

非常感谢

【讨论】:

    猜你喜欢
    • 2022-10-21
    • 1970-01-01
    • 2015-05-20
    • 2017-07-05
    • 2017-10-11
    • 1970-01-01
    • 2012-07-03
    • 2012-03-08
    相关资源
    最近更新 更多