1, 记录一些代码-opencv 图片视频裁剪

1,161 阅读6分钟

记录一些代码

# 裁剪矩形图片
def clipImage(file, p1, p2):
    img = cv2.imread(file, cv2.IMREAD_COLOR)
    return img.copy()[p1[0]:p2[0], p1[1]:p2[1]]


# 裁剪矩形图片
def clipMat(mat, p1, p2):
    return mat.copy()[p1[0]:p2[0], p1[1]:p2[1]]

p1 = (817, 898)
p2 = (2183 , 1666)
# 视频读, 显示
cap = cv2.VideoCapture('D:/crawler/code/MoviePy/donggandimo_01/mask1.mp4')
fourcc = cv2.VideoWriter_fourcc(*'XVID')
videoWriter = cv2.VideoWriter('D:/crawler/code/MoviePy/donggandimo_01/mask1_clip.mp4', fourcc, 15.0, (768, 1366))
i = 0
ret = True
while cap.isOpened() and ret:
    ret, frame = cap.read()
    if ret:
        out = clipMat(frame, p1, p2)
        print(out.shape[:2])
        # cv2.imshow('',out)
        # cv2.waitKey(100)
        videoWriter.write(out)
        print(i)
        i += 1
cap.release()
cv2.destroyAllWindows()

中心点坐标系变为左上角坐标系

# -*- coding: utf-8 -*-

import json
import math
import time
'''
    将transform数据封装成方法
'''



# 角度转弧度
def degreeToRad(r):
    return r * math.pi / 180
# 角度转为360以内
def degreeConvertIn360(r):
    return r%360

# 获取缩放后的大小
def get_size(_x, _y, scale):
    return (_x*scale[0], _y*scale[1])



# 位置信息 x: 素材宽, y:素材高, anchor: 锚点在图片中,rotate:角度, sacle:缩放, anchor_pos:锚点位置
def get_postion(_x, _y, anchor, rotate, scale, anchor_pos):
    print((_x, _y, anchor, rotate, scale, anchor_pos))
    p = anchor_pos
    s = scale
    a = anchor
    _r = rotate
    # 左上角的坐标
    x = p[0] - a[0] * s[0]
    y = p[1] - a[1] * s[1]
    r = degreeConvertIn360(_r)
    after = ransform((p[0], -p[1]), (x, -y), -_r)
    if r >= 0 and r< 90:
        after = (after[0] - _y* s[1]*math.sin(degreeToRad(r)), after[1])
    elif r >= 90 and r < 180:
        r = r - 90
        after = (after[0] - _y * s[1] * math.cos(degreeToRad(r)) - _x*s[0]*math.sin(degreeToRad(r)), after[1] -  _y * s[1] * math.sin(degreeToRad(r)))
    elif r >= 180 and r < 270:
        r = r - 180
        after = (after[0] - _x * s[0] * math.cos(degreeToRad(r)), after[1]- _x * s[0] * math.sin(degreeToRad(r)) - _y * s[1] * math.cos(degreeToRad(r)))
    elif r >= 270 and r < 360:
        r = r - 270
        after = (after[0],  after[1] - _x * s[0] * math.cos(degreeToRad(r)))
    else:
        print("######### Error rotate: %s" % (_r))
    print("转换后的坐标: (%s, %s), 角度为: %s" % (after[0], after[1],_r))
    return (after[0], after[1])


# 角度变换 点a:目标点  点a0:旋转点, r:旋转角度(逆时针旋转)
def ransform(a0, a, r):
    x0 = a[0] - a0[0]
    y0 = a[1] - a0[1]
    # rad = degreeToRad(r)
    rad = math.radians(r)
    return (x0*math.cos(rad)-y0* math.sin(rad) + a0[0], -(x0 * math.sin(rad)+ y0 *math.cos(rad) + a0[1]))


if __name__ == "__main__":
    # import  numpy as np
    # from moviepy.editor import *
    # import  playutil
    #
    # bg = np.zeros((500, 500, 3), np.uint8)
    # bg1 = np.zeros((400, 10, 3), np.uint8)
    # bg1.fill(255)
    # def get_pos(t):
    #     h, w = bg1.shape[:2]
    #     print('w: %s, h: %s' % (w, h))
    #     return get_postion(w, h, (w/2, h/2), math.sin(t/3)*360, (1, 1), (250, 250))
    #     # return transformutil.get_postion(w, h, (w/2, h/2), 45, (1, 1), (w/2, h/2))
    #
    # bg_clip = ImageClip(bg).set_duration(200).set_fps(15)
    # bg_clip1 = ImageClip(bg1).set_position(get_pos).set_fps(55).set_duration(20).rotate(lambda t:math.sin(t/3)*360)
    #
    # out = CompositeVideoClip([bg_clip, bg_clip1]).set_duration(20)
    # playutil.play(out, False)


    pos = get_postion(100, 100, (50, 50), 0, (0.2, 0.2), (50, 50))
    print(pos)

