【问题标题】:opencv - Detecting a rectangle on a photo of paper with inner elementsopencv - 在具有内部元素的纸张照片上检测矩形
【发布时间】:2018-09-19 20:46:09
【问题描述】:

所以我正在尝试阅读下面的图片。

我已经能够设置一个自适应阈值并检测一个旋转角度(我不确定我是否必须旋转图像)

我正在努力检测包含表单的矩形。我尝试了不同的方法,例如 opencv 的 findContours()。它能够找到的最大轮廓是一个带有名字的框。

之后我决定使用 HoughLinesP,但它发现了很多行,我不知道如何过滤它们。检测矩形以歪斜表格也很方便,之后我将能够轻松阅读答案。 所以我已经在考虑在角落添加黑色方形标记。但也许有人可以给我一些关于如何正确做的想法。

HoughLinesP(我用的是nodejs,但是我会读python和c++):

const imageSize = {
    width: gray.cols,
    height: gray.rows
  };

  const threshold_min = 200;
  const ratio_min_max = 1;
  const edges = gray.canny(threshold_min,threshold_min*ratio_min_max,3);

  const minLineLength = imageSize.width / 4, 
        maxLineGap = 10, 
        threshold = 100;
  const lines = edges.houghLinesP(1, Math.PI/180, threshold, minLineLength, maxLineGap);

  //draw lines on the output
  for( let i = 0; i < lines.length; i++ )  {  
    const l = lines[i];  
    const {x,y,z,w} = l;
    output.drawLine(
      cv.Point(w, x), 
      cv.Point(y, z), 
      new cv.Vec(Math.random()*255,Math.random()*255,Math.random()*255), 
      // new cv.Vec(0,0,255), 
      2, 
      // 1
    );   
  }
  //end draw lines

【问题讨论】:

  • 所以我能够在 findContour 之前使用 dilate 函数找到轮廓,进行 6 次迭代。我正在寻找一个面积最大的矩形物体。但我现在很好奇,如果将照片拍摄得更远一点,如何检测它,这样纸张就会完全适合它。如何检测内轮廓?
  • 先拍一张更好的照片。
  • 我会将其扫描成 pdf,而不仅仅是使用手机中的图像。不要让工作变得比需要的更难。
  • 如果可以,我会这样做,但这是任务条件。说起来太容易了 - 只需获得没有倾斜和旋转的完美图像,但这就是设定条件下的编程挑战。

标签: opencv opencv3.0 opencv-contour


【解决方案1】:

好的,所以我能够使用膨胀检测矩形:

  let {area, contour} = getMaxContour(gray);

  let dilateIterations = 0;

  const MAX_DILATE_ITERATIONS = 9;
  while(area<MINIMAL_POSSIBLE_AREA && dilateIterations<MAX_DILATE_ITERATIONS){
    dilateIterations++;
    gray = gray.dilate(new cv.Mat(), new cv.Point(-1,-1), 1, cv.BORDER_CONSTANT);

    let result = getMaxContour(gray);
    contour = result.contour;
    area = result.area;

    if(DEBUG) {
      writeImage(`dilated_${dilateIterations}.png`, gray);
    }
  }

和最大轮廓码:

const getMaxContour = (image) => {
  const contours = image.findContours(cv.RETR_LIST,cv.CHAIN_APPROX_SIMPLE);
  let maxAreaFound = 0;
  let maxContour = [];
  let contourObj = null;
  console.log(`Found ${contours.length} contours.`);
  contours.forEach((contour,i)=>{
    // const perimeter = cv.arcLength(contour, true);
    const perimeter = contour.arcLength(true);
    const approx = contour.approxPolyDP(0.1*perimeter, true);
    const area = contour.moments()['m00'];

    if (approx.length == 4 && maxAreaFound<area){
      maxAreaFound = area;        
      maxContour = approx;
      contourObj=contour;
    }  
  });

  console.log(JSON.stringify(contourObj))
  console.log(`Max contour area found ${maxAreaFound}.`);

  return {
    contour:maxContour,
    area:maxAreaFound
  };
}

之后,我能够突出角落并进行进一步的透视修复。

【讨论】:

    猜你喜欢
    • 2021-06-05
    • 2017-05-11
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-10
    相关资源
    最近更新 更多