1

这是我在 Stackoverflow 上的第一个问题。

我是一名专业的软件工程师(Java、C#),我对图像处理和 Android 相关技术的知识为 0。我正在为我的硕士论文编写一个 android 应用程序,以支持我国的视障人士以我们的母语从他们的 Android 智能手机阅读文档。

我已将文档的样本大小选择为 A4,一旦整个 A4 文档在相机视图中(应向用户发出声音通知),应用程序最终应自动聚焦在文档上,然后应捕获该图像。然后我打算通过tesseract引擎运行文档,将其转换为OCR。(其他人正在做这个应用程序的文本到语音部分)

我用谷歌搜索了几个应用程序,并提出了 OpenCV 的文档。http://docs.opencv.org/opencv_tutorials.pdf解释了一些关于“为轮廓创建边界框和圆圈”的内容,看起来它会成为我的救星。

我的 MSC 项目是一个 300 小时的兼职项目,所以我担心在自己花时间将 C++/Python 示例转换为 Java 来学习 OpenCV 之后,我会一无所获。我也浏览了 JavaCV,但看起来它仍处于成长阶段,所以很可能我必须自己转换示例。

我想问专家的是,OpenCV 是否真的可以做到这样的事情?提前致谢!

编辑。我查看了评论上的链接并尝试将 C++ 示例移植到 Java。这是我到目前为止得到的。不过还有几件事要做...

int thresh = 50, N = 11;

// helper function:
// finds a cosine of angle between vectors
// from pt0->pt1 and from pt0->pt2
static double angle(Point pt1, Point pt2, Point pt0)
{
    double dx1 = pt1.x - pt0.x;
    double dy1 = pt1.y - pt0.y;
    double dx2 = pt2.x - pt0.x;
    double dy2 = pt2.y - pt0.y;

    return (dx1*dx2 + dy1*dy2)/Math.sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}

public void find_squares(Mat image, Vector<Vector<Point> > squares)
{
    Imgproc img = new Imgproc();

    // blur will enhance edge detection
    org.opencv.core.Mat blurred = new org.opencv.core.Mat();
    Imgproc.medianBlur(image, blurred, 9);

    Mat gray0 = new Mat(blurred.size(), CvType.CV_8U);
    Mat gray = new Mat();
//        Vector<Vector<Point> > contours;
    List<MatOfPoint> contours = new ArrayList<MatOfPoint>();

    // find squares in every color plane of the image
    for (int c = 0; c < 3; c++)
    {
        int ch[] = {c, 0};
//            Core.mixChannels(blurred, 1, gray0, 1, ch, 1);
        List<Mat> src = new ArrayList<Mat>();
        src.add(blurred);
        List<Mat> dest = new ArrayList<Mat>();
        dest.add(gray0);

        MatOfInt a = new MatOfInt(ch);
        Core.mixChannels(src, dest, a);

        // try several threshold levels
        final int threshold_level = 2;
        for (int l = 0; l < threshold_level; l++)
        {
            // Use Canny instead of zero threshold level!
            // Canny helps to catch squares with gradient shading
            if (l == 0)
            {
                Imgproc.Canny(gray0, gray, 10, 20, 3, false);

                // Dilate helps to remove potential holes between edge segments
                Point point =  new Point(-1, -1);
                Imgproc.dilate(gray, gray, new Mat(), point, 1);
            }
            else
            {
                // TODO
                // gray = gray0 >= (l+1) * 255 / threshold_level;

            }

            // Find contours and store them in a list. //TODO
            Imgproc.findContours(gray, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);

            // Test contours
            MatOfPoint2f approx = new MatOfPoint2f();
            for (int i = 0; i < contours.size(); i++)
            {
                // approximate contour with accuracy proportional
                // to the contour perimeter
                double epilson = Imgproc.arcLength(new MatOfPoint2f(contours.get(i)), true);
                epilson *= 0.02;
                Imgproc.approxPolyDP(new MatOfPoint2f(contours.get(i)), approx, epilson, true);

                // Note: absolute value of an area is used because
                // area may be positive or negative - in accordance with the
                // contour orientation
//                    Mat mmm = new Mat();
//                    MatOfPoint ppp = new MatOfPoint();

                if (/*TODO*/approx.size().area() == 4 &&
                        Math.abs(Imgproc.contourArea(approx)) > 1000 &&
                        Imgproc.isContourConvex(/*TODO*/approx))
                {
                    double maxCosine = 0;

                    for (int j = 2; j < 5; j++)
                    {
                        double cosine = Math.abs(angle(approx[j % 4], approx[j - 2], approx[j - 1]));
                        maxCosine = /*TODO*/MAX(maxCosine, cosine);
                    }

                    if (maxCosine < 0.3)
                        squares./*TODO*/push_back(approx);
                }
            }
        }
    }

}
}
4

1 回答 1

0

只是为了回答这个问题,是的,这可以在 OpenCv 中完成(以及许多其他事情),并且我已经完成了我在问题中解释的项目。还投票赞成阿比德对他提供的链接的回答:)

于 2014-11-13T08:23:27.460 回答