锋行_THU_SJTU

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

小老板给了新任务,看来要研究一下java的图像处理了。

目前最基本的目标是:任意图片的文字提取。

还没有明确的思路,先简单调研一下看看别人都怎么搞的吧。

 

首先是搭环境。

1. 下载安装opencv。

去opencv官网下载并且解压缩就好了。目前我还没搞清版本2.4和3.3有什么区别。

这里有的帖子说要加path,我就顺手加了。$opencvpath$/build/java/x64

2. 在IDEA中新建项目。

这就没啥说的了,新建一个java项目就可以。

3. 设置jar库和dll位置。

在project structure中新建一个java库,然后引用到$opencvpath$/build/java/*.jar

然后在run configurations里的VM option里根据opencv库解压缩的位置添加:-Djava.library.path=D:\MyLibrary\opencv-3.3.0-vc14\build\java\x64;D:\MyLibrary\opencv-3.3.0-vc14\build\java\x64

最后,在新建的类里面,一定要包含以下代码:

static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}

然后就可以了…………最后一步大概折腾了我半个小时…………直到看到一篇帖子提到这段代码,我才意识到是少了这个。

 

然后就是先随便抓一篇代码练练手。

这里参考了这篇文章 http://blog.csdn.net/huobanjishijian/article/details/63685503

然后面临的问题就是:网上常见的opencv代码都是用c++或者python实现的。但是目前看要求,我这套还是得在java上跑,所以就需要把代码改写成java版本的。

这里用到了opencv的官方手册。https://docs.opencv.org/java/2.4.11/

反正就是一条一条对,但是仍然有对不上的。

最后代码如下:

import org.opencv.core.*;

import java.util.ArrayList;
import java.util.List;

import static org.opencv.core.CvType.CV_8U;
import static org.opencv.imgcodecs.Imgcodecs.imread;
import static org.opencv.imgcodecs.Imgcodecs.imwrite;
import static org.opencv.imgproc.Imgproc.*;


/**
 * Created by wangzhao on 2017/10/24.
 */
public class test {
    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    public static void main(String[] args){
        System.out.println("hello");
        System.out.println(Core.VERSION);

        Mat mat=imread("test.jpg");
        System.out.println(mat);
        detect(mat);
    }

    public static void detect(Mat img) {
        Mat gray=new Mat();
        cvtColor(img, gray, COLOR_BGR2GRAY);
        Mat pro=preprocess(gray);
        List<MatOfPoint> region=findTextRegion(pro);
        System.out.println(region.size());
        drawContours(img, region, -1, new Scalar(0, 255, 0), 2);
        imwrite("contours.png", img);
    }

    public static Mat preprocess(Mat gray) {
        Mat sobel=new Mat();
        Sobel(gray, sobel, CV_8U, 1, 0);
        Mat binary=new Mat();
        threshold(sobel, binary, 0, 255, THRESH_OTSU+THRESH_BINARY);
        Mat element1=getStructuringElement(MORPH_RECT, new Size(30,9));
        Mat element2=getStructuringElement(MORPH_RECT, new Size(24,6));
        Mat dilation=new Mat();
        dilate(binary, dilation, element2);
        Mat erosion=new Mat();
        erode(dilation, erosion, element1);
        Mat dilation2=new Mat();
        dilate(erosion, dilation2, element2);
        imwrite("binary.png", binary);
        imwrite("dilation.png", dilation);
        imwrite("erosion.png", erosion);
        imwrite("dilation2.png", dilation2);
        return dilation2;
    }

    public static List<MatOfPoint> findTextRegion(Mat img) {
        Mat hierarchy=new Mat();
        List<MatOfPoint> contours=new ArrayList<>();
        findContours(img, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
//        for (MatOfPoint cnt:contours) {
//            double area=contourArea(cnt);
//            if (area<1000) {
//                continue;
//            }
//            double epsilon=0.001*arcLength(new MatOfPoint2f(cnt.toArray()), true);
//            MatOfPoint2f approx=new MatOfPoint2f();
//            approxPolyDP(new MatOfPoint2f(cnt.toArray()), approx, epsilon, true);
//            RotatedRect rect=minAreaRect(new MatOfPoint2f(cnt.toArray()));
//        }
        return contours;
    }
}

好消息是:现在用java跑opencv已经没有大的问题了。

但是仍然有以下的问题需要解决:

1. 一些c++或python的opencv库提供的函数,在java中并不存在。对于存在的函数,由于python不需要声明变量类型,所以改写成java的版本也效率很低。不过这至少可以work。

2. 这次初步尝试的文本提取方法,对于稍微复杂一点的情况就无法实现了。需要调研寻找可靠的文字提取算法。

以上是今天尝试的收获。

posted on 2017-10-24 20:53  锋行_THU_SJTU  阅读(161)  评论(0编辑  收藏  举报