在图像裁剪操作中,opencv和pillow两个库都具有相应的函数,但是这两个库中的函数仅仅能对与图片平行的矩形进行裁剪操作,如果想要对目标的最小外接矩形进行裁剪该如何操作呢?如下所示:
具体处理该问题的思路如下:
- 计算最小外接矩形的四个点的坐标,旋转角度
- 将原图像进行旋转,旋转角度为最小外接矩形的角度
- 将四个点的坐标进行映射,求出被旋转后图像的四个点的坐标
- 利用这四个点对图像进行裁剪
图像原图如下:
1 求出该区域的最小外接矩形,并且得到外接矩形的四个点的坐标和旋转角度。
python" id="highlighter_442648">
1
2
|
rect = cv2.minarearect( self .contours[ 0 ]) #rect为[(旋转中心x坐标,旋转中心y坐标),(矩形长,矩形宽),旋转角度] box_origin = cv2.boxpoints(rect) #box_origin为[(x0,y0),(x1,y1),(x2,y2),(x3,y3)] |
2 将原图像进行旋转,旋转角度为最小外接矩形的角度,由于防止旋转后目标区域在图像外面,所以我将图像大小扩大为原来的2倍。
1
2
|
m = cv2.getrotationmatrix2d(rect[ 0 ],rect[ 2 ], 1 ) dst = cv2.warpaffine(rotateimg,m,( 2 * rotateimg.shape[ 0 ], 2 * rotateimg.shape[ 1 ])) |
3 将原四个点的坐标做映射,映射到旋转后的区域,得到新的四个点的坐标。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
#逆时针旋转 def nrotate(angle,valuex,valuey,pointx,pointy): angle = (angle / 180 ) * math.pi valuex = np.array(valuex) valuey = np.array(valuey) nrotatex = (valuex - pointx) * math.cos(angle) - (valuey - pointy) * math.sin(angle) + pointx nrotatey = (valuex - pointx) * math.sin(angle) + (valuey - pointy) * math.cos(angle) + pointy return (nrotatex, nrotatey) #顺时针旋转 def srotate(angle,valuex,valuey,pointx,pointy): angle = (angle / 180 ) * math.pi valuex = np.array(valuex) valuey = np.array(valuey) srotatex = (valuex - pointx) * math.cos(angle) + (valuey - pointy) * math.sin(angle) + pointx srotatey = (valuey - pointy) * math.cos(angle) - (valuex - pointx) * math.sin(angle) + pointy return (srotatex,srotatey) #将四个点做映射 def rotatecordiate(angle,rectboxs,pointx,pointy): output = [] for rectbox in rectboxs: if angle> 0 : output.append(srotate(angle,rectbox[ 0 ],rectbox[ 1 ],pointx,pointy)) else : output.append(nrotate( - angle,rectbox[ 0 ],rectbox[ 1 ],pointx,pointy)) return output box = rotatecordiate(rect[ 2 ],box_origin,rect[ 0 ][ 0 ],rect[ 0 ][ 1 ]) |
4 利用四个点坐标进行裁剪,如2中图所示,图像经过旋转后已经变为和图片没有旋转角的图像,经过实验观察旋转后的坐标还是有细微差别,但误差已经在千分点甚至万分点左右,对我们裁剪造成的影响可以忽略不计。
1
2
3
4
5
6
7
8
9
10
|
def imagecrop(image,box): xs = [x[ 1 ] for x in box] ys = [x[ 0 ] for x in box] print (xs) print ( min (xs), max (xs), min (ys), max (ys)) cropimage = image[ min (xs): max (xs), min (ys): max (ys)] print (cropimage.shape) cv2.imwrite( 'cropimage.png' ,cropimage) return cropimage imagecrop(dst,np.int0(box)) |
到此,利用4个坐标点对图像进行裁剪操作已经完成。
到此这篇关于python四个坐标点对图片区域最小外接矩形进行裁剪的文章就介绍到这了,更多相关python 图片坐标裁剪内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://blog.csdn.net/u014662865/article/details/105125361