python图片裁剪矩形复原
参考链接
图片裁剪&矩形复原
- 图片裁剪&矩形复原
- 实现效果
- 操作流程
- 1.有张照片
- 2.看看照片
- 3.选择角点
- 4.最终结果
- 代码分析
- 懒人一键复制代码
图片裁剪&矩形复原
这篇博文的目的是从图片中提取一定的矩形区域作为新的图片
简单来说:我给我的房间拍了张照片,其中我的桌子上有一个相框,相框里有全家福
现在我的全家福丢了,所以我想从以前的房间照片里,提取出其中的全家福并重新打印一张(忽视画质问题)
现在我就是这么个目的
实现效果
该方法通过鼠标选择四个点,在手动设置生成的矩形长宽后生成变换后的矩形
这篇需要设置矩形长宽,后续的2.0版本不需要设置
操作流程
首先复制代码会吧?
1.有张照片
这是网上随便找的一张照片,自行保存测试

2.看看照片
运行代码,其中show_img函数是展示照片
3.选择角点
按照左上,右上,右下,左下的顺序选择四个角点

如果担心自己选不好,可以直接去除我代码里的points的注释,那是我自己用的原版
4.最终结果

代码分析
import 没什么好说的
#如果python没有安装cv2,那么就安装python-opencv就好
import cv2 as cv
import numpy as np
获取图片的长宽
#输入cv.imread后的图片,通过点击四个点选择要裁剪的部分
def get_window_size(src, bound=600):h,w = src.shape[0], src.shape[1]if h > w:h, w = bound, int(w*bound/h)else:h, w = int(h*bound/w), boundreturn (h, w)
通过鼠标获取图片的坐标点,顺序是左上,右上,右下,左下
class Indexer:def __init__(self, bound=4):self.id = 0self.bound = bounddef get_id(self):self.id = (self.id + 1)return (self.id)def on_EVENT_LBUTTONDOWN(event, x, y, flags, param):if event == cv.EVENT_LBUTTONDOWN:img = param['src']win_name = param['window']indexer = param['indexer']points = param['points']curr_id = indexer.get_id()points.append((x, y))print('第{}个顶点: ({},{})'.format(curr_id, x, y))cv.circle(img, (x, y), 10, (0, 0, 255), thickness=2)cv.putText(img,str(curr_id), # 文字(x, y), # 坐标cv.FONT_HERSHEY_PLAIN,5, # 字号(0, 0, 255), # 字体颜色thickness=2 # 粗细)cv.imshow(win_name, img)#输入cv.imread后的图片,通过点击四个点选择要裁剪的部分
def get_points(src):points = []indexer = Indexer()h, w=get_window_size(src)win_name = 'get_points'cv.namedWindow(win_name, cv.WINDOW_NORMAL)cv.resizeWindow(win_name, width=w, height=h)cv.imshow(win_name, src)cv.setMouseCallback(win_name, on_EVENT_LBUTTONDOWN,param={'src': src, 'window': win_name, 'indexer': indexer, 'points': points})cv.waitKey(0)cv.destroyAllWindows()if len(points)>4:return points[0:4]# print(points)# points=[(2, 14), (90, 50), (87, 194), (1, 204)]return points#输入cv.imread后的图片,展示图片长什么样
def show_img(src):win_name = 'show_img'h, w=get_window_size(src)cv.namedWindow(win_name, cv.WINDOW_NORMAL)cv.resizeWindow(win_name, width=w, height=h)cv.imshow(win_name, src)cv.waitKey(0)cv.destroyAllWindows()
将图片截取,并按照指定的长宽比恢复成矩形
def photo_cut_restore(src,points,H,W):target_points = [(0, 0), (W, 0), (W, H), (0, H)]points, target_points = np.array(points, dtype=np.float32), np.array(target_points, dtype=np.float32)M = cv.getPerspectiveTransform(points, target_points)# print('透视变换矩阵:', M)result = cv.warpPerspective(src_copy, M, (0, 0))result = result[:H, :W]win_name = 'Result'cv.namedWindow(win_name, cv.WINDOW_NORMAL)cv.resizeWindow(win_name, width=W, height=H)cv.imshow(win_name,result)cv.waitKey(0)cv.destroyAllWindows()return result
主程序
if __name__ == '__main__':path = './1.jpg'src = cv.imread(path)src_copy = src.copy()show_img(src)W = 20H = 20# points=[(112, 308), (175, 310), (176, 369), (113, 369)]points=get_points(src)n = 20W = int(W * n)H = int(H * n)result=photo_cut_restore(src_copy,points,H,W)output_file = 'result.jpg'cv.imwrite(output_file, result)
懒人一键复制代码
诶,气不气,好不容易一段段复制完,结果最后居然有一键复制的地方
import cv2 as cv
import numpy as np#输入cv.imread后的图片,通过点击四个点选择要裁剪的部分
def get_window_size(src, bound=600):h,w = src.shape[0], src.shape[1]if h > w:h, w = bound, int(w*bound/h)else:h, w = int(h*bound/w), boundreturn (h, w)class Indexer:def __init__(self):self.id = 0def get_id(self):self.id = (self.id + 1)return (self.id)def on_EVENT_LBUTTONDOWN(event, x, y, flags, param):if event == cv.EVENT_LBUTTONDOWN:img = param['src']win_name = param['window']indexer = param['indexer']points = param['points']curr_id = indexer.get_id()points.append((x, y))print('第{}个顶点: ({},{})'.format(curr_id, x, y))cv.circle(img, (x, y), 10, (0, 0, 255), thickness=2)cv.putText(img,str(curr_id), # 文字(x, y), # 坐标cv.FONT_HERSHEY_PLAIN,5, # 字号(0, 0, 255), # 字体颜色thickness=2 # 粗细)cv.imshow(win_name, img)#输入cv.imread后的图片,通过点击四个点选择要裁剪的部分
def get_points(src):points = []indexer = Indexer()h, w=get_window_size(src)win_name = 'get_points'cv.namedWindow(win_name, cv.WINDOW_NORMAL)cv.resizeWindow(win_name, width=w, height=h)cv.imshow(win_name, src)cv.setMouseCallback(win_name, on_EVENT_LBUTTONDOWN,param={'src': src, 'window': win_name, 'indexer': indexer, 'points': points})cv.waitKey(0)cv.destroyAllWindows()if len(points)>4:return points[0:4]# print(points)# points=[(2, 14), (90, 50), (87, 194), (1, 204)]return points#输入cv.imread后的图片,展示图片长什么样
def show_img(src):win_name = 'show_img'h, w=get_window_size(src)cv.namedWindow(win_name, cv.WINDOW_NORMAL)cv.resizeWindow(win_name, width=w, height=h)cv.imshow(win_name, src)cv.waitKey(0)cv.destroyAllWindows()def photo_cut_restore(src,points,H,W):target_points = [(0, 0), (W, 0), (W, H), (0, H)]points, target_points = np.array(points, dtype=np.float32), np.array(target_points, dtype=np.float32)M = cv.getPerspectiveTransform(points, target_points)# print('透视变换矩阵:', M)result = cv.warpPerspective(src_copy, M, (0, 0))result = result[:H, :W]win_name = 'Result'cv.namedWindow(win_name, cv.WINDOW_NORMAL)cv.resizeWindow(win_name, width=W, height=H)cv.imshow(win_name,result)cv.waitKey(0)cv.destroyAllWindows()return resultif __name__ == '__main__':path = './3.jpg'src = cv.imread(path)src_copy = src.copy()# show_img(src)W = 20H = 20# points=[(124, 182), (181, 177), (180, 243), (125, 266)]points=get_points(src)print(points)n = 20W = int(W * n)H = int(H * n)result=photo_cut_restore(src_copy,points,H,W)output_file = 'result.jpg'cv.imwrite(output_file, result)
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
