【问题标题】:OpenCv c++ cropping imageOpenCv c++ 裁剪图像
【发布时间】:2017-08-04 12:45:00
【问题描述】:

所以,我设法使用 opencv c++ 代码检测文档边界。现在,我需要裁剪该图像并使其看起来不错。

如图所示,边界检测看起来不错:

但是现在,当我尝试裁剪它时,它看起来像这样:

现在,这是我正在使用的代码:

extern "C"
JNIEXPORT void JNICALL
Java_prisca_ctest_ScanActivity_doWithMat(JNIEnv *env, jobject instance, jlong matNumber) {
    //reference to the image from Java
    Mat &image = *(Mat *) matNumber;
    //resize image
    image = GetSquareImage(image);
    //add color effects for better detection
    Mat gray;
    cvtColor(image, gray, CV_BGR2GRAY);
    GaussianBlur(gray, gray, Size(5, 5), 0);
    Mat edged;
    Canny(gray, edged, 75, 200);
    //find contours and sort them from biggest to smallest
    vector<vector<Point> > contours;
    vector<Point> screenCnt;
    findContours(edged, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
    // sort contours
    sort(contours.begin(), contours.end(), compareContourAreas);

    Rect boundRect;

    //itterate over the contours and get the biggest contour for image
    for (int i = (int) (contours.size() - 1); i > 0; i--) {
        double peri = arcLength(Mat(contours[i]), true);
        vector<Point> approx;
        approxPolyDP(Mat(contours[i]), approx, 0.02 * peri, true);
        if (approx.size() == 4) {
            screenCnt = approx;
            boundRect = boundingRect(approx);
            break;
        }
    }
    Scalar color = Scalar(0, 255, 0);
    drawContours(image, Mat(screenCnt), -1, color, 5);
    //crop image with boundRect
    image = Mat(image, boundRect).clone();
}


Mat GetSquareImage(const cv::Mat &img, int target_width = 500) {
    int width = img.cols,
            height = img.rows;

    cv::Mat square = cv::Mat::zeros(target_width, target_width, img.type());

    int max_dim = (width >= height) ? width : height;
    float scale = ((float) target_width) / max_dim;
    cv::Rect roi;
    if (width >= height) {
        roi.width = target_width;
        roi.x = 0;
        roi.height = height * scale;
        roi.y = (target_width - roi.height) / 2;
    } else {
        roi.y = 0;
        roi.height = target_width;
        roi.width = width * scale;
        roi.x = (target_width - roi.width) / 2;
    }

    cv::resize(img, square(roi), roi.size());

    return square;
}


extern "C"
bool compareContourAreas(std::vector<cv::Point> contour1, std::vector<cv::Point> contour2) {
    double i = fabs(contourArea(cv::Mat(contour1)));
    double j = fabs(contourArea(cv::Mat(contour2)));
    return (i < j);
}

首先,我遵循python code 的教程。他调整图片大小以获得所需的结果,当我这样做时,我的文字不可读,我的图像也没有像它应该的那样被裁剪(裁剪它,所以没有周围的背景,只有纸张等)。

有人有这方面的经验吗?如果有,有人可以帮助我吗?

【问题讨论】:

标签: android c++ image opencv


【解决方案1】:

看起来您需要获取rotatedRect 而不是矩形。然后执行warpAffine (http://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html?highlight=warpaffine)

然后使用getRotationMatrix2D (http://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html#getrotationmatrix2d) 获取旋转角度,像这样旋转图像,像往常一样裁剪,然后再旋转回正常。

【讨论】:

  • 这看起来很有希望,谢谢。至于画质,你能告诉我什么?
  • 原始图像本身看起来有点失焦,并且由于您的代码根本没有降低图像质量,因此可能只是由于 android 手机上的摄像头所致。可能值得再拍一张照片,让文字更加清晰。
  • 那么,使用我的代码中的 GetSquareImage 函数不会降低质量吗?
  • 不,它所做的是获取原始图片的一个区域。这本身在技术上是较低的分辨率,但它不会降低图像质量。
【解决方案2】:

我创建了一个带有原生支持代码的 git 存储库,它以正确的方式裁剪图像,请在以下位置找到它:link

如果您想出更好的解决方案,请随时编辑代码。

【讨论】:

    猜你喜欢
    • 2020-10-18
    • 1970-01-01
    • 2012-12-31
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多