一、操作流程
首先復制代碼會吧?
1.有張照片
這是網(wǎng)上隨便找的一張照片,自行保存測試
![](/d/20211017/bcd9bf9efcfc50c867b7211da334c9c5.gif)
2.看看照片
運行代碼,其中show_img函數(shù)是展示照片
3.選擇角點
按照左上,右上,右下,左下的順序選擇四個角點
![](/d/20211017/1f6670d5cf78620dbfd0acd2579f427d.gif)
如果擔心自己選不好,可以直接去除我代碼里的points的注釋,那是我自己用的原版
4.最終結(jié)果
![](/d/20211017/6486c5b5a80022a5f85aadb217b69e39.gif)
二、代碼分析
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), bound
return (h, w)
通過鼠標獲取圖片的坐標點,順序是左上,右上,右下,左下
class Indexer:
def __init__(self, bound=4):
self.id = 0
self.bound = bound
def 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 = 20
H = 20
# points=[(112, 308), (175, 310), (176, 369), (113, 369)]
points=get_points(src)
n = 20
W = 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)
三、懶人一鍵復制代碼
誒,氣不氣,好不容易一段段復制完,結(jié)果最后居然有一鍵復制的地方
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), bound
return (h, w)
class Indexer:
def __init__(self):
self.id = 0
def 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 = './3.jpg'
src = cv.imread(path)
src_copy = src.copy()
# show_img(src)
W = 20
H = 20
# points=[(124, 182), (181, 177), (180, 243), (125, 266)]
points=get_points(src)
print(points)
n = 20
W = 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)
到此這篇關(guān)于Python圖片處理之圖片裁剪教程的文章就介紹到這了,更多相關(guān)Python圖片裁剪內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- Python圖像處理之圖片拼接和堆疊案例教程
- python圖片灰度化處理的幾種方法
- Python圖像處理之圖像拼接
- Python圖片檢索之以圖搜圖
- python圖片合成的示例
- 昨晚我用python幫隔壁小姐姐P證件照然后發(fā)現(xiàn)