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变换,但它们比使用轮廓更难正确处理。我有以下建议可以帮助您开始:
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)
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)
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
是迭代通过轮廓时得到的轮廓之一。