剪切图片的某个部分

前言

from PIL import Image
# 打开图片,path路径
img=Image.open(path)
# 如果我要剪切图片,我可以用crop方法
# 可是,我怎么知道我需要剪切的图片的位置,
# crop方法需要
# 左上角的坐标,右下角坐标

可是,我怎么会知道,我需要剪切的图片的左、右坐标?难道慢慢尝试,还是

要用opencv去寻找轮廓,可是假如我需要的地方,opencv就是找不到,就是需要自己剪切。

可以尝试,也行。。。

希望

我希望我打开一张图片,

在我希望剪切的地方画个东西,比如矩形,就可以得到所需要剪切的图片的坐标,就可以剪切了。

很明显,opencv可以实现。

正文

# 导包
import cv2 as cv
import prettytable as pt
import numpy as np
class seek_place:
    def __init__(self,show=False):
        self.tangle = [0, 0, 0, 0]
# 矩形的四个角的初始化
        self.start = [0, 0]
# 用来存放点击位置的坐标
        self.click = False
        self.data = []
# 数据的保存
        self.show=show
# 是否展示,默认为Flase
    def get_size(self, path):
        img = cv.imdecode(np.fromfile(path, dtype=np.uint8), -1)
        w, h, _ = img.shape
        return h, w
# 得到大小,图片不同,窗口的大小也不同,而且不用imread,因为在图片的路径有中文不能读取成功
    def draw(self, path):
        cv.namedWindow('tu_xiang', 0)
        cv.resizeWindow('tu_xiang', self.get_size(path))
        cv.setMouseCallback('tu_xiang', self.call_back)
# 鼠标的回调
        while cv.waitKey(1) != 27:
# 退出按Esc
            img = cv.imdecode(np.fromfile(path, dtype=np.uint8), -1)
            pt1 = (self.tangle[0], self.tangle[1])
            pt2 = (self.tangle[2], self.tangle[3])
            cv.rectangle(img, pt1, pt2, (255, 0, 0), 2)
# 画矩形
            cv.imshow('tu_xiang', img)
        return self
# 返回self,为了链式调用
    def call_back(self, event, x, y, flags, param):
        if event == cv.EVENT_LBUTTONDOWN:
# 按下左键,得到位置,改变参数self.click
            self.start[0] = x
            self.start[1] = y
            self.click = True
        if event == cv.EVENT_MOUSEMOVE:
# 鼠标移动
            if self.click:
                self.tangle[0] = self.start[0]
                self.tangle[1] = self.start[1]
                self.tangle[2] = x
                self.tangle[3] = y
        if event == cv.EVENT_LBUTTONUP:
#放开左键
            tb = pt.PrettyTable()
            tb.field_names = ['左上角的坐标', '右下角的坐标:', '中心点的坐标:']
            left_palce = (self.tangle[0], self.tangle[1])
            right_palce = (self.tangle[2], self.tangle[3])
            center_place = [int((self.tangle[0] + self.tangle[2]) / 2), int((self.tangle[1] + self.tangle[3]) / 2)]
            tb.add_row([tuple(left_palce), tuple(right_palce), tuple(center_place)])
            if not self.data:
                self.data.append([(*left_palce, *right_palce), center_place])
# 得到数据
            else:
# 为了得到最后一次的数据,只能保存一个
                self.data.clear()
                self.data.append([(*left_palce, *right_palce), center_place])
            if self.show:
#如果需要展示==prettable
                print(tb)
            self.click = False
#改变参数
    def get_data(self):
        if self.data:
            return self.data
        else:
            None
#得到数据

得到数据的说明

比如是这样的

[[(467, 184, 910, 783), [688, 483]]]

最里面的那个元组的前两个数据是左上角坐标,后两个是右下角坐标,我把二者和为一个元组了,取出来直接用,假如需要其他需要,再提取数据

元组后面有个列表,看正文,这个是画的矩形的中心点的坐标。(取整了)

操作

import cv2 as cv
import prettytable as pt
import numpy as np
from init import picturepath
from PIL import Image
# 完整导包
path = picturepath + '/31.jpg'
#picturnpath 图片路径
data=seek_place(show=True).draw(path).get_data()
for i in data:
    box=i[0]
# 或者 box=data[0][0]
img=Image.open(path)
a=img.crop(box)
a.save('2.jpg')

show=True展示的结果

剪切图片的某个部分_第1张图片

剪切

给出一张图片

剪切图片的某个部分_第2张图片

比如我要这样剪切

结果

剪切图片的某个部分_第3张图片

总结

有待修改,如果不是矩形,假如我想剪的是圆形,或者其他形状。。。

只用opencv好像也可以剪切,我比较菜,先这样把。

当然,结合pypt5,更美观。

(为什么不用ps,或者其他修图工具,哈哈哈哈哈哈哈哈)

你可能感兴趣的:(opencv,计算机视觉,人工智能,python)