图片裁剪

# 等比例缩放, 背景用原图片模糊处理
# w, h: 处理后的图片大小
def convertImage(file, w, h):
    img = cv2.imread(file, cv2.IMREAD_COLOR)
    img_h, img_w = img.shape[:2]
    # img = ImageClip(file)
    bgImg = cv2.resize(img, (w, h))
    bgImg = cv2.GaussianBlur(bgImg, (25, 25), 0)
    if img_w / img_h > w/h:
        print((img_w, img_h))
        img = cv2.resize(img, (w,int(img_h/(img_w/w))))
    else:
        img = cv2.resize(img, (int(img_w/(img_h/h)),h))
    img_h, img_w = img.shape[:2]
    bgImg[int((h-img_h)/2):int((h-img_h)/2)+ img_h, int((w-img_w)/2):int((w-img_w)/2)+ img_w] = img
    # result = result.set_start(0).set_duration(4)
    # result.write_videofile("result.mp4", fps=24, codec="libx264", bitrate="1000000")
    return bgImg

图片上写字

# coding:utf-8
import  cv2
import numpy as np
from PIL import ImageFont, Image, ImageDraw




def getFont():
    return '../Engine/ttf/ss.ttf'

def showframe0(video):
    frame = video.get_frame(0)
    cv2.imshow('aa', frame)
    cv2.waitKey(0)

def showim(frame):
    h, w = frame.shape[:2]
    cv2.namedWindow('frame', cv2.WINDOW_NORMAL)
    cv2.resizeWindow("frame", (int(w / 2), int(h / 2)));
    cv2.imshow('frame', frame)
    cv2.waitKey(1000)


def play(video, hasframecount):
    iter = video.iter_frames()
    i1=0
    # print(type(iter))
    for frame in iter:
        frame = frame.copy().astype(np.uint8)
        print(frame[0,0])
        # frame  = make_frame(0)
        print(frame.shape)
        img = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
        # img = frame
        istr = str(i1)
        h, w = img.shape[:2]
        if hasframecount:
            text = writeText(100,50*len(istr),istr,100,(255,0,0), '../aiqingtuya/ss.ttf')
            th, tw = text.shape[:2]
            img[0:th, 0:tw] = text
        # cv2.namedWindow('frame', cv2.WINDOW_NORMAL)
        # cv2.resizeWindow("frame", (200 ,200));
        cv2.imshow('frame', img)
        key = cv2.waitKey(300)
        if key == ord('q'):
            break
        i1 = i1 +1
    cv2.destroyAllWindows()

# 实现在指定区域写字
# w:写字区域的宽, h:写字区域的高, x:写的字左上角的x坐标,y:同理 color: 字的颜色, font: 字体的ttf文件路径,
# x1,y1: 写字区域的左上角坐标(超过写字区域不显示)
def getTextMask(text, h, w,img=None,  x=0, y=0,x1 =0, y1=0, color=(255, 255, 255), font=getFont(),font_size=None, bg_color=(0,0,0)):
    # 修复截取的区域超出图片报错的bug
    n = text.count('\n') + 1
    if img is None:
        canvas_bg = np.zeros((1080, 720, 3), np.uint8)
        canvas_bg[:,:,0] = bg_color[0]
        canvas_bg[:, :, 1] = bg_color[1]
        canvas_bg[:, :, 2] = bg_color[2]
    else:
        canvas_bg = img.copy()
    c_h, c_w = canvas_bg.shape[:2]
    canvas = np.zeros((c_h+2*h, c_w+2*w, 3),np.uint8)
    canvas[ h:h+c_h, w:w+c_w] = canvas_bg

    if font_size is None:
        font_size = int((h - 10) / n)
    txt_area = canvas[y1+h:y1 + 2*h, x1+w:x1 + 2*w]

    out = writeText(h, w, text, font_size, color, font,img=txt_area, x=x, y=y, bg_color=bg_color)
    # showim(out)
    # cv2.imshow('b', out)
    canvas[y1+h:y1 + 2*h, x1+w:x1 + 2*w] = out
    # cv2.rectangle(canvas, (x1, y1), (x1+w, y1+h), (0,0,255), thickness=1)
    return canvas[h:h+c_h, w:w+c_w]

# 在图片上写字
def writeText(h, w,text, size, color, ttf=getFont(), img=None, x =None, y=None, bg_color=(0,0,0)):
    color = (color[2], color[1], color[0])
    if img is None:
        img = np.zeros((h, w, 3), np.uint8)
        img[:, :, 0] = bg_color[0]
        img[:, :, 1] = bg_color[1]
        img[:, :, 2] = bg_color[2]
    if x is None:
        x = 0
    if y is None:
        y=0
    cv2_im = cv2.cvtColor(img, cv2.COLOR_BGRA2RGBA)
    pil_im = Image.fromarray(cv2_im)
    draw = ImageDraw.Draw(pil_im)
    font = ImageFont.truetype(ttf, size, encoding="utf-8")
    draw.text((x, y), text, color, font=font)
    cv2_text_im = cv2.cvtColor(np.array(pil_im), cv2.COLOR_RGB2BGR)
    # cv2.imshow("Video", cv2_text_im)
    # cv2.waitKey(0)
    return cv2_text_im




