-
请问这个文件谁知道怎么解决?
-
准备工作 环境咱们还是使用 Python3.8 和 pycharm2021 即可 实现原理 将视频分为音频和画面 画面中出现人脸和目标比对,相应人脸进行打码 处理后的视频添加声音 模块 手动安装一下 cv2 模块 ,pip install opencv-python 安装 安装遇到报错,可以私信我 素材工具 我们需要安装一下 ffmpeg 音视频转码工具 所有的素材.源码.点击此处即可领取 代码解析 导入模块 import cv2 import face_recognition # 人脸识别库 99.7% cmake dlib face_recognition import subprocess 视频转为音频 def video2mp3(file_name): """ :param file_name: 视频文件路径 :return: """ outfile_name = file_name.split('.')[0] + '.mp3' cmd = 'ffmpeg -i ' + file_name + ' -f mp3 ' + outfile_name print(cmd) subprocess.call(cmd, shell=False) 打码 def mask_video(input_video, output_video, mask_path='mask.jpg'): """ :param input_video: 需打码的视频 :param output_video: 打码后的视频 :param mask_path: 打码图片 :return: """ # 读取图片 mask = cv2.imread(mask_path) # 读取视频 cap = cv2.VideoCapture(input_video) # 视频 fps width height v_fps = cap.get(5) v_width = cap.get(3) v_height = cap.get(4) # 设置写入视频参数 格式MP4 # 画面大小 size = (int(v_width), int(v_height)) fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') # 输出视频 out = cv2.VideoWriter(output_video, fourcc, v_fps, size) # 已知人脸 known_image = face_recognition.load_image_file('tmr.jpg') biden_encoding = face_recognition.face_encodings(known_image)[0] cap = cv2.VideoCapture(input_video) while (cap.isOpened()): ret, frame = cap.read() if ret: # 检测人脸 # 人脸区域 face_locations = face_recognition.face_locations(frame) for (top_right_y, top_right_x, left_bottom_y, left_bottom_x) in face_locations: print((top_right_y, top_right_x, left_bottom_y, left_bottom_x)) unknown_image = frame[top_right_y - 50:left_bottom_y + 50, left_bottom_x - 50:top_right_x + 50] if face_recognition.face_encodings(unknown_image) != []: unknown_encoding = face_recognition.face_encodings(unknown_image)[0] # 对比人脸 results = face_recognition.compare_faces([biden_encoding], unknown_encoding) # [True] # 贴图 if results == [True]: mask = cv2.resize(mask, (top_right_x - left_bottom_x, left_bottom_y - top_right_y)) frame[top_right_y:left_bottom_y, left_bottom_x:top_right_x] = mask out.write(frame) else: break 音频添加到画面 def video_add_mp3(file_name, mp3_file): """ :param file_name: 视频画面文件 :param mp3_file: 视频音频文件 :return: """ outfile_name = file_name.split('.')[0] + '-f.mp4' subprocess.call('ffmpeg -i ' + file_name + ' -i ' + mp3_file + ' -strict -2 -f mp4 ' + outfile_name, shell=False) 完整代码 源码.素材.资料.点击领取即可 好啦,今天的分享到这里就结束了 ~ 如果需要更多视频学习的可以在b站搜索 :Python小圆 / ka-爆浆麻薯团子 对文章有问题的,或者有其他关于python的问题,可以在评论区留言或者私信我哦 觉得我分享的文章不错的话,可以关注一下我,或者给文章点赞(/≧▽≦)/ ———————————————— 版权声明:本文为CSDN博主「小圆-」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/aliYz/article/details/127541002
-
🌟好久不见 写这篇文章只是想证明一下:本博主还在呼吸😇 📢许久未更,甚是想更呐~ 这段时间生活中充斥着各种事情,感觉每天都在忙忙碌碌,偶而停下疲惫的身躯,突然抬头,却不知自己身处何方,忙了这么久,到底在忙些什么呢?找不着方向,于是开始惶恐,便又不知方向的胡乱奔走……,好吧好吧,总结两个字:迷茫,再加两个字:瞎忙…… 其实这几天一直想写博客的,想写有趣又轻松的一篇文章,但又不到写哪些内容比较好,又因还要解决各种事情,于是就搁到了现在…… 💥直到某天,为了完成MOOC(MOOC不会没人不知道吧👀)上的回复讨论任务,我不已为然的点开了MOOC……突然 ⁉️我看到了一个进度条,那个进度条仿佛就像是深渊,脑海中突然闪出一句话,我%@#!,咳咳咳,不是不是,是一句名言:当你凝望深渊,深渊也在凝望着你……😭 (进度条是已经用代……不是,是已经用我辛勤的劳动把它拉起来的) 不知到有没有小伙伴经历过要回复几十条讨论的经历,当场看见那进度条我就……,就偷偷写脚本了😁 这个脚本花了我比较长的时间才完成的,因为调试的过程有些许麻烦……,不过最终还是解决了,想看效果如何,请往下看👇 ⛳️实现过程 🌴老操作了兄弟们~ 又双叒叕是Get_cookie.py了兄弟,看过我《小玩意儿》专栏文章的都能看烂了,但别说,还真好用,登录一次,一劳永逸,就靠它了~,话不多说,直接❗️ ❗️ ❗️ 上号💬 上码❗️ ❗️ ❗️ (记得在三十秒内登录哦~) from selenium import webdriver import time import json driver = webdriver.Chrome() driver.maximize_window() driver.get('https://www.icourse163.org/') time.sleep(30) dictCookies = driver.get_cookies() jsonCookies = json.dumps(dictCookies) # 转换成字符串保存 with open('moocCookie.txt', 'w') as f: f.write(jsonCookies) print("cookies保存成功") 🐢一步拿捏讨论 以前回复讨论咱们讲究的是什么⁉️讲究的是灵活运用Ctrl C和Ctrl V,讲究的是快准狠💪 现在回复讨论咱们讲究的是什么⁉️讲究的是能不用手就不用手,讲究的是一个 automation,科技是第一生产力呀兄弟们 🤘 什么?相应模块怎么下载?pip install 模块名 就完事了兄弟~ 什么?chromedriver怎么配置?看这篇文章就完事兄弟~ 【Python网络蜘蛛 · 9】:selenium模块【安装和配置环境变量教程、提取数据操作、无头模式】(附操作源码) 什么?不会搞?看下图干就完事了兄弟 话不多说❗️ ❗️ ❗️码来❗️ ❗️ ❗️ from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By import json import time class MOOC(object): def __init__(self): self.driver = webdriver.Chrome() self.driver.get('https://www.icourse163.org/') def login(self): #获取保存下的cookie值 with open('moocCookie.txt', 'r', encoding='utf-8') as f: listCookies = json.loads(f.read()) # 往driver里添加cookie for cookie in listCookies: cookie_dict = { 'domain': '.icourse163.org', 'name': cookie.get('name'), 'value': cookie.get('value'), 'expires': '', 'path': '/', 'httpOnly': False, 'HostOnly': False, 'Secure': False } self.driver.add_cookie(cookie_dict) self.driver.refresh() # 刷新页面 # 进入课程 def entering_the_course(self): #等待“个人中心”元素出现 WebDriverWait(self.driver, 1000).until( EC.presence_of_element_located((By.XPATH, '//*[@id="j-indexNav-bar"]/div/div/div/div/div[7]/div[3]/div/div/a/span')) ) self.driver.find_element(By.XPATH, '//*[@id="j-indexNav-bar"]/div/div/div/div/div[7]/div[3]/div/div/a/span').click() # 等待“SPOC课程12”元素出现并点击 time.sleep(1) WebDriverWait(self.driver, 1000).until( EC.presence_of_element_located((By.XPATH, '//div[@class="u-selectTab-container"]/div[2]/a')) ) self.driver.find_element(By.XPATH, '//div[@class="u-selectTab-container"]/div[2]/a').click() #等待课程元素出现,并获取元素,用户选择课程 WebDriverWait(self.driver, 1000).until( EC.presence_of_element_located((By.XPATH, '//div[@class="course-card-wrapper"]/div/a/div/img')) ) course_ele = self.driver.find_elements(By.XPATH, '//div[@class="course-card-wrapper"]/div/a/div/img') course_name = [ele.get_attribute('alt') for ele in course_ele] for index, i in enumerate(course_name): print(index, i) user = int(input('请输入课程序号:')) course_ele[user].click() time.sleep(2) self.driver.switch_to.window(self.driver.window_handles[-1]) # 切换窗口 time.sleep(2) #等待课件出现并点击 WebDriverWait(self.driver, 1000).until( EC.presence_of_element_located((By.XPATH, '//li[@data-name="课件"]')) ) self.driver.find_element(By.XPATH, '//li[@data-name="课件"]').click() # 等待章节元素出现并点击 WebDriverWait(self.driver, 1000).until( EC.presence_of_element_located((By.XPATH, '//div[@class="m-learnChapterList f-pr"]/div[@class="m-learnChapterNormal f-pr"][1]')) ) # 点击章节 self.driver.find_element(By.XPATH, '//div[@class="m-learnChapterList f-pr"]/div[@class="m-learnChapterNormal f-pr"][1]').click() time.sleep(0.3) # 点击进入视频 self.driver.find_elements(By.XPATH, '//div[@class="sourceList"]/div[1]')[0].click() # 获取章节中”选择课程“的元素并点击 WebDriverWait(self.driver, 1000).until( EC.presence_of_element_located( (By.XPATH, '//div[@class="j-breadcb f-fl"]//div[@class="f-fl j-lesson"]/div')) ) # 获取所有章节 temp_chapters = self.driver.find_elements(By.XPATH, '//div[@class="f-fl j-chapter"]//div[@class="down f-bg j-list"]/div') # 通过循环获取到的章节元素和课程元素,进行讨论 for chapter_index in range(len(temp_chapters)): # 循环章节 # 获取章节中”选择课程“的元素并点击 WebDriverWait(self.driver, 1000).until( EC.presence_of_element_located( (By.XPATH, '//div[@class="j-breadcb f-fl"]//div[@class="f-fl j-lesson"]/div')) ) # 获取章节选项框并点击 self.driver.find_element(By.XPATH, '//div[@class="f-fl j-chapter"]/div[@class="u-select"]/div[1]').click() self.driver.find_elements(By.XPATH, '//div[@class="f-fl j-chapter"]//div[@class="down f-bg j-list"]/div')[chapter_index].click() # 等待课程元素出现 WebDriverWait(self.driver, 1000).until( EC.presence_of_element_located( (By.XPATH, '//div[@class="j-breadcb f-fl"]//div[@class="f-fl j-lesson"]/div')) ) # 获取章节中所有课程 course = self.driver.find_elements(By.XPATH,'//div[@class="j-breadcb f-fl"]//div[@class="f-fl j-lesson"]/div/div[2]/div') course_names = [i.get_attribute('title') for i in course] for c_index in range(len(course)): # 循环课程 WebDriverWait(self.driver, 1000).until( EC.presence_of_element_located( (By.XPATH, '//div[@class="j-breadcb f-fl"]//div[@class="f-fl j-lesson"]/div')) ) self.driver.find_element(By.XPATH,'//div[@class="j-breadcb f-fl"]//div[@class="f-fl j-lesson"]/div').click() WebDriverWait(self.driver, 1000).until( EC.presence_of_element_located( (By.XPATH, '//div[@class="j-breadcb f-fl"]//div[@class="f-fl j-lesson"]/div/div[2]/div')) ) # 重新获取课程元素并点击 course1 = self.driver.find_elements(By.XPATH, '//div[@class="j-breadcb f-fl"]//div[@class="f-fl j-lesson"]/div/div[2]/div') course1[c_index].click() time.sleep(2) try: try: # 获取讨论元素 disc = self.driver.find_element(By.XPATH, '//li[@title="讨论:讨论话题"]/span[2]') if disc.is_enabled(): # 如果讨论元素存在且可以点击 disc.click() self.discuss() # 调用讨论函数 except: time.sleep(0.5) if course_names[c_index] == '讨论区': self.discuss() except: pass # 讨论 def discuss(self): # 等待“回复”元素出现 WebDriverWait(self.driver, 100).until( EC.presence_of_element_located((By.XPATH, '//div[@class="optbar f-cb"]/a[1]/span')) ) time.sleep(0.5) self.driver.execute_script("var q=document.documentElement.scrollTop=10000") time.sleep(0.5) try: content = self.driver.find_element(By.XPATH, '//div[@class="j-list"]/div/div[3]/div/div[2]/p').text except: content = self.driver.find_element(By.XPATH, '//div[@class="j-list"]/div/div[1]/div/div[2]').text self.driver.switch_to.frame(0) time.sleep(0.5) # 定位输入框并输入信息 self.driver.find_element(By.XPATH, '//body[@contenteditable="true"]').send_keys(content) self.driver.switch_to.window(self.driver.window_handles[-1]) # 进行窗口切换 time.sleep(1) # 点击发送回复 self.driver.find_element(By.XPATH,'/html/body/div[5]/div[2]/div[4]/div[2]/div/div[1]/div/div/div[3]/div[2]/div[2]/div/div/div[5]/div/div[1]/div[2]/a[1]').click() def run(self): self.login() self.entering_the_course() mooc = MOOC() mooc.run() 💖美图 结束语 好了,以上就是今天哔哩吧啦咕噜哇啦叽里呱啦哗哗啦啦写的一篇水……呃不,勉强还看得过去的文章😛,如果喜欢,可以 点赞👍 收藏🌈 关注💖 感谢您的支持🌹 🚈下次再见💨 哦对了💡为啥每次刷网课时最小化网页后,看完一个视频它就自动暂停了❓是不是可以写一个自动刷视频的❓不管了,下次再说吧💨 peace~ ———————————————— 版权声明:本文为CSDN博主「IT工藤新一」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/Oh_Python/article/details/127465767
-
Python去除小数点后面多余的0最近在用Python 写导入数据的脚本。百度 必应搜了好多,都没有一个完美解决的。在这里还是要吐槽一下百度对于这些真的很垃圾。后来FQ谷歌了一下,第一个词条出来就找到办法了。这里我搬过来整理一下,以及使用时候可能遇到的问题。希望对看到这篇文章的读者有用首先引入头文件from decimal import Decimal举个例子数字 100.2000 第一次 这么使用 Decimal('100.2000').normalize() 得到的结果 100.2 是想要的结果。可是 normalize() 有个问题,如果是100.00000 同样 Decimal('100.0000').normalize()得到的结果就是1E+2那么这种情况怎么办呢,就是换个方法 使用 “ to_integral ”,像这样:Decimal('100.000').to_integral() 得到结果是100,这才是想要的结果。 那怎么才能更好的两种兼容呢,可以先做一个判断 在去除多余0之后 是否相等:>>> Decimal('100.2000') == Decimal('100.2000').to_integral() False >>> Decimal('100.0000') == Decimal('100.0000').to_integral() True根据这个判断 可以自己写一个functiondef remove_exponent(num): return num.to_integral() if num == num.to_integral() else num.normalize()最后调用这个function 这里同样举上面几个例子得到的结果>>> remove_exponent(Decimal('100.2000')) Decimal('100.2') >>> remove_exponent(Decimal('100.0000')) Decimal('100') >>> remove_exponent(Decimal('0.2000')) Decimal('0.2')这里输出是Decimal 类型 是因为 调用的方法里面就是这个类型的。可以直接当float用,如果想要换成string类型 就在用str() 包一下上面得到的结果就行啦,这个就不解释了 这样就解决标题所说的去除小数点后面多余的0的问题了Python去掉数字前面的0有时候文件的编号是在前面自动补0生成的,而当我们需要读取这些文件名对应的编号时,前面的0会给判断语句造成麻烦,那么如何将前面的0去掉呢?因为Python默认在转换成字符串时忽略前面的0,因此可以通过格式转换的方法实现去0:>>> str(000001) '1' >>> int(str(000001)) 1
-
遇到的问题工作中遇到这么一个事,需要写很多C++的底层数据库类,但这些类大同小异,无非是增删改查,如果人工来写代码,既费力又容易出错;而借用python的代码自动生成,可以轻松搞定; (类比JAVA中的Hibernate自动生成的数据库底层操作代码) 下面介绍使用python字符串替换的方法;Python字符串替换的几种方法1. 字符串替换 将需要替换的内容使用格式化符替代,后续补上替换内容;template = "hello %s , your website is %s " % ("大CC","http://blog.me115.com") print(template)也可使用format函数完成:template = "hello {0} , your website is {1} ".format("大CC","http://blog.me115.com") print(template)注:适用相同变量较多的单行字符串替换;3.模版方法替换 使用string中的Template方法;from string import Template tempTemplate = string.Template("Hello $name ,your website is $message") print(tempTemplate.substitute(name='大CC',message='http://blog.me115.com'))有了模版方法后,就可以将模版保存到文件单独编辑,在生成的地方替换为需要的变量;示例:代码生成这个示例使用以上讲到的第三种方法; 建立一个模版文件,里面需要替换的内容使用${}变量替换; dao_cpp.template /// /// @class ${CLASSNAME} /// @brief Redis底层接口类 操作${TABLE_NAME}表 /// TABLE ${TABLE_NAME_UPPER} /// @author dao_cpp_generator.py /// @generate date: ${GENE_DATE} /// [注:本文件为自动生成,不需要人为编辑,若有修改,请通过配置py脚本来重新生成.] #include "${CLASSNAME}.h" #include "include/${TABLE_NAME}_t.h" #include "RedisManager.h" #include "common/LogMacros.h" #include "common/StringUtility/OtherStringFunc.h" #include "common/DateTime.h" namespace redisdao{ #define PRIMARY_KEY "${PRIMER_KEY}" const string ${CLASSNAME}::TABLE_NAME = "${TABLE_NAME}"; const string ${CLASSNAME}::TABLE_ID = "${TABLE_ID}"; //在数据库中的表的唯一性标识符 const string ${CLASSNAME}::KEY_SEPARETER = "${KEY_SEPARETER}"; ${CLASSNAME}::${CLASSNAME}(void) { if ( 0 == m_reHandler.EnsureConnect()) m_bRedisConnected = true; else m_bRedisConnected = false; } ${CLASSNAME}::~${CLASSNAME}(void) { } int ${CLASSNAME}::InsertRecord(const string& strVal) ... python代码生成程序: cpp_generator.py #! /usr/bin/env python #coding=utf-8 #Redis底层操作类CPP文件生成程序(*RedisDao.cpp) #author me115@126.com 2014-7-22 import os,sys,re,traceback from datetime import datetime from string import Template class DaoCppGenerator: def generate(self): tableName = 'students' className = '%sRedisDao' % tableName.capitalize() filePath = r'include/%s.cpp' % className class_file = open(filePath,'w') lines = [] #模版文件 template_file = open(r'dao_cpp.template','r') tmpl = Template(template_file.read()) #模版替换 lines.append(tmpl.substitute( CLASSNAME = className, TABLE_NAME = tableName, TABLE_NAME_UPPER = tableName.upper(), GENE_DATE = datetime.now().strftime('%Y-%m-%d %H:%M:%S'), TABLE_ID = '115', EXPIRE_DATE = '06JUN14')) # 0.将生成的代码写入文件 class_file.writelines(lines) class_file.close() print 'generate %s over. ~ ~' % filePath
-
装饰器的价值不言而喻,可以用来增强函数功能、简化代码、减少代码冗余。它的使用场景同样很多,比较简单的场景包含打印日志、统计运行时间,这类例子和用法网上已经很多了:def time_dec(func): def wrapper(*arg): t = time.clock() res = func(*arg) print func.func_name, time.clock()-t return res return wrapper @time_dec def myFunction(n): ... 再进阶一些的,可以用来校验函数传入参数类型、线程同步、单元测试等:@parameters( (2, 4, 6), (5, 6, 11), ) def test_add(a, b, expected): assert a + b == expected 目前可以用的装饰器可以分为如下几类:自定义第三方工具包内置下面就分别来介绍一下。自定义关于自定义的装饰器在前面已经提到了,我在开发过程中经常用到的就是日志打印、计时、数据校验等场景,通过装饰器可以提高代码的简洁性,避免重复造轮子。除了这些基本的,也有一些比较实用的地方。作为开发同学,肯定会遇到不同的运行环境:开发环境测试环境生产环境有时候,我们期望一个函数在不同环境下执行不同的过程,产出不同的结果,做一些环境的隔离和差异化处理。通过装饰器就可以很好的解决:production_servers = [...] def production(func: Callable): def inner(*args, **kwargs): if gethostname() in production_servers: return func(*args, **kwargs) else: print('This host is not a production server, skipping function decorated with @production...') return inner def development(func: Callable): def inner(*args, **kwargs): if gethostname() not in production_servers: return func(*args, **kwargs) else: print('This host is a production server, skipping function decorated with @development...') return inner def sit(func: Callable): def inner(*args, **kwargs): print('Skipping function decorated with @sit...') return inner @production def foo(): print('Running in production, touching databases!') foo() @development def foo(): print('Running in production, touching databases!') foo() @inactive def foo(): print('Running in production, touching databases!') foo() 简单的介绍一下这段代码。在这里,先是罗列了生产环境的服务列表,然后分别定义了生产、开发、测试环境的装饰器,然后给同名的函数就可以配上对应的装饰器。在执行代码的过程中,这段代码会首先获取hostname,自动判断所在环境,然后执行对应函数。第三方工具包上面是根据我们在开发过程中遇到的个性化场景进行来自定义一个装饰器。作为一款以工具包著称的编程语言,Python中也有很多工具包提供了一些实用的装饰器。以日志为例,这是每个程序员都无法绕开的。调试程序对于大多数开发者来说是一项必不可少的工作,当我们想要知道代码是否按照预期的效果在执行时,我们会想到去输出一下局部变量与预期的进行比对。目前大多数采用的方法主要有以下几种:Print函数Log日志IDE调试器但是这些方法有着无法忽视的弱点:繁琐过度依赖工具其中有一款不错的开源工具PySnooper就通过装饰器把这个问题巧妙的解决了。PySnooper的调用方式就是通过@pysnooper.snoop的方式进行使用,该装饰器可以传入一些参数来实现一些目的,具体如下:参数描述:None输出日志到控制台filePath输出到日志文件,例如'log/file.log'prefix给调试的行加前缀,便于识别watch查看一些非局部变量表达式的值watch_explode展开值用以查看列表/字典的所有属性或项depth显示函数调用的函数的snoop行举个例子:import numpy as np import pysnooper @pysnooper.snoop() def one(number): mat = [] while number: mat.append(np.random.normal(0, 1)) number -= 1 return mat one(3) 然后,就会给出如下输出:Starting var:.. number = 322:17:10.634566 call 6 def one(number):22:17:10.634566 line 7 mat = []New var:....... mat = []22:17:10.634566 line 8 while number:22:17:10.634566 line 9 mat.append(np.random.normal(0, 1))Modified var:.. mat = [-0.4142847169210746]22:17:10.634566 line 10 number -= 1Modified var:.. number = 222:17:10.634566 line 8 while number:22:17:10.634566 line 9 mat.append(np.random.normal(0, 1))Modified var:.. mat = [-0.4142847169210746, -0.479901983375219]22:17:10.634566 line 10 number -= 1Modified var:.. number = 122:17:10.634566 line 8 while number:22:17:10.634566 line 9 mat.append(np.random.normal(0, 1))Modified var:.. mat = [-0.4142847169210746, -0.479901983375219, 1.0491540468063252]22:17:10.634566 line 10 number -= 1Modified var:.. number = 022:17:10.634566 line 8 while number:22:17:10.634566 line 11 return mat22:17:10.634566 return 11 return matReturn value:.. [-0.4142847169210746, -0.479901983375219, 1.0491540468063252]局部变量值、代码片段、局部变量所在行号、返回结果等,这些关键信息都输出了,既方便,又清晰。内置除了自定义和第三方工具包之外,Python还内置了很多不错的装饰器,例如@abc.abstractmethod、@asyncio.coroutine、@classmethod等等。这里着重提一个非常强大的装饰器,能够极大的提升Python的运行速度和效率,通过一个装饰器能够将Python代码的执行速度提升上万倍,这个装饰器就是@functools.lru_cache。以比较知名的斐波那契数列的例子来演示一下。由于它递归计算的过程中,还会用到之前计算的结果,因此会涉及较多的重复计算,下面先看一下正常计算的耗时情况。import time as tt def fib(n): if n <= 1: return n return fib(n-1) + fib(n-2) t1 = tt.time() fib(30) print("Time taken: {}".format(tt.time() - t1)) # 0.2073 n等于30时,耗时0.2073。加上@functools.lru_cache装饰器再看一下:import time as tt import functools @functools.lru_cache(maxsize=5) def fib(n): if n <= 1: return n return fib(n-1) + fib(n-2) t1 = tt.time() fib(30) print("Time taken: {}".format(tt.time() - t1)) # 1.811981e-05 耗时为1.811981e-05,足足差了4个量级,快了10000+倍!
-
一,json.load()和json.dump只要用于读写json数据1json.load()从文件中读取json字符串with open('data.json','r',encoding='utf-8') as f print(json.load(f))2json.dump()将json字符串写入到文件中content="{'name':'zhangsan','age':18}" with open('text.json','w',encoding='utf-8') as f: json.dump(content,f)二,json.loads和json.dumps主要用于字符串和字典之间的类型转换3json.loads()将json字符串转换成字典类型content="{'name':'zhangsan','age':18}" json.loads(content)3json.dumps()将字典类型转换成json字符串content={'name':'zhangsan','age':18}#假设这个是python定义的字典1编写一个json格式的文件{ "one": ["数字1"], "two": ["数字2"], "too": ["太","也","非常"] }2编写python方法import json from difflib import get_close_matches data = json.load(open("data.json","r",encoding="utf-8")) def translate(word): word = word.lower() if word in data: return data[word] elif len(get_close_matches(word,data.keys(),cutoff=0.5)) > 0: yes_no = input("你要查询的是不是%s?,请输入yes或no:"%get_close_matches(word,data.keys(),cutoff=0.5)) yes_no = yes_no.lower() if yes_no == "yes": return data[get_close_matches(word,data.keys(),cutoff=0.5)[0]] else: return "你要查找的内容库里没有" word = input("请输入你要查询的单词") output = translate(word) if type(output) == list: for item in output: print(item) else: print(output)
-
一、测试平台:解决分散用例执行方式,提供统一测试用例执行过程、用例管理、测试报告二、搭建过程2.1 使用django搭建一个web系统1. 创建项目 django-admin startproject TestPlatform创建python的包,测试平台的配置和功能2. 创建appdjango-admin startapp web创建python的包,具体的功能代码(1)在TestPlatform/Web/apps.py中注册appfrom django.apps import AppConfig class WebConfig(AppConfig): # default_auto_field = 'django.db.models.BigAutoField' name = 'Web' verbose_name = "自动化测试" (2) 在TestPlatform/TestPlatform/settings.py中进行相关设置INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'Web.apps.WebConfig' ] LANGUAGE_CODE = 'zh-hans'# 设置中文 TIME_ZONE = 'Asia/Shanghai'# 设置时区 USE_I18N = True USE_L10N = True USE_TZ = False MEDIA_ROOT = 'uploads/' MEDIA_URL = 'uploads/' (3)编辑TestPlatform/TestPlatform/urls.py文件from django.conf import settings from django.conf.urls.static import static from django.contrib import admin from django.urls import path # 定义http路由,是web系统的入口点 urlpatterns = static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + [ path('', admin.site.urls), ] (4)启动测试平台 python manage.py runserver2.2 搭建测试框架1. 定义modelmodel驱动开发import pathlib from django.db import models # 定义model # 抽象化 from django.utils import html class Task(models.Model): name = models.CharField("用例名称", max_length=20) case = models.FileField("用例文件", upload_to='tests/%Y_%m_%d_%H_%M_%S/') status = models.IntegerField( "测试状态", default=-1, choices=[ (-1, '初始化'), (0, '马上执行'), (1, '正在执行测试用例'), (2, '正在生成测试报告'), (3, '执行完毕'), ] ) run_datatime = models.DateTimeField( "最近执行时间", null=True, blank=True ) class Meta: verbose_name_plural = verbose_name = "测试任务" def __str__(self): return self.name def get_url(self, _type): """生成报告或者测试日志的Url""" if self.case and self.status == 3: # 执行完毕 case_path = pathlib.PurePosixPath(str(self.case)) root_path = pathlib.PurePosixPath('/uploads') if _type == 'report': # 报告的url report_path = root_path / case_path.parent / "report/index.html" elif _type == 'log': # 日志的url report_path = root_path / case_path.parent / "pytest.txt" else: report_path = '_' return html.format_html(f"<a href='{report_path}' target='_blank'> 点击查看</a>") else: return "-" 2. 定义界面 from django.contrib import admin from .models import Task # Register your models here. @admin.register(Task) class TaskAdmin(admin.ModelAdmin): # 决定了model 怎么显示 list_display = ("id", "name", "status", "run_datatime", "report_url", "log_url", ) # 要显示的字段 readonly_fields = ('run_datatime',) def report_url(self, obj): return obj.get_url('report') report_url.short_description = '测试报告' def log_url(self, obj): return obj.get_url('url') log_url.short_description = '执行日志' 3. 执行数据库迁移 python manage.py makemigrations python manage.py migrate三、平台如何管理1. 创建管理员账号 python manage.py createsuperuser 用户名:admin 邮箱:admin@qq.com 密码:admin2. 调整页面显示3. 执行测试用例在models.py文件中调用pytest,pytest执行yaml文件(关键字驱动)import pathlib from datetime import datetime from django.db import models # 定义model # 抽象化 from django.utils import html class Task(models.Model): name = models.CharField("用例名称", max_length=20) case = models.FileField("用例文件", upload_to='tests/%Y_%m_%d_%H_%M_%S/') status = models.IntegerField( "测试状态", default=-1, choices=[ (-1, '初始化'), (0, '马上执行'), (1, '正在执行测试用例'), (2, '正在生成测试报告'), (3, '执行完毕'), ] ) run_datatime = models.DateTimeField( "最近执行时间", null=True, blank=True ) class Meta: verbose_name_plural = verbose_name = "测试任务" def __str__(self): return self.name def get_url(self, _type): """生成报告或者测试日志的Url""" if self.case and self.status == 3: # 执行完毕 case_path = pathlib.PurePosixPath(str(self.case)) root_path = pathlib.PurePosixPath('/uploads') if _type == 'report': # 报告的url report_path = root_path / case_path.parent / "report/index.html" elif _type == 'log': # 日志的url report_path = root_path / case_path.parent / "pytest.txt" else: report_path = '_' return html.format_html(f"<a href='{report_path}' target='_blank'> 点击查看</a>") else: return "-" def save(self, *args, **kwargs): super().save(*args, **kwargs) # 判断是否需要启动测试框架,执行测试用例 if self.status == 0: self.status = 1 # 修改状态:正在执行 self.run_datatime = datetime.datetime.now() super().save() # 启动测试框架 import pytest pytest.main(self.case.path) # 执行指定的测试用例文件 self.status = 3 # 修改状态:执行完毕 self.run_datatime = datetime.datetime.now() super().save()
-
PDF是我们经常会接触到的一种文件格式,文献、文档...很多都是PDF格式。它以格式稳定的优势,使得我们在打印、分享、传输过程中能够最优的保持原有色彩和格式。PDF是以PostScript语言图像模型为基础的一种文档格式,它在格式的稳定性方面虽然具有很大优势。但是,在可编辑性方面却为使用者引入了另外一个困扰。例如,在文档的分割、合并、剪切、转换、编辑等方面PDF就有些捉襟见肘了。Adobe Reader、福昕阅读器、熊猫PDF...经常用到的PDF工具只能用于文档阅读,但是免费版都不可以用于文档编辑。虽然,网页版PDF工具,例如SmallPDF、I love PDF可以用于PDF的编辑,但是对于文档大小也有限制。曾经,为了替换PDF中的一页,我几乎试遍了所有市面上主流的PDF工具,最终还是不得不选择使用付费工具来解决问题。事后想了想,既然这些商业化软件不靠谱,为什么不考虑自己动手开发一款工具呢?明明几十行代码能够解决的问题,为什么要费那么多劲去下载、安装那些没有节操的软件呢?本文就来介绍一下利用Python轻松开发一款PDF编辑工具,可以用于PDF转TxT、分割、合并、剪切、转换。PyPDF2PyPDF2是一个第三方的python PDF库,它能够对PDF文件进行分割、合并、裁剪和转换页面。另外,它还可以对PDF文件添加自定义数据、水印、密码,也可以从PDF文件中检索出文本和元数据。安装使用pip直接安装:$ pip install PyPDF2 下面就来演示几项PDF编辑功能,并且会逐行解释代码的含义。删除PDF页先给出实现代码,from PyPDF2 import PdfFileWriter, PdfFileReader output = PdfFileWriter() // 1 input1 = PdfFileReader(open("example.pdf", "rb")) // 2 def delete_pdf(index): pages = input1.getNumPages() // 3 for i in range(pages): if i+1 in index: continue output.addPage(input1.getPage(i)) // 4 outputStream = open("PyPDF2-output.pdf", "wb") output.write(outputStream) // 5 delete_pdf([2,3,4]) 下面来解释一下代码中的几个关键点:声明一个用于输出PDF的实例;读取本地PDF文件;获取PDF文档的页数;读取PDF的第i页,添加到输出output实例中;把编辑后的文档保存到本地;合并PDF已经实现了删除PDF页,接下来就看一下如何把另外一个PDF中的页面合并到当前PDF中。方法1:可以沿着前面删除PDF页的方式进行拓展一下,对PDF进行合并。from PyPDF2 import PdfFileWriter, PdfFileReader output = PdfFileWriter() input1 = PdfFileReader(open("example.pdf", "rb")) input2 = PdfFileReader(open("simple2.pdf", "rb")) // 1 def merge_pdf(add_index, origin_index): pages = input1.getNumPages() k = 0 for i in range(pages): if i+1 in add_index: output.addPage(input2.getPage(origin_index[k])) // 2 pages += 1 k += 1 output.addPage(input1.getPage(i)) outputStream = open("PyPDF2-output.pdf", "wb") output.write(outputStream) merge_pdf([2,3,4], [0, 0, 0]) 读取需要合并的源文件;遍历到指定页,合并源PDF的页面;方法2:除了方法1,还有另外一种方法可以合并PDF:from PyPDF2 import PdfFileMerger // 1 merger = PdfFileMerger() input1 = open("document1.pdf", "rb") // 2 input2 = open("document2.pdf", "rb") input3 = open("document3.pdf", "rb") merger.append(fileobj = input1, pages = (0,3)) // 3 merger.merge(position = 2, fileobj = input2, pages = (0,1)) // 4 merger.append(input3) // 5 output = open("document-output.pdf", "wb") merger.write(output) 导入PyPDF2合并模块PdfFileMerger;读取需要处理和合并的PDF文档;从第一个PDF文档中取出需要合并的前3页;把第二个PDF文档的第一页插入到文档中;把第三个PDF文档附到输出文档末尾;除了上述介绍的2项主要功能,PyPDF2也有一些其他小功能:旋转input1.getPage(1).rotateClockwise(90) 使得页面1旋转90度。添加水印page = input1.getPage(3) watermark = PdfFileReader(open("watermark.pdf", "rb")) page.mergePage(watermark.getPage(0)) 其中,水印存储在另外一个PDF文档watermark.pdf中。加密password = "secret" output.encrypt(password) 首先给一个secret密码,然后使用encrypt对输出文档进行加密。pdfminer前面介绍的PyPDF2主要擅长于PDF页面级编辑,而对于文本和源数据级别编辑能力较弱。所以,这里就来介绍另外一款Python库来弥补它的不足。PDFMiner是一个PDF文档的文本提取工具,它具有如下特性:能够准确获取文本的位置和布局信息;可以将PDF转换为HTML/XML等格式;可以提取目录;可以提取标签内容;支持各种字体类型(Type1、TrueType、Type3和CID);支持中、日、韩语言和垂直书写文本;安装$ pip install pdfminer PDF转TxTpdfminer在GitHub的托管项目中,在目录tools下给出了一些实用的工具集,例如,PDF转HTML、PDF转HTML、PDF转TXT。我们可以直接通过使用下面命令提出PDF文档中的文本信息。$ pdf2txt.py samples/simple1.pdf
-
问题描述利用栈的数据结构实现将十进制数转换成二进制数C语言实现顺序表的存储结构实现栈代码:#include <stdlib.h> #include <stdio.h> #define STACK_INIT_SIZE 100 //栈初始开辟空间大小 #define STACK_INCREMENT 10 //栈追加空间大小 //栈的结构体 typedef struct stack{ int *base; int *top; int size; }binStack; //栈初始化 binStack stack_init() { binStack bs; bs.base = (int *)malloc(sizeof(int)*STACK_INIT_SIZE); bs.top = bs.base; bs.size = STACK_INIT_SIZE; return bs; } //入栈 void push(binStack *bs, int e) { if(bs->top - bs->base >= bs->size) { bs->size += STACK_INCREMENT; bs->base = realloc(bs->base, bs->size); } *(bs->top++) = e; } //出栈 int pop(binStack *bs) { if(bs->top != bs->base) { bs->top--; return *bs->top; } return -1; } //主函数 void main() { int dec; binStack bs = stack_init(); printf("请输入十进制整数:\n"); scanf("%d", &dec); while(dec) { push(&bs, dec%2); dec /= 2; } printf("转换后的二进制数是:\n"); while(bs.top != bs.base) { printf("%d", pop(&bs)); } printf("\n\n"); system("date /T"); system("TIME /T"); system("pause"); exit(0); } Python实现对于stack我们可以使用python内置的list实现(也可以用链表实现),因为list是属于线性数组,在末尾插入和删除一个元素所使用的时间都是O(1),这非常符合stack的要求。代码:import datetime //显示时间引入的库 import time // from pip._vendor.distlib.compat import raw_input //使命令窗口不立即关闭引入的库 //栈类 class BinStack: def __init__(self): self.bs = [] //入栈 def push(self, e): self.bs.append(e) //出栈 def pop(self): if self.bs: return self.bs.pop() else: raise LookupError("stack is empty!") //检查栈是否为空,是返回False,不是返回True def isEmpty(self): return bool(self.bs) if __name__ == '__main__': binStack = BinStack() dec = int(input("请输入十进制整数:\n")) print("转换后的二进制数是:") while dec != 0: binStack.push(dec%2) dec //= 2 while binStack.isEmpty() == True: print("{}".format(binStack.pop()), end="") else: print("\n") //打印时间 datetime = datetime.datetime.now() print(datetime.strftime("%Y-%m-Ðb4a7d8a-5071-4084-94e2-a53e9bc61694n%H:%M:%S")) //使命令窗口不立即关闭 input("Press Enter to exit…")
-
列表和元组简介如果说在 Python 语言中找一个最优秀的数据类型,那无疑是列表,列表学习要点先看一遍列表定义:列表是可变序列,也是一种可存储任意数据类型的容器,用中括号([])表示开始和结束,内部各元素使用英文逗号(,)分隔,每个元素都可称为项目,并且每个元素都有一个索引,也被称为下标。列表的声明语法声明一个列表,可以参考下述几种格式。使用空中括号 [] 声明一个空列表my_list = [] print(my_list) 声明包含一个元素的列表my_list = [1] print(my_list) 声明包含多个元素的列表my_list = [1,2] print(my_list) 声明包含多个不同数据类型元素的列表my_list = [1,'a',True] print(my_list) 声明一个列表中包含列表my_list = [1,['a'],[True,1,1]] print(my_list) 列表的读取读取列表中最重要的概念是下标,也叫做位置或者索引。下标从 0 开始计数,即列表内第一项元素的索引是 0,例如下述代码,读取数字 2。12my_list = [1,2,3,4,5]print(my_list[1]) # 数字2所在的下标为1列表操作列表是一个动态容器,其支持对其元素的增加,删除,修改,查询,合并等操作,用到的都是字典对象的方法,基本操作的方法名如下所示:append():末尾追加元素;extend():末尾追加列表,也可以理解为两个列表合并;insert():在指定位置插入元素;copy():列表复制;clear():清空列表;count():统计列表指定元素个数;pop():删除并返回指定下标对应的元素;remove():删除列表中指定元素;index():获取指定元素的下标;reverse():反转元素;sort():对列表元素进行排序。列表元素添加方法从上述清单中,可以查看到列表追加元素,有两种办法可以实现,其一是使用 append() 方法,其二是使用 insert() 方法,示例代码如下所示:my_list = [1,2,3,4,5]my_list.append(888)my_list.insert(1,666)print(my_list)对比一下上述两个方法的差异,可以看到 append() 仅能在里列表末尾追加元素,而 insert() 方法可以在任意位置插入元素,即 insert() 方法的第一个参数为索引,表示插入位置。列表元素查找方法在列表中查找某一元素,使用 index() 方法实现,该方法的语法格式如下所示:1my_list.index(value,[start[,stop]])其中 my_list 是待查找目标列表,value 表示待查找的值,start 和 stop 为可选参数,表示开始查找的索引值和结束查找的索引值,该方法当查找到元素后,会返回第一个找到的元素索引位置,例如下述代码,会返回 3。my_list = [1,2,3,4,5]ret = my_list.index(4)print(ret)如果该方法没有在目标列表中找到元素,会报错,错误类型为 ValueError。除 index() 方法外,列表的读取其实也是元素查找方式,例如读取下标 2 的元素,代码如下:my_list = [1,2,3,4,5]ret = my_list[2]print(ret)在列表中还有一个重要知识点,即列表切片,学习该知识点需要先牢牢掌握列表按索引读取相关语法,切片的语法格式如下:my_list = [1,2,3,4,5]ret = my_list[1:3:2]print(ret)可以看到上述第二行代码,在原列表读取的规则之上,格式变为了 [1:3:2],将其转换为中文语法说明如下所示:1my_list[起始索引:结束索引:步长]使用切片的时候,英文冒号不能缺少,起始索引为必选项,结束索引和步长为可选项。如果理解困难,最好的办法就是反复用代码校验。# 缺省结束索引,默认获取到列表结尾元素my_list = [1,2,3,4,5,6,7,8,9,10]ret = my_list[1:]print(ret) # 输出 [2, 3, 4, 5, 6, 7, 8, 9, 10]# 缺少步长,默认按照索引+1解决,同时不包含结束索引代表的元素my_list = [1,2,3,4,5,6,7,8,9,10]ret = my_list[1:5]print(ret) # 输出 [2, 3, 4, 5]# 步长设置为2,表示索引每次+2my_list = [1,2,3,4,5,6,7,8,9,10]ret = my_list[1:6:2]print(ret) # 输出 [2, 4, 6]
-
介绍众所周知,计算机视觉在机器学习和人工智能领域获得了巨大的普及。图像识别技术允许计算机处理比人眼更多的信息,通常更快、更准确,或者只是在人们不参与观看的情况下处理。因此,你可能想知道机器如何学习和解释视觉世界。在本文中,我将介绍如何使用 Python 的 OpenCV 库开始处理图像和视频。我们将涵盖以下主题:计算机视觉简介OpenCV 库及其应用简介如何使用 OpenCV 库处理图像和视频计算机视觉它是人工智能和计算机科学的一个领域,训练计算机理解视觉世界。它是机器学习的主要组成部分之一。它处理自然世界的图像(高维数据)。它执行各种任务,例如获取、分析和处理以理解图像并将其转换为数字或符号信息。当今的计算机视觉算法基于模式识别,通常依赖于卷积神经网络 (CNN)。由于该领域的各种进步,计算机视觉正在蓬勃发展,并且它的受欢迎程度在过去几年中呈指数增长。计算机视觉的应用范围从缺陷检测到入侵者检测、口罩检测到肿瘤检测、作物监测到植物监测、车辆分类到交通流量分析等。该技术主要应用于零售和制造、交通、媒体、农业、医疗保健、体育、银行、增强现实、家庭安全等。OpenCVPython 包含一个名为 OpenCV 的库,用于在计算机视觉领域工作。它是一个开源库,于 1999 年推出。我们可以执行图像处理、图像分析、视频分析等任务。该库主要用 C++ 编写,具有 C++、Python、Java 和 MATLAB 等接口。应用:2D 和 3D 特征工具包视频/图像搜索检索人脸识别系统手势识别移动机器人对象识别医学影像分析运动追踪增强现实使用 OpenCV 处理图像在处理图像时,OpenCV 有许多可以对图像执行的操作。其中,我将讨论:读取图像调整图像大小旋转图像翻转图像重写图像裁剪图像在图像上绘制各种形状1. 从文件中读取图像使用函数imread()读取图片 (支持BMP、jpeg、tiff、png、便携图片格式等)为了显示我们在上一步中读取的图像,我们使用函数“imshow()”。这个函数的第一个参数是标题,第二个是我们读到的图像。waitkey() 函数显示一个窗口几毫秒。毫秒数作为参数传递给函数。如果 0 作为参数传递,它将永远等待,直到按下任何键。最后,destroyAllWindows() 将图像窗口显示后从内存中删除。例子:python 代码:import cv2 img=cv2.imread('img.jpeg') cv2.imshow('Image',img) cv2.waitKey() cv2.destroyAllWindows()2. 调整图像大小:在图像处理中,经常需要调整图像的大小。OpenCV 为我们提供了几种轻松重新缩放图像的方法。让我们通过一个例子来理解。例子:img2=cv2.resize(img,(400,400)) #resize by a fraction of original size img3=cv2.resize(img,(0,0),fx=0.5,fy=0.6) #using INTER_AREA to shrink the image img4=cv2.resize(img,(600,700),interpolation=cv2.INTER_AREA)安装使用 pip 命令可以轻松安装 OpenCV,如下所示1pip install opencv-python3. 旋转图像使用 OpenCV 旋转图像的语法是1M=cv2.getRotationMatrix2D(center, angle,scale)然后我们使用方法1cv2.wrapAffine(src,M, (h,w))让我们通过一个例子来深入了解:例子:#calculate height and width to get center (h,w)=img.shape[:2] center=(w/2,h/2) #rotate by 90 degrees M = cv2.getRotationMatrix2D(center, 90, 1.0) img90 = cv2.warpAffine(img, M, (h, w)) #rotate by 180 degrees M = cv2.getRotationMatrix2D(center, 180, 1.0) img180 = cv2.warpAffine(img, M, (h, w)) #rotate by 270 degrees M = cv2.getRotationMatrix2D(center, 270, 1.0) img270 = cv2.warpAffine(img, M, (h, w))4. 翻转图像:要翻转图像,我们使用函数 cv2.flip() 并传递参数,即图像和翻转代码(水平或垂直)例子:#flip- vertical axes img=cv2.flip(img,0) #flip- horizontal axes img=cv2.flip(img,1)5. 重写图像要将图像重写为新文件,我们使用函数 imwrite() 如下:cv2.imwrite('new_img.jpg',img)6. 裁剪图像#crop from top img=img[0:100,0:100] #crop by specifying height and width img=img[50:200,50:100]7. 绘制形状使用 OpenCV,我们可以使用不同的函数在图像上快速绘制各种形状,如圆形、矩形、多边形等。让我们用一个例子来理解:例子:#creating a blank image import cv2 as cv2 import numpy as np img=np.zeros((500,500,3),dtype=float) #changing the color of the image to green img[:]=0,255,0 #Red img[:]=0,0,255#changing the color of a particular portion img[200:300,300:450]=0,255,0 #drawing a rectangle cv2.rectangle(img,(100,100),(180,180),color=(255,0,0),thickness=5) #draw a circle with filling the color cv2.circle(img,center=(100,300),radius=60,color=(0,255,0),thickness=-1) #drawing a line cv2.line(img,(0,0),(317,356),thickness=3,color=(0,255,0)) #adding text cv2.putText(img,org=(50,50),fontScale=3,color=(255,0,0) ,thickness=2,lineType=cv2.LINE_AA,text="IMAGES", fontFace=cv2.FONT_HERSHEY_COMPLEX_SMALL) cv2_imshow(img) cv2.waitKey(0)frame.shape (2160, 3840, 3) plt.imshow(frame) plt.show()使用 OpenCV 处理视频视频是帧序列或图像序列。图像通常采用 BGR(蓝、绿、红)的形式。每个像素的值都在 0-255 之间。要开始使用 OpenCV 处理视频,我们使用以下函数:Cv2.VideoCapture():它建立与视频的连接。它带有一个参数,该参数指示是使用内置摄像头还是附加摄像头。值“0”表示内置摄像头。Cap.read():这个方法可以让我们得到一个帧。Cv2.cvtColor():允许你更改图像使用的颜色模型。这包括从 BGR 转换为 RGB 和灰度。在处理视频方面,在本文中,我们将学习如何捕获视频帧的不同属性读取视频文件写视频1. 捕获视频帧的属性:让我们看几个捕获视频属性的示例。要捕获帧形状:frame.shape (2160, 3840, 3) plt.imshow(frame) plt.show()为了捕捉视频,我们使用函数 cv2.VideoCapture()12cap=cv2.VideoCapture('/content/video.mp4')cap.read()要获取框架的高度,我们使用 cap.get() 函数如下:12#heightcap.get(cv2.CAP_PROP_FRAME_HEIGHT)为了获得框架的宽度,我们使用:12#widthcap.get(cv2.CAP_PROP_FRAME_WIDTH)要获取帧数,我们使用函数 cap.get() 如下:1#number of frames1cap.get(cv2.CAP_PROP_FRAME_COUNT)为了获得每秒的帧数,我们使用12#number of frames per seccap.get(cv2.CAP_PROP_FPS)2. 读取视频文件导入 cv2然后我们使用函数 cv2.VideoCapture() 来捕捉视频。接下来,我们循环遍历每一帧并使用函数 cap.read() 读取帧。为了显示每一帧,我们使用方法 cv2.imshow()。最后,我们使用 waitKey() 函数中断循环,当用户按下任意键时,该函数会中断循环。destroyAllWindows() 函数将关闭窗口。例子:#importing dependencies import cv2 from matplotlib import pyplot as plt #establish capture cap=cv2.VideoCapture('/content/video.mp4') #loop through each frame while(cap.isOpened()): ret,frame=cap.read() frame=cv2.resize(frame,(1200,700)) cv2.imshow(‘Video',frame) if cv2.waitKey(10) & 0xFF == ord('q'): break #close down everything cap.release() cv2.destroyALLWindows()3. 编写视频文件导入 cv2使用函数 cv2.VideoCapture() 捕获视频然后我们使用函数 cv2.VideoWriter 来编写视频。该函数将参数作为cv2.VideoWriter(filename, fourcc, fps, framesize)filename - 捕获的输入视频文件Fourcc - 用于指定视频编解码器的代码fps - 每秒帧数framesize - 视频框的高度和宽度接下来,我们循环遍历每一帧并使用对象 video_writer 来写入帧。最后,我们使用 waitKey() 函数来打破循环使用函数 destroyAllWindows() 关闭窗口import cv2 from google.colab.patches import cv2_imshow cap=cv2.VideoCapture('/content/video.mp4') height=int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) width=int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) fps=int(cap.get(cv2.CAP_PROP_FPS)) frame_size = (width,height) video_writer= cv2.VideoWriter('/content/output.avi',cv2.VideoWriter_fourcc('M','J','P','G'), fps, frame_size) for frame_idx in range(int(cap.get(cv2.CAP_PROP_FRAME_COUNT))): ret,frame=cap.read() gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) video_writer.write(gray) if cv2.waitKey(10) & 0xFF== ord('q'): break cap.release() cv2.destroyALLWindows()
-
OpenCV 简介图像可以进行算术运算,例如加法、减法和按位运算(AND、OR、NOT、XOR)。这些操作可以帮助改善输入图像的属性。图像算法对于分析输入图像的属性是必要的,可以将操作后的图像用作增强的输入图像,并且可以对图像应用更多操作,以进行阈值化、膨胀等。图像算术是将一幅或多幅图像应用于标准算术运算或逻辑运算符之一。运算符是逐个像素应用的,因此输出图像中像素的值仅由输入图像中相应像素的值决定。因此,图像通常必须具有相同的大小。当向图像添加恒定偏移量时,输入图像之一可能是恒定值。虽然图像算法是图像处理的最基本形式,但它有很多应用。算术运算符的一个显着优势是该过程简单明了,因此速度很快。添加图像在其最基本的形式中,该运算符将两个相同大小的图像作为输入,并输出与前两个相同大小的第三个图像,每个像素值是两个输入图像中每个图像中对应像素值的总和. 更高级的版本允许在一次操作中组合多个图像。运算符的一个常见变体只是允许向每个像素添加一个指定的常数。使用函数 cv2.add(),我们可以添加两个图像。这直接将两个图像中的图像像素相加。1Syntax: cv2.add(image1, image2)但是,添加像素并不是一个理想的情况。因此,我们使用 cv2.addweighted()。请记住,两个输入图像的形状和颜色通道必须相同。1Syntax: cv2.add Weighted(image1, weight1, Image2, weight2, gammaValue)参数:image1:第一个图像数组输入weight 1:输入图像中第一个用于最终图像的图像元素的权重。image2:第二个图像数组输入weight 2:将第二输入图像元素的权值应用于最终图像的伽马值。gammaValue:光测量。加法代码图像减法像素减法算子将两幅图像作为输入并输出第三幅图像,其像素值是第一幅图像的像素值减去第二幅图像的相应像素值。使用单个图像作为输入是常见的,从所有像素中减去一个常数值也是常见的。一些版本的运算符将简单地输出像素值之间的绝对差,而不是直接的有符号输出。1Syntax: cv2.subtract(image1, image2)参数:图 1:第一个图像数组输入(单通道、8 位或浮点)图 2:第二个图像阵列输入(单通道、8 位或浮点)代码 :import cv2 import numpy as np image1 = cv2.imread('input1.jpg') image2 = cv2.imread('input2.jpg') sub = cv2.subtract(image1, image2) cv2.imshow('Subtracted Image', sub) cv2.waitKey(0)位运算位运算用于图像处理以提取重要部分。本文中使用了以下按位运算:ANDORNOTXR位运算对于图像遮罩也很有用。这些操作可用于启用图像创建。这些操作可以帮助改善输入图像的属性。注意:按位运算只能在相同尺寸的输入图像上执行。图像的 AND 位运算AND 运算符(以及类似方式的 NAND 运算符)通常将两个二进制或整数灰度级图像作为输入,并生成第三个图像,其像素值只是第一个图像的像素值与来自第二个图像的相应像素相乘。可以修改此运算符以通过获取单个输入图像,并将每个像素与预定的常数值进行与运算来产生输出。1Syntax: cv2.bitwise_and(Image1, Image2, destination, mask)参数:Image1:第一个输入图像 numpy 数组Image1:第二个输入图像numpy数组destination:输出数组mask: 操作掩码图像代码 :import cv2 import numpy as np img1 = cv2.imread('input1.png') img2 = cv2.imread('input2.png') dest_and = cv2.bitwise_and(img2, img1, mask = None) cv2.imshow('Bitwise And', dest_and) cv2.waitKey(0)图像的 OR 位运算OR 运算符通常将两个二进制或灰度图像作为输入,并输出第三个图像,其像素值是第一个图像的像素值与来自第二个图像的相应像素进行或运算。该运算符的一个变体采用单个输入图像并将每个像素与一个常数值进行 OR 运算以生成输出。1Syntax: cv2.bitwise_or(source1, source2, destination, mask)参数:source1 :第一个输入 numpy 图像数组source2 :第二个输入 numpy 图像数组目的地:输出数组图像mask :操作掩码,输入/输出 8 位单通道掩码。代码 :import cv2 import numpy as np img1 = cv2.imread('input1.png') img2 = cv2.imread('input2.png') dest_or = cv2.bitwise_or(img1, img2, mask = None) cv2.imshow('Bitwise OR', dest_or) cv2.waitKey(0)图像的NOT位运算逻辑非,也称为反转,是一种将二值或灰度图像作为输入并生成其照相底片的运算符。1Syntax: cv2.bitwise_not(Image1,Destination, mask)参数:Image1: 输入图像数组Destination:输出数组图像mask: 操作掩码代码 :import cv2 import numpy as np img1 = cv2.imread('input1.png') dest_not = cv2.bitwise_not(img1, mask = None) cv2.imshow('Bitwise Not', dest_not) cv2.waitKey(0)图像的 XR 位运算至关重要的是,正在处理的所有输入像素值都具有相同的位数,否则可能会出现意外结果。当输入图像中的像素值不是简单的 1 位数字时,XOR 操作通常(但不总是)对像素值中的每个对应位按位执行。1Syntax: cv2.bitwise_xor(source1, source2, destination, mask)参数:source1 :第一个输入图像数组(单通道、8 位或浮点)source2 :第二个输入图像数组(单通道、8 位或浮点)目的地:输出图像数组mask :操作掩码,输入/输出8位单通道掩码。代码 :import cv2 import numpy as np img1 = cv2.imread('input1.png') img2 = cv2.imread('input2.png') dest_or = cv2.bitwise_xor(img1, img2, mask = None) cv2.imshow('Bitwise XOR', dest_xor) cv2.waitKey(0)import cv2 import numpy as np image1 = cv2.imread('input1.jpg') image2 = cv2.imread('input2.jpg') weightedSumadd = cv2.addWeighted(image1, 0.6, image2, 0.4, 0) cv2.imshow('Weighted Image', weightedSumadd) cv2.waitKey(0) cv2.destroyAllWindows()
-
一般来说,保存模型是把参数全部用model.cpu().state_dict(),然后加载模型时一般用model.load_state_dict(torch.load(model_path)),下面这篇文章主要给大家介绍了关于pytorch模型保存与加载中的一些问题实战记录,需要的朋友可以参考下前言最近使用pytorch训练模型,保存模型后再次加载使用出现了一些问题。记录一下解决方案!一、torch中模型保存和加载的方式1、模型参数和模型结构保存和加载torch.save(model,path) torch.load(path)2、只保存模型的参数和加载——这种方式比较安全,但是比较稍微麻烦一点点torch.save(model.state_dict(),path) model_state_dic = torch.load(path) model.load_state_dic(model_state_dic)二、torch中模型保存和加载出现的问题1、单卡模型下保存模型结构和参数后加载出现的问题模型保存的时候会把模型结构定义文件路径记录下来,加载的时候就会根据路径解析它然后装载参数;当把模型定义文件路径修改以后,使用torch.load(path)就会报错。把model文件夹修改为models后,再加载就会报错。import torch from model.TextRNN import TextRNN load_model = torch.load('experiment_model_save/textRNN.bin') print('load_model',load_model)这种保存完整模型结构和参数的方式,一定不要改动模型定义文件路径。2、多卡机器单卡训练模型保存后在单卡机器上加载会报错在多卡机器上有多张显卡0号开始,现在模型在n>=1上的显卡训练保存后,拷贝在单卡机器上加载import torch from model.TextRNN import TextRNN load_model = torch.load('experiment_model_save/textRNN_cuda_1.bin') print('load_model',load_model)会出现cuda device不匹配的问题——你保存的模代码段 小部件型是使用的cuda1,那么采用torch.load()打开的时候,会默认的去寻找cuda1,然后把模型加载到该设备上。这个时候可以直接使用map_location来解决,把模型加载到CPU上即可。load_model = torch.load('experiment_model_save/textRNN_cuda_1.bin',map_location=torch.device('cpu'))3、多卡训练模型保存模型结构和参数后加载出现的问题当用多GPU同时训练模型之后,不管是采用模型结构和参数一起保存还是单独保存模型参数,然后在单卡下加载都会出现问题a、模型结构和参数一起保然后在加载torch.distributed.init_process_group(backend='nccl')模型训练的时候采用上述多进程的方式,所以你在加载的时候也要声明,不然就会报错。b、单独保存模型参数model = Transformer(num_encoder_layers=6,num_decoder_layers=6) state_dict = torch.load('train_model/clip/experiment.pt') model.load_state_dict(state_dict)同样会出现问题,不过这里出现的问题是参数字典的key和模型定义的key不一样原因是多GPU训练下,使用分布式训练的时候会给模型进行一个包装,代码如下:model = torch.load('train_model/clip/Vtransformers_bert_6_layers_encoder_clip.bin') print(model) model.cuda(args.local_rank) 。。。。。。 model = nn.parallel.DistributedDataParallel(model,device_ids=[args.local_rank],find_unused_parameters=True) print('model',model)在外层多了DistributedDataParallel以及module,所以才会导致在单卡环境下加载模型权重的时候出现权重的keys不一致。三、正确的保存模型和加载的方法 if gpu_count > 1: torch.save(model.module.state_dict(),save_path) else: torch.save(model.state_dict(),save_path) model = Transformer(num_encoder_layers=6,num_decoder_layers=6) state_dict = torch.load(save_path) model.load_state_dict(state_dict)
-
一、selenium的安装以及简单应用我们以谷歌浏览器的chromedriver为例1、在Python虚拟环境中安装selenium模块pip/pip3 install selenium2、下载版本符合的webdriver以chrome谷歌浏览器为例查看谷歌浏览器的版本鼠标点击右上角的竖排的三个点,然后选择“帮助”,选择“关于 Google Chrome”,进去之后即可查看谷歌浏览器的版本访问下载chromedriver网站http://chromedriver.storage.googleapis.com/index.html点击notes.txt进入版本说明页面 查看chrome和chromedriver匹配的版本根据操作系统下载正确版本的chromedriver解压压缩包后获取python代码可以调用的谷歌浏览器的webdriver可执行文件windows为 chromedriver.exelinux和macos为 chromedriverchromedriver环境的配置windows环境下需要将 chromedriver.exe 所在的目录设置为path环境变量中的路径linux/mac环境下,将 chromedriver 所在的目录设置到系统的PATH环境值中3、chromedriver环境配置的教程windows环境下将 chromedriver.exe 所在的目录设置为path环境变量中的路径的过程鼠标右键点击“Google Chrome” ,然后点击“打开文件所在位置”复制 chrome.exe 所在的文件路径接着打开“控制面板” 搜索输入 “环境变量” 并搜索,然后点击 “编辑系统环境变量”二、selenium的简单使用Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的。Selenium 可以直接调用浏览 器,它支持所有主流的浏览器(包括PhantomJS这些无界面的浏览器),可以接收指令,让浏览器自动加载页 面,获取需要的数据,甚至页面截屏等。我们可以使用selenium很容易完成之前编写的爬虫,接下来我们就来 看一下selenium的运行效果接下来我们就通过代码来模拟百度搜索(展示效果)123456789101112131415161718import time from selenium import webdriver # 通过指定chromedriver的路径来实例化driver对象,chromedriver放在当前目录。 # driver = webdriver.Chrome(executable_path='./chromedriver') # 这里的chromedriver已经添加环境变量 driver = webdriver.Chrome() # 控制浏览器访问url地址 driver.get("https://www.baidu.com/") time.sleep(3)# 在百度搜索框中搜索'python' driver.find_element_by_id('kw').send_keys('python') # 点击'百度搜索' driver.find_element_by_id('su').click() time.sleep(6) # 退出浏览器 driver.quit()webdriver.Chrome(executable_path='./chromedriver') 中executable参数指定的是下载好的chromedriver文件的路径driver.find_element_by_id('kw').send_keys('python') 定位id属性值是'kw'的标签,并向其中输入字符 串'python'driver.find_element_by_id('su').click() 定位id属性值是su的标签,并点击click函数作用是:触发标签的js的click事件三、selenium提取数据1、driver对象常用的属性和方法在使用selenium过程中,实例化driver对象后,driver对象有一些常用的属性和方法driver.page_source 获取当前标签页浏览器渲染之后的网页源代码driver.current_url获取当前标签页的urldriver.close() 关闭当前标签页,如果只个一个标签页则关闭整个浏览器driver.quit() 关闭浏览器driver.forward() 页面前进driver.back() 页面后退driver.screen_shot(img_name) 页面截图示例打印当前标签页的urlimport time from selenium import webdriver driver = webdriver.Chrome() # 控制浏览器访问url地址 driver.get("https://www.baidu.com/") time.sleep(3) # 打印当前标签页的url print(driver.current_url) driver.quit()2、driver对象定位标签元素获取标签对象的方法在selenium中可以通过多种方式来定位标签,返回标签元素对象方式功能find_element_by_id返回一个元素find_element(s)_by_class_name根据类名获取元素列表find_element(s)_by_name根据标签的name属性值返回包含标签对象元素的列表find_element(s)_by_xpath返回一个包含元素的列表find_element(s)_by_link_text根据连接文本获取元素列表find_element(s)_by_partial_link_text根据链接包含的文本获取元素列表find_element(s)_by_tag_name;根据标签名获取元素列表find_element(s)_by_css_selector根据css选择器来获取元素列表注意find_element和find_elements的区别:多了个s就返回列表,没有s就返回匹配到的第一个标签对象find_element匹配不到就抛出异常,find_elements匹配不到就返回空列表by_link_text 和 by_partial_link_tex 的区别:全部文本和包含某个文本以上函数的使用方法:driver.find_element_by_id('id_str')id_str是id值示例接下来我们就通过代码来模拟百度搜索(具体讲解)首先我们先打开百度页面,然后点击网页检查 ,定位搜索框,可以看见搜索框的input标签的id值为kw于是开始编写基础代码通过driver.get()获取网页通过find_element_by_id('kw')定位搜索框通过.send_keys('python')向搜索框输入搜索信息import time from selenium import webdriver driver = webdriver.Chrome() # 控制浏览器访问url地址 driver.get("https://www.baidu.com/") time.sleep(3) # 在百度搜索框中搜索'python' driver.find_element_by_id('kw').send_keys('python')完善代码,通过 .click() 实现点击搜索import time from selenium import webdriver driver = webdriver.Chrome() # 控制浏览器访问url地址 driver.get("https://www.baidu.com/") time.sleep(3) # 在百度搜索框中搜索'python' driver.find_element_by_id('kw').send_keys('python') # 点击'百度搜索' driver.find_element_by_id('su').click() time.sleep(6) # 退出浏览器 driver.quit()3、标签对象提取文本内容和属性值find_element仅仅能够获取元素,不能够直接获取其中的数据,如果需要获取数据需要使用以下方法对元素执行点击操作: element.click()对定位到的标签对象进行点击操作向输入框输入数据: element.send_keys(data)对定位到的标签对象输入数据获取文本: element.text通过定位获取的标签对象的 text 属性,获取文本内容获取属性值: element.get_attribute("属性名")通过定位获取的标签对象的 get_attribute 函数,传入属性名,来获取属性的值import time from selenium import webdriver driver = webdriver.Chrome() # 控制浏览器访问url地址 driver.get("https://www.baidu.com/") time.sleep(3) # 点击'百度搜索',用ele变量接受获取的元素 ele = driver.find_element_by_id('su') print(ele.get_attribute('value')) time.sleep(6) # 退出浏览器 driver.quit()四、selenium无头模式我们知道,当我们利用 dirver.get() 获取网页时会自动打开一个网页,但是有时候我们可能不需要通过打开浏览器获取数据,于是就可以通过给driver对象设置无头模式 。# 给driver对象设置无头模式 op = webdriver.ChromeOptions() op.add_argument('--headless') driver = webdriver.Chrome(options=op)
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签