Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何从图像中裁剪出最大的矩形_Python_Opencv_Image Processing - Fatal编程技术网

Python 如何从图像中裁剪出最大的矩形

Python 如何从图像中裁剪出最大的矩形,python,opencv,image-processing,Python,Opencv,Image Processing,我有几张桌子上的页面图片。我想从图像中裁剪出页面。通常,页面将是图像中最大的矩形,但是,在某些情况下,矩形的所有四边可能都不可见 我正在做以下工作,但没有得到预期的结果: import cv2 import numpy as np im = cv2.imread('images/img5.jpg') gray=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(gray,127,255,0) _,contours,_ =

我有几张桌子上的页面图片。我想从图像中裁剪出页面。通常,页面将是图像中最大的矩形,但是,在某些情况下,矩形的所有四边可能都不可见

我正在做以下工作,但没有得到预期的结果:

import cv2
import numpy as np

im = cv2.imread('images/img5.jpg')
gray=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,127,255,0)
_,contours,_ = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
areas = [cv2.contourArea(c) for c in contours]
max_index = np.argmax(areas)
cnt=contours[max_index]
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow("Show",im)
cv2.imwrite("images/img5_rect.jpg", im)
cv2.waitKey(0)
以下是一些例子:

第一个示例:我可以在这张图中找到矩形,但是,我想知道木材的剩余部分是否也可以裁剪出来。

第二个示例:未在此图像中找到矩形的正确尺寸。

第三个示例:也无法在此图像中找到正确的尺寸。

第四个示例:与此相同。

这是一项相当复杂的任务,不能简单地通过搜索轮廓来解决。例如,《经济学人》封面仅显示杂志的一个边缘,将图像一分为二。你的电脑怎么知道哪一本是杂志,哪一本是桌子?所以你必须给你的程序增加更多的智能

您可以在图像中查找线条。例如,Hough变换。然后找到一组或多或少平行或正交的线,一定长度的线。。。 通过检查典型的打印颜色或您通常在桌子上找不到的颜色来查找打印。搜索由打印文本创建的高对比度频率。。。 想象一下,作为一个人类,你是如何识别一张印刷纸的


总而言之,这对于StackOverflow来说是一个过于宽泛的问题。尝试将其分解为更小的子问题,尝试解决它们,如果遇到问题,请返回此处。

正如我之前所做的类似操作一样,我曾体验过hough变换,但它们比使用轮廓更难正确处理。我有以下建议可以帮助您开始:

  • 一般来说,纸张(至少边缘)是白色的,所以你可以选择像YUV这样的颜色空间,这样可以更好地分离亮度:

    image_yuv = cv2.cvtColor(image,cv2.COLOR_BGR2YUV)
    image_y = np.zeros(image_yuv.shape[0:2],np.uint8)
    image_y[:,:] = image_yuv[:,:,0]
    
  • 纸上的文字是个问题。使用模糊效果(希望)消除这些高频噪音。你也可以使用形态学操作,比如扩张

    image_blurred = cv2.GaussianBlur(image_y,(3,3),0)
    
  • 您可以尝试应用精明的边缘检测器,而不是简单的阈值。不一定,但可能有助于您:

     edges = cv2.Canny(image_blurred,100,300,apertureSize = 3)
    
  • 然后找到轮廓线。在我的例子中,我只使用了极端的外部轮廓。您可以使用CHAIN_APROX_SIMPLE标志来压缩轮廓

    contours,hierarchy = cv2.findContours(edges,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    
  • 现在你应该有一系列的轮廓。是时候找到合适的了。对于每个轮廓
    cnt
    ,首先找到凸面外壳,然后使用
    approaxPolyDP
    尽可能简化轮廓

    hull = cv2.convexHull(cnt)
    simplified_cnt = cv2.approxPolyDP(hull,0.001*cv2.arcLength(hull,True),True)
    
  • 现在我们应该使用这个简化的轮廓来找到封闭的四边形。你可以尝试你提出的许多规则。最简单的方法是拾取轮廓的四条最长线段,然后通过与这四条线相交创建封闭四边形。根据您的案例,您可以根据线条的对比度、角度以及类似的情况找到这些线条

  • 现在你有一堆四边形。现在可以执行两步方法来查找所需的四边形。首先,删除那些可能是错误的。例如,四边形的一个角度大于175度。然后,您可以选择面积最大的一个作为最终结果。您可以将橙色轮廓视为我在此时获得的结果之一:

  • 找到(希望)右侧四边形后的最后一步是转换回矩形。为此,您可以使用
    findHomography
    生成变换矩阵

    (H,mask) = cv2.findHomography(cnt.astype('single'),np.array([[[0., 0.]],[[2150., 0.]],[[2150., 2800.]],[[0.,2800.]]],dtype=np.single))
    
    这些数字假定投影到信纸上。你可能会想出更好更聪明的数字来使用。您还需要重新排列轮廓点,以匹配信纸的坐标顺序。然后调用
    warpPerspective
    创建最终图像:

    final_image = cv2.warpPerspective(image,H,(2150, 2800))
    
    这种扭曲会导致如下结果(根据我之前的结果):


  • 我希望这能帮助您找到一种适合您的方法。

    这个问题很难解决,因为木材和纸张的颜色都不相同。。。。我的意思是,这个算法的问题是阈值。。。由于您正在查找此阈值之后的轮廓。。。我建议您在彩色图像中尝试阈值化类似木材的颜色,或者尝试不同的方法。您可以尝试一些边缘检测器,如canny(已经有一些阈值),然后对其执行findcontours。我在image_y[:,:]=imy[:,:,0]imy not处遇到错误defined@usernan这是错误的,它应该是
    image\u y[:,:]=image\u yuv[:,:,0]
    。谢谢你指出。现在答案中已经解决了这个问题。你能帮我解决这个问题吗?我正在考虑使用opencv而不是imagemagick。我在
    等高线,hierarchy=cv2.findContours(edges,cv2.RETR\u EXTERNAL,cv2.CHAIN\u APPROX\u SIMPLE)
    得到了“ValueError:toom values many values to unpackage(expected 2)”。此外,我很困惑:在
    hull=cv2.convxhull(cnt)
    上,cnt来自哪里
    用于轮廓中的cnt
    ?@ytu此代码是为OpenCV2编写的。在OpenCV3中,函数
    findContours
    也返回图像。因此,像返回值的
    边、轮廓、层次结构之类的东西应该可以解决这个问题。对于下一部分,是的,
    cnt
    是迭代通过
    轮廓时得到的轮廓之一。