使用Opencv的高级降噪图像

时间:2016-10-19 17:13:59

标签: opencv

我正在尝试降噪此图片以获得更好的边缘

我已经尝试了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);
}

}

正如所建议的那样,我正在使用structuredEdgeDetection来尝试使用opencv contrib。我正在使用固定图像进行测试。

首先我用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?

非常感谢!

1 个答案:

答案 0 :(得分:0)

结果很强,就像这样

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

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

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

全部,

非常感谢你