# 处理多行文字居中对齐
def handlerTextLine(*txt):
    max = 0
    s = []
    for i in txt:
        l = 0
        for ch in i:
            if isChinese(ch):
                l = l +2
            else:
                l = l + 1
        if l > max:
            max = l
    print(max)
    for i in txt:
        l = 0
        for ch in i:
            if isChinese(ch):
                l = l + 2
            else:
                l = l + 1
        space_num= int((max-l)/2)
        print(str(i)+':'+str(space_num))
        s.append(space_num*"  "+ i)
    return '\n'.join(s)


# 判断单个字符是否为汉字
def isChinese(ch):
    if '\u4e00' <= ch <= '\u9fff':
        return True

# @hubobo 判断方法
def txtLen(i):
    l = 0
    for ch in i:
        if isChinese(ch):
            l = l + 2
        elif ch.islower():
            l = l + 1
        else:
            l = l + 1.5
    return l

# 判断字符串的长度, 汉字为2个, 字母为1个
def txtLenSelf(i) :
    l = 0
    for ch in i:
        if isChinese(ch):
            l = l + 2
        else:
            l = l + 1
    return l




# 实现在图片上写字, 有透明效果
def writeTextWeighted(imput_txt, h, w, img=None,  x=0, y=0,x1 =0, y1=0, color=(255, 255, 255), font=getFont(), font_size=None, bg_color=(0,0,0), weight=1):
    if img is None:
        canvas = np.zeros((1080, 720, 3), np.uint8)
        canvas[:, :, 0] = bg_color[0]
        canvas[:, :, 1] = bg_color[1]
        canvas[:, :, 2] = bg_color[2]
    else:
        canvas = img
    img2 = canvas.copy()
    text = getTextMask(imput_txt, h, w, img=img2, x=x, y=y, x1=x1, y1=y1, font_size=font_size, color=color)
    out = cv2.addWeighted(img, (1-weight), text,weight, 0)
    return out




#
if __name__ == "__main__":
#
#
#
    # 1, 写透明字体
    # text = handlerTextLine('您好', '娃哈哈', '江山如此多娇')
    # # 写透明字
    # for i in range(10):
    #     out = writeTextWeighted(text, 80, 360, img=cv2.imread('../test/cat.jpg', cv2.IMREAD_COLOR), x=0, y=0, x1=180,
    #                             y1=680, color=(255, 0, 0), weight=i / 10)
    #     cv2.imshow('', out)
    #     cv2.waitKey(0)

#
#
#
#     # 2, 逐字写入
#     # txt = '昨夜星辰昨夜风,画楼西畔桂堂东。\n身无彩凤双飞翼,心有灵犀一点通。\n隔座送钩春酒暖,分曹射覆蜡灯红。\n嗟余听鼓应官去,走马兰台类转蓬。'
#     # n = txt.count('\n') + 1
#     # # 写透明字
#     # for i in range(len(txt)+1):
#     #     input_txt = txt[:i]
#     #     m = input_txt.count('\n')
#     #     input_txt =input_txt + ((n-m)*"\n")
#     #     out = writeTextWeighted(input_txt, 200, 600, img=cv2.imread('../demo/a.jpg', cv2.IMREAD_COLOR), x=0,y=0, x1=0, y1=0, color=(255,0,0), weight=1)
#     #     cv2.imshow('', out)
#     #     cv2.waitKey(100)
#
    # 3, 从上往下写
    txt1 = '李白'
    txt2 = '杜甫'
    txt1s = '\n'.join(list(txt1))
    txt2s = '\n'.join(list(txt2))

# out = pictureutil.writeTextWeighted(txt1s, 500, 800, img=cv2.imread( self.path + 'head.png', cv2.IMREAD_COLOR),
#                                 x=0, y=0, x1=516,
#                                 y1=526, color=(136,245,255), font_size=45, weight=1)
#     cv2.namedWindow('a', cv2.WINDOW_NORMAL)
    for i in range(max(len(txt1s), len(txt2s))+1):
        input_txt1s = txt1s[:i]
        input_txt2s = txt2s[:i]
        out = getTextMask(input_txt1s, 200, 600, img=cv2.imread('../test/cat.jpg', cv2.IMREAD_COLOR), x=0, y=0, x1=-10,
                                y1=-10,color=(89,147,255), font_size=25)
        # out = writeTextWeighted(input_txt2s, 200, 600, img=out, x=0, y=20, x1=0,
        #                         y1=0, color=(89,147,255), font_size=25, weight=1)
        cv2.imshow('a', out)
        cv2.waitKey(1000)