-
前言 本程序主要讲述python的AI视觉方面的应用:自动驾驶寻找车道。 推荐博客好文章 (上过csdn热榜top5的优质好文!) 1.若不知道怎么安装opencv或者使用的请看我的这篇文章(曾上过csdn综合热榜的top1): python进阶——人工智能视觉识别_lqj_本人的博客-CSDN博客 2.基于opencv的人工智能视觉实现的目标实时跟踪功能(曾上过csdn综合热榜的top5): python进阶——人工智能实时目标跟踪_lqj_本人的博客-CSDN博客 3.基于PaddlenHub模块以及playsound模块实现口罩检测并实时语音报警(曾上过csdn综合热榜的top1): python进阶——AI视觉实现口罩检测实时语音报警系统_lqj_本人的博客-CSDN博客 项目前须知 1.opencv的图像灰度转化方法 gray = cv2.cvtColor("图像", cv2.COLOR_RGB2GRAY) 2.opencv检测图像边缘 高斯模糊图像 cv2.GaussianBlur(gray, (5, 5), 0) 获取精明图像 canny = cv2.Canny(blur, 50, 150) 3.matplotlib绘制图像库的使用 项目详情 我们先拿到实时摄像的某一帧的图像 导入库 import cv2 import numpy as np import matplotlib.pyplot as plt 边缘检测 进行图像的灰度转化以及图像的边缘检测 def canny(image): """1.图像的灰度转化""" #把某一帧的图片转换成灰度图像 gray = cv2.cvtColor(lane_image, cv2.COLOR_RGB2GRAY) """2.检测图像边缘""" #高斯模糊图像 blur = cv2.GaussianBlur(gray, (5, 5), 0) #获取精明的图片 canny = cv2.Canny(blur, 50, 150) return canny image = cv2.imread('1.jpg') lane_image = np.copy(image) canny = canny(lane_image) plt.imshow(canny) plt.show() 得到绘图结果 因为中国的车道时沿右边行驶的,所以我们可以在绘图的图像中清楚的看见X轴与Y轴的数码,由X轴的(400,0)位置到X轴的大约(1100,0)位置是右车道的宽度,然后我们再来看Y轴的数码,大约在150的位置是我们可视范围内的右车道的尽头点,又因为(400,0)到(1100,0)的距离为700px,所以我们可以得到可视范围内的右车道的尽头点为(700,150)。 根据上述位置的计算,我们可以得出一个右车道中的三角形 def region_of_interest(image): height = image.shape[0] polygons = np.array([ [(400,height),(1100,height),(700,150)] ]) mask = np.zeros_like(image) cv2.fillPoly(mask,polygons,255) return mask image = cv2.imread('1.jpg') lane_image = np.copy(image) canny = canny(lane_image) cv2.imshow('result',region_of_interest(canny)) cv2.waitKey(0) 得出检测三角形 生成蒙版 将检测到的图像由255(白色)表示,周围区域用0(黑色表示) 有时候三角形不是正好与我们看到的进到点到左右两侧点的形状正好相似,所以我们需要自己微调一下 polygons = np.array([ [(400,height),(1200,height),(800,200)] ]) 然后,我们可以对我们的图像进行右车道三角形的裁剪 masked_image = cv2.bitwise_and(image,mask) cropped_image = region_of_interest(canny) cv2.imshow('result',cropped_image) 边缘检测与蒙版产生的效果 裁剪显示图像 定义车道起始点位置 def make_coordinates(image,line_parameters): slope,intercept = line_parameters print(image.shape) y1 = image.shape[0] y2 = int(y1*(3/5)) x1 = int((y1 - intercept)/slope) x2 = int((y2 - intercept)/slope) return np.array([x1,y1,x2,y2]) 霍夫变换的直线检测 用到的是Opencv封装好的函数cv.HoughLinesP函数,使用到的参数如下: image:输入图像,通常为canny边缘检测处理后的图像 rho:线段以像素为单位的距离精度 theta:像素以弧度为单位的角度精度(np.pi/180较为合适) threshold:霍夫平面累加的阈值 minLineLength:线段最小长度(像素级) maxLineGap:最大允许断裂长度 lines = cv2.HoughLinesP(cropped_image, 2, np.pi/180, 100, np.array([]), minLineLength=40, maxLineGap=5) 绘制车道 def display_lines(image,lines): line_image = np.zeros_like(image) if lines is not None: for line in lines: # print(line) x1,y1,x2,y2 = line.reshape(4) cv2.line(line_image,(x1,y1),(x2,y2),(255,100,10),10) return line_image 效果图像 图像与绘制车道融合 视频流中位置检测 def average_slope_intercept(image,lines): left_fit = [] right_fit = [] if lines is None: return None for line in lines: x1,y1,x2,y2 = line.reshape(4) parameters = np.polyfit((x1,x2),(y1,y2),1) # print(parameters) slope = parameters[0] intercept = parameters[1] if slope < 0: left_fit.append((slope,intercept)) else: right_fit.append((slope,intercept)) print(left_fit) print(right_fit) 打印左右位置结果 检测数每一帧的左右位置结果 left_fit_average = np.average(left_fit,axis=0) right_fit_average = np.average(right_fit,axis=0) print(left_fit_average,'左') print(right_fit_average,'右') left_line = make_coordinates(image,left_fit_average) right_line = make_coordinates(image,right_fit_average) return np.array([left_line,right_line]) 导入视频流做最后处理 cap = cv2.VideoCapture('3.mp4') # try: while cap.isOpened(): _,frame = cap.read() canny_image = canny(frame) cropped_image = region_of_interest(canny_image) lines = cv2.HoughLinesP(cropped_image, 2, np.pi/180, 100, np.array([]), minLineLength=40, maxLineGap=5) averaged_lines = average_slope_intercept(frame, lines) line_image = display_lines(frame, averaged_lines) combo_image = cv2.addWeighted(frame, 0.8, line_image, 1, 1) # cv2.resizeWindow("result", 1080, 960); cv2.imshow('result', line_image) cv2.waitKey(10) 完整代码 import cv2 import numpy as np import matplotlib.pyplot as plt def make_coordinates(image,line_parameters): slope,intercept = line_parameters print(image.shape) y1 = image.shape[0] y2 = int(y1*(3/5)) x1 = int((y1 - intercept)/slope) x2 = int((y2 - intercept)/slope) return np.array([x1,y1,x2,y2]) def average_slope_intercept(image,lines): left_fit = [] right_fit = [] if lines is None: return None for line in lines: x1,y1,x2,y2 = line.reshape(4) parameters = np.polyfit((x1,x2),(y1,y2),1) # print(parameters) slope = parameters[0] intercept = parameters[1] if slope < 0: left_fit.append((slope,intercept)) else: right_fit.append((slope,intercept)) # print(left_fit) # print(right_fit) left_fit_average = np.average(left_fit,axis=0) right_fit_average = np.average(right_fit,axis=0) print(left_fit_average,'左') print(right_fit_average,'右') left_line = make_coordinates(image,left_fit_average) right_line = make_coordinates(image,right_fit_average) return np.array([left_line,right_line]) def canny(image): """1.图像的灰度转化""" #把某一帧的图片转换成灰度图像 gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) """2.检测图像边缘""" #高斯模糊图像 blur = cv2.GaussianBlur(gray, (5, 5), 0) #获取精明的图片 canny = cv2.Canny(blur, 50, 150) return canny #每一行都是一个二维数组,包含我们的线坐标,形式为[[x1,yl,x2,y2]]。这些坐标指定了线条的参数,以及线条相对与图像空间位置,确保他们被放置在正确的位置 def display_lines(image,lines): line_image = np.zeros_like(image) if lines is not None: for line in lines: # print(line) x1,y1,x2,y2 = line.reshape(4) cv2.line(line_image,(x1,y1),(x2,y2),(255,100,10),10) return line_image def region_of_interest(image): height = image.shape[0] polygons = np.array([ [(300,height),(650,height),(500,150)] ]) mask = np.zeros_like(image) cv2.fillPoly(mask,polygons,255) masked_image = cv2.bitwise_and(image,mask) return masked_image # image = cv2.imread('1.png') # lane_image = np.copy(image) # canny_image = canny(lane_image) # cropped_image = region_of_interest(canny_image) # lines = cv2.HoughLinesP(cropped_image,2,np.pi/180,100,np.array([]),minLineLength=40,maxLineGap=5) # averaged_lines = average_slope_intercept(lane_image,lines) # line_image = display_lines(lane_image,averaged_lines) # combo_image = cv2.addWeighted(lane_image,0.8,line_image,1,1) # cv2.imshow('result',combo_image) # cv2.waitKey(0) cap = cv2.VideoCapture('3.mp4') # try: while cap.isOpened(): _,frame = cap.read() canny_image = canny(frame) cropped_image = region_of_interest(canny_image) lines = cv2.HoughLinesP(cropped_image, 2, np.pi/180, 100, np.array([]), minLineLength=40, maxLineGap=5) averaged_lines = average_slope_intercept(frame, lines) line_image = display_lines(frame, averaged_lines) combo_image = cv2.addWeighted(frame, 0.8, line_image, 1, 1) # cv2.resizeWindow("result", 1080, 960); cv2.imshow('result', combo_image) cv2.waitKey(10) 用前须知 根据自己的需要适当微调参数: def region_of_interest(image): height = image.shape[0] polygons = np.array([ [(300,height),(650,height),(500,150)] ]) mask = np.zeros_like(image) cv2.fillPoly(mask,polygons,255) masked_image = cv2.bitwise_and(image,mask) return masked_image 效果显示 ———————————————— 版权声明:本文为CSDN博主「lqj_本人」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/lbcyllqj/article/details/128937913
-
一.什么是python Python由荷兰数学和计算机科学研究学会的吉多·范罗苏姆于1990年代初设计,作为一门叫做ABC语言的替代品。 Python提供了高效的高级数据结构,还能简单有效地面向对象编程。Python语法和动态类型,以及解释型语言的本质,使它成为多数平台上写脚本和快速开发应用的编程语言, [ 随着版本的不断更新和语言新功能的添加,逐渐被用于独立的、大型项目的开发。 Python解释器易于扩展,可以使用C语言或C++(或者其他可以通过C调用的语言)扩展新的功能和数据类型。Python也可用于可定制化软件中的扩展程序语言。Python丰富的标准库,提供了适用于各个主要系统平台的源码或机器码 二.游戏代码效果呈现 三.游戏主代码 ''' Function: 炸弹人小游戏 ''' import sys import cfg import random import pygame from modules import * '''游戏主程序''' def main(cfg): # 初始化 pygame.init() pygame.mixer.init() pygame.mixer.music.load(cfg.BGMPATH) pygame.mixer.music.play(-1, 0.0) screen = pygame.display.set_mode(cfg.SCREENSIZE) pygame.display.set_caption('炸弹人') # 开始界面 Interface(screen, cfg, mode='game_start') # 游戏主循环 font = pygame.font.SysFont('Consolas', 15) for gamemap_path in cfg.GAMEMAPPATHS: # -地图 map_parser = mapParser(gamemap_path, bg_paths=cfg.BACKGROUNDPATHS, wall_paths=cfg.WALLPATHS, blocksize=cfg.BLOCKSIZE) # -水果 fruit_sprite_group = pygame.sprite.Group() used_spaces = [] for i in range(5): coordinate = map_parser.randomGetSpace(used_spaces) used_spaces.append(coordinate) fruit_sprite_group.add(Fruit(random.choice(cfg.FRUITPATHS), coordinate=coordinate, blocksize=cfg.BLOCKSIZE)) # -我方Hero coordinate = map_parser.randomGetSpace(used_spaces) used_spaces.append(coordinate) ourhero = Hero(imagepaths=cfg.HEROZELDAPATHS, coordinate=coordinate, blocksize=cfg.BLOCKSIZE, map_parser=map_parser, hero_name='ZELDA') # -电脑Hero aihero_sprite_group = pygame.sprite.Group() coordinate = map_parser.randomGetSpace(used_spaces) aihero_sprite_group.add(Hero(imagepaths=cfg.HEROBATMANPATHS, coordinate=coordinate, blocksize=cfg.BLOCKSIZE, map_parser=map_parser, hero_name='BATMAN')) used_spaces.append(coordinate) coordinate = map_parser.randomGetSpace(used_spaces) aihero_sprite_group.add(Hero(imagepaths=cfg.HERODKPATHS, coordinate=coordinate, blocksize=cfg.BLOCKSIZE, map_parser=map_parser, hero_name='DK')) used_spaces.append(coordinate) # -炸弹bomb bomb_sprite_group = pygame.sprite.Group() # -用于判断游戏胜利或者失败的flag is_win_flag = False # -主循环 screen = pygame.display.set_mode(map_parser.screen_size) clock = pygame.time.Clock() while True: dt = clock.tick(cfg.FPS) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit(-1) # --↑↓←→键控制上下左右, 空格键丢炸弹 elif event.type == pygame.KEYDOWN: if event.key == pygame.K_UP: ourhero.move('up') elif event.key == pygame.K_DOWN: ourhero.move('down') elif event.key == pygame.K_LEFT: ourhero.move('left') elif event.key == pygame.K_RIGHT: ourhero.move('right') elif event.key == pygame.K_SPACE: if ourhero.bomb_cooling_count <= 0: bomb_sprite_group.add(ourhero.generateBomb(imagepath=cfg.BOMBPATH, digitalcolor=cfg.YELLOW, explode_imagepath=cfg.FIREPATH)) screen.fill(cfg.WHITE) # --电脑Hero随机行动 for hero in aihero_sprite_group: action, flag = hero.randomAction(dt) if flag and action == 'dropbomb': bomb_sprite_group.add(hero.generateBomb(imagepath=cfg.BOMBPATH, digitalcolor=cfg.YELLOW, explode_imagepath=cfg.FIREPATH)) # --吃到水果加生命值(只要是Hero, 都能加) ourhero.eatFruit(fruit_sprite_group) for hero in aihero_sprite_group: hero.eatFruit(fruit_sprite_group) # --游戏元素都绑定到屏幕上 map_parser.draw(screen) for bomb in bomb_sprite_group: if not bomb.is_being: bomb_sprite_group.remove(bomb) explode_area = bomb.draw(screen, dt, map_parser) if explode_area: # --爆炸火焰范围内的Hero生命值将持续下降 if ourhero.coordinate in explode_area: ourhero.health_value -= bomb.harm_value for hero in aihero_sprite_group: if hero.coordinate in explode_area: hero.health_value -= bomb.harm_value fruit_sprite_group.draw(screen) for hero in aihero_sprite_group: hero.draw(screen, dt) ourhero.draw(screen, dt) # --左上角显示生命值 pos_x = showText(screen, font, text=ourhero.hero_name+'(our):'+str(ourhero.health_value), color=cfg.YELLOW, position=[5, 5]) for hero in aihero_sprite_group: pos_x, pos_y = pos_x+15, 5 pos_x = showText(screen, font, text=hero.hero_name+'(ai):'+str(hero.health_value), color=cfg.YELLOW, position=[pos_x, pos_y]) # --我方玩家生命值小于等于0/电脑方玩家生命值均小于等于0则判断游戏结束 if ourhero.health_value <= 0: is_win_flag = False break for hero in aihero_sprite_group: if hero.health_value <= 0: aihero_sprite_group.remove(hero) if len(aihero_sprite_group) == 0: is_win_flag = True break pygame.display.update() clock.tick(cfg.FPS) if is_win_flag: Interface(screen, cfg, mode='game_switch') else: break Interface(screen, cfg, mode='game_end') '''run''' if __name__ == '__main__': while True: main(cfg) 四.cfg '''配置文件''' import os '''屏幕大小''' SCREENSIZE = (640, 480) '''块大小''' BLOCKSIZE = 30 '''FPS''' FPS = 30 '''游戏地图路径''' GAMEMAPPATHS = [os.path.join(os.getcwd(), path) for path in \ ['resources/maps/1.map', 'resources/maps/2.map']] '''墙路径''' WALLPATHS = [os.path.join(os.getcwd(), path) for path in \ ['resources/images/misc/wall0.png', 'resources/images/misc/wall1.png', 'resources/images/misc/wall2.png']] '''英雄路径''' HERODKPATHS = [os.path.join(os.getcwd(), path) for path in \ ['resources/images/dk/left.png', 'resources/images/dk/right.png', 'resources/images/dk/up.png', 'resources/images/dk/down.png']] HEROZELDAPATHS = [os.path.join(os.getcwd(), path) for path in \ ['resources/images/zelda/left.png', 'resources/images/zelda/right.png', 'resources/images/zelda/up.png', 'resources/images/zelda/down.png']] HEROBATMANPATHS = [os.path.join(os.getcwd(), path) for path in \ ['resources/images/batman/left.png', 'resources/images/batman/right.png', 'resources/images/batman/up.png', 'resources/images/batman/down.png']] '''水果路径''' FRUITPATHS = [os.path.join(os.getcwd(), path) for path in \ ['resources/images/misc/banana.png', 'resources/images/misc/cherry.png']] '''背景路径''' BACKGROUNDPATHS = [os.path.join(os.getcwd(), path) for path in \ ['resources/images/misc/bg0.png', 'resources/images/misc/bg1.png', 'resources/images/misc/bg2.png']] '''爆炸和发射路径''' BOMBPATH = os.path.join(os.getcwd(), 'resources/images/misc/bomb.png') FIREPATH = os.path.join(os.getcwd(), 'resources/images/misc/fire.png') '''背景音乐''' BGMPATH = os.path.join(os.getcwd(), 'resources/audio/bgm.mp3') '''一些颜色''' YELLOW = (255, 255, 0) BLUE = (0, 0, 255) RED = (255, 0, 0) BLACK = (0, 0, 0) WHITE = (255, 255, 255) 五.README # Introduction https://mp.weixin.qq.com/s/XzB_cJMFEtz6p_MvqiaCrA # Environment ``` OS: Windows10 Python: Python3.5+(have installed necessary dependencies) ``` # Usage ``` Step1: pip install -r requirements.txt Step2: run "python Game19.py" ``` # Game Display  六.requirements pygame ———————————————— 版权声明:本文为CSDN博主「小刘在C站」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/lzl10211345/article/details/128989934
-
请问python怎么使用判题器的调试模式?我已经按照以下步骤进行:1. Robot参数使用-d2. 选手程序中在初始化时候sleep一段时间3. 使用pycharm attach到robot_gui.exe的进程但是pycharm出现报错:搜索引擎找不到相关解决方案,只能来求助各位了ORZ
-
一直提示无keyboard这个module,但我已经检查环境下使用的python均已安装这个module。只有使用判题器时,找不到这个module,不知道这个判题器是如何调用python解释器的。
-
1 安装Python环境1.1 安装Miniconda conda是一个开源的包、环境管理器,可以用于在同一个机器上安装不同Python版本的软件包及其依赖,并能够在不同的Python环境之间切换,Anaconda包括Conda、Python以及一大堆安装好的工具包,比如:numpy、pandas等,Miniconda包括Conda、Python。 此处,我们不需要如此多的工具包,故选择MiniConda。1)下载Miniconda(Python3版本)下载地址:cid:link_0 2)安装Miniconda (1)执行以下命令进行安装,并按照提示操作,直到安装完成。bash Miniconda3-py38_23.1.0-1-Linux-x86_64.sh在安装过程中,出现以下提示时,可以指定安装路径 出现以下字样,即为安装完成 3)加载环境变量配置文件,使之生效source ~/.bashrc4)取消激活base环境Miniconda安装完成后,每次打开终端都会激活其默认的base环境,我们可通过以下命令,禁止激活默认base环境。 conda config --set auto_activate_base false1.2 创建Python3.6以上环境conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main conda config --set show_channel_urls yes2)创建Python环境conda create --name superset python=3.8 说明:conda环境管理常用命令创建环境:conda create -n env_name查看所有环境:conda info --envs删除一个环境:conda remove -n env_name --all1.3 适配环境下载相关依赖进入Miniconda3所在目录下bin执行 ./pip3 install pyhive==0.6.1 --force-reinstall ./pip3 install thrift==0.16.0 --force-reninstall ./pip3 install thrift-sasl==0.4.3 ./pip3 install pure-sasl==0.6.2 ./pip3 install sasl==0.3.修改源代码,将域名写死 vim /opt/miniconda3/lib/python3.8/site-packages/pyhive/hive.py添加kerberos_service_host参数 1.4 通过python代码连接hive./python3import os from pyhive import hive host='x.x.x.x' port=21066 auth='KERBEROS' kerberos_service_name='hive' kerberos_service_host='hadoop.hadoop.com' os.system('source /opt/140client/bigdata_env') os.system('echo password | kinit user') with hive.connect(host=host, port=port, auth=auth, kerberos_service_host=kerberos_service_host, kerberos_service_name=kerberos_service_name) as conn: with conn.cursor() as cur: cur.execute("show tables") for i in cur.fetchall(): print(i)注:host是hive对应实例节点,需提前在页面查看然后填写查看Hive数据库中表
-
codeArts2月份技术干货合集以及数据库版块问题合集。 1.pytest中的fixture基本用法【转】 https://bbs.huaweicloud.com/forum/thread-0234112932818513063-1-1.html 2.java double 类型_关于Java中的double类型数据【转】 https://bbs.huaweicloud.com/forum/thread-0222111742558810011-1-1.html 3.解决 Maven ‘parent.relativePath‘ of POM【转】 https://bbs.huaweicloud.com/forum/thread-0236112434845316028-1-1.html 4.Non-resolvable parent POM for解决【转】 https://bbs.huaweicloud.com/forum/thread-0220112499223799035-1-1.html 5.在Maven中出现Could not find artifact ...:pom:0.0.1-SNAPSHOT and ‘parent.relativePath‘的错误怎么解决?【转】 https://bbs.huaweicloud.com/forum/thread-0267112499546748034-1-1.html 6.Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean【转】 https://bbs.huaweicloud.com/forum/thread-0221112501396435024-1-1.html 7.Python利用plotly绘制正二十面体详解【转】 https://bbs.huaweicloud.com/forum/thread-0275112930670884059-1-1.html 8.基于Python实现绘制一个足球【转】 https://bbs.huaweicloud.com/forum/thread-0261112931071459060-1-1.html 9.python __init__与 __new__的区别【转】 https://bbs.huaweicloud.com/forum/thread-0234112931373944060-1-1.html 10.详解Flask数据库的连接与使用【转】 https://bbs.huaweicloud.com/forum/thread-0221112931454173048-1-1.html 11.tensorflow1.x和tensorflow2.x中的tensor转换为字符串的实现【转】 https://bbs.huaweicloud.com/forum/thread-0261112931688113061-1-1.html 12.Flask中特殊装饰器的使用【转】 https://bbs.huaweicloud.com/forum/thread-0237112931865991052-1-1.html 13.pytorch 简介及常用工具包展示【转】 https://bbs.huaweicloud.com/forum/thread-0236112932234100050-1-1.html 14.Pytorch中的 torch.distributions库详解【转】 https://bbs.huaweicloud.com/forum/thread-0234112932425200062-1-1.html 数据库版块问题合集 1.【GaussDB】连接高斯数据库建议使用什么工具? https://bbs.huaweicloud.com/forum/thread-0220111983015871012-1-1.html 2.【GaussDB】数据库存入空字符串会全部被转成NULL,这个能控制不转吗? https://bbs.huaweicloud.com/forum/thread-0236111894276100005-1-1.html 3.【GaussDB】 GaussDB create sequence有if not exists 的类似写法吗 https://bbs.huaweicloud.com/forum/thread-0237111825559668004-1-1.html 4.【GaussDB】连接高斯数据库建议使用什么工具? https://bbs.huaweicloud.com/forum/thread-0220111983015871012-1-1.html 5.【GaussDB】报错: "ERROR:query returened no rows when process into context",怎么处理? https://bbs.huaweicloud.com/forum/thread-0261111825433614001-1-1.html
-
简介: fixture区别于unnitest的传统单元测试(setup/teardown)有显著改进: 1.有独立的命名,并通过声明它们从测试函数、模块、类或整个项目中的使用来激活。 2.按模块化的方式实现,每个fixture都可以互相调用。 3.fixture的范围从简单的单元测试到复杂的功能测试,可以对fixture配置参数,或者跨函数function,类class,模块module或整个测试session范围。fixture的功能fixture是pytest特有的功能,用以在测试执行前和执行后进行必要的准备和清理工作。使用pytest.fixture标识,定义在函数前面。在你编写测试函数的时候,你可以将此函数名称做为传入参数,pytest将会以依赖注入方式,将该函数的返回值作为测试函数的传入参数。主要的目的是为了提供一种可靠和可重复性的手段去运行那些最基本的测试内容。从功能上看来,与setup、teardown相似,但是优势明显:命名方式灵活,不局限于setup和teardown这几个命名conftest.py 配置里可以实现数据共享,不需要import就能自动找到一些配置scope="module" 每一个.py文件调用一次scope="session" 可以实现多个.py跨文件使用一个session来完成多个用例特点及优势1、命令灵活:对于setup.teardown,可以不起这两个名字2、数据共享:在conftest.py配置里写的方法可以实现数据共享,不需要import导入,可以跨文件共享3、scope的层次及神奇的yield组合相当于各种setup和teardown4、实现参数化基本用法@pytest.fixture()import pytest @pytest.fixture() def login(): print("完成登录操作") def test_search(): print("搜索功能,此方法不需要完成登录即可执行") def test_cart(login): print("加入购物车,需要完成登录才可以")fixture在自动化中的应用--作用域@pytest.fixture(scope='module')取值范围说明function函数级每个函数或方法都会调用class类级别每个测试类只运行一次module模块级别每一个.py文件只调用一次package包级没一个python包至调用一次session会话级每次会话只需要运行一次,会话内所有方法及类、模块都共享这个方法import pytest @pytest.fixture(scope='module') def login(): print("完成登录操作") def test_search(login): print("搜索功能,此方法不需要完成登录即可执行") def test_cart(login): print("加入购物车,需要完成登录才可以")、fixture在自动化中的应用-yield关键字场景:你已经可以将测试方法【前要执行的或依赖的】解决了,测试方法后销毁清除数据的要如何进行呢?解决:通过在fixture函数中加入yield关键字,yield是调用第一次返回结果,第二次执行他下面的语句返回。步骤:在@pytest.fixture(scope=module),在登录的方法中加yield,之后加销毁清楚的步骤。import pytest @pytest.fixture(scope='module') def login(): # setup操作 print("完成登录操作") token = 1 yield token # 相当于return的操作 # teardown操作 print("完成登出操作") def test_search(login): # print("搜索功能,此方法不需要完成登录即可执行") print(f"token = {login}") def test_cart(login): # print("加入购物车,需要完成登录才可以") print(f"token = {login}")fixture在自动化中的应用--数据共享场景:与其他测试工程师合作一起开发时,公共的模块要在不同的文件中,要在大家都能访问到的地方解决:使用conftest.py这个文件进行数据共享,并且他可以放在不同位置骑着不同的范围共享作用前提:conftest文件名是不能换的放在项目下是全局的数据共享的地方执行:系统执行到参数login时,先从本模块中查找是否有这个名字的变量之后在conftest.py中找是否有步骤:将登录模块带@pytest.fixture写在conftest.py中fixture在自动化中的应用-自动应用场景:不想原测试方法有任何改动,或全部都自动实现自动应用,没特例,也都不需要返回值时可以选择自动应用解决:使用fixture中参数autouse=True实现步骤:在方法上面加@pytest.fixture(autouse=True)fixture在自动化中的应用-参数化场景:测试离不开数据,为了数据灵活,一般数据都是用过参数传的解决:fixture通过固定参数requests传递步骤:在fixture中增加@pytest.fixture(params=[1,2,3,'tom'])在方法参数写request,方法体里面使用request.param接收参数import pytest @pytest.fixture(params=[1, 2, 3, "测试"]) def login(request): print(f"数据名称为:{request.param}") return request.param def test_search(login): print(f"{login}")
-
Pytorch torch.distributions库包介绍torch.distributions包包含可参数化的概率分布和采样函数。 这允许构建用于优化的随机计算图和随机梯度估计器。不可能通过随机样本直接反向传播。 但是,有两种主要方法可以创建可以反向传播的代理函数。这些是评分函数估计量 score function estimato似然比估计量 likelihood ratio estimatorREINFORCE路径导数估计量 pathwise derivative estimatorREINFORCE 通常被视为强化学习中策略梯度方法的基础,路径导数估计器常见于变分自编码器的重新参数化技巧中。虽然评分函数只需要样本 f(x)的值,但路径导数需要导数 f'(x)。本文重点讲解Pytorch中的 torch.distributions库。pytorch 的 torch.distributions 中可以定义正态分布:import torch from torch.distributions import Normal mean=torch.Tensor([0,2]) normal=Normal(mean,1)sample()就是直接在定义的正太分布(均值为mean,标准差std是1)上采样:result = normal.sample() print("sample():",result)输出:sample(): tensor([-1.3362, 3.1730])rsample()不是在定义的正太分布上采样,而是先对标准正太分布 N(0,1) 进行采样,然后输出: mean + std × 采样值result = normal.rsample() print("rsample():",result)输出:rsample: tensor([ 0.0530, 2.8396])log_prob(value) 是计算value在定义的正态分布(mean,1)中对应的概率的对数,正太分布概率密度函数是:对其取对数可得:这里我们通过对数概率还原其对应的真实概率:print("result log_prob:",normal.log_prob(result).exp())输出:result log_prob: tensor([ 0.1634, 0.2005])
-
一、pytorch 简介Pytorch是torch的python版本,是由Facebook开源的神经网络框架,专门针对 GPU 加速的深度神经网络(DNN)编程。Torch 是一个经典的对多维矩阵数据进行操作的张量(tensor )库,在机器学习和其他数学密集型应用有广泛应用。Pytorch的计算图是动态的,可以根据计算需要实时改变计算图。由于Torch语言采用 Lua,导致在国内一直很小众,并逐渐被支持 Python 的 Tensorflow 抢走用户。作为经典机器学习库 Torch 的端口,PyTorch 为 Python 语言使用者提供了舒适的写代码选择。二、pytorch 优势1.简洁:PyTorch的设计追求最少的封装,尽量避免重复造轮子。不像 TensorFlow 中充斥着session、graph、operation、name_scope、variable、tensor、layer等全新的概念,PyTorch 的设计遵循tensor→variable(autograd)→nn.Module 三个由低到高的抽象层次,分别代表高维数组(张量)、自动求导(变量)和神经网络(层/模块),而且这三个抽象之间联系紧密,可以同时进行修改和操作。2.速度:PyTorch 的灵活性不以速度为代价,在许多评测中,PyTorch 的速度表现胜过 TensorFlow和Keras 等框架。3.易用:PyTorch 是所有的框架中面向对象设计的最优雅的一个。PyTorch的面向对象的接口设计来源于Torch,而Torch的接口设计以灵活易用而著称,Keras作者最初就是受Torch的启发才开发了Keras。4.活跃的社区:PyTorch 提供了完整的文档,循序渐进的指南,作者亲自维护的论坛,供用户交流和求教问题。Facebook 人工智能研究院对 PyTorch 提供了强力支持。三、pytorch 常用工具包torch :类似 NumPy 的张量库,支持GPU;torch.autograd :基于 type 的自动区别库,支持 torch 之中的所有可区分张量运行;torch.nn :为最大化灵活性而设计,与 autograd 深度整合的神经网络库;torch.optim:与 torch.nn 一起使用的优化包,包含 SGD、RMSProp、LBFGS、Adam 等标准优化方式;torch.multiprocessing: python 多进程并发,进程之间 torch Tensors 的内存共享;torch.utils:数据载入器。具有训练器和其他便利功能;torch.legacy(.nn/.optim) :出于向后兼容性考虑,从 Torch 移植来的 legacy 代码;四、pytorch 注意点特别注意一个问题:通道问题:不同视觉库对于图像读取的方式不一样,图像通道也不一样:opencv 的 imread 默认顺序时 H * W * Cpytorch的Tensor是 C * H * WTensorflow是两者都支持五、pytorch 理解numpy风格的tensor操作pytorch对tensor提供的API参照了numpy变量自动求导在计算过程形成的计算图中,参与的变量可快速计算出自己对于目标函数的梯度神经网络求导及损失函数优化等高层封装网络层封装在torch.nn损失函数封装在torch.functional优化函数封装在torch.optim六、pytorch-Tensor1. tensor 数据类型tensor数据类型:3浮点(float16,float32,float64)5整数(int16,int32,int64,int8+uint8)Data typedtypeCPU tensorGPU tensor16-bit floating pointtorch.float16 or torch.halftorch.HalfTensortorch.cuda.HalfTensor32-bit floating pointtorch.float32 or torch.floattorch.FloatTensortorch.cuda.FloatTensor64-bit floating pointtorch.float64 or torch.doubletorch.DoubleTensortorch.cuda.DoubleTensorData typedtypeCPU tensorGPU tensor8-bit integer(unsigned)torch.uint8torch.ByteTensortorch.cuda.ByteTensor8-bit integer(signed)torch.int8torch.CharTensortorch.cuda.CharTensor16-bit integer(signed)torch.int16 or torch.shorttorch.ShortTensortorch.cuda.ShortTensor32-bit integer(signed)torch.int32 or torch.inttorch.IntTensortorch.cuda.IntTensor64-bit integer(signed)torch.int64 or torch.longtorch.LongTensortorch.cuda.LongTensor2. 创建 tensor 相关的 API创建tensor的常见api方法名说明Tensor()直接从参数构造张量,支持list和numpy数组eye(row,column)创建指定行数&列数的单位tensor(单位阵)linspace(start,end,count)在[s,e]上创建c个元素的一维tensorlogspace(start,end,count)在[10s,10e]上创建c个元素的一维tensorones(size)返回指定shape的tensor,元素初始值为1zeros(size)返回指定shape的tensor,元素初始值为0ones_like(t)返回一个tensor,shape与t相同,且元素初始值为1zeros_like(t)返回一个tensor,shape与t相同,且元素初始值为1arange(s,e,sep)在区间[s,e)上以间隔sep生成一个序列张量3. tensor 对象的 APItensor 对象的方法方法名作用size()返回张量的shapenumel()计算tensor的元素个数view(shape)修改tensor的shape,与np.reshape相似,view返回的是对象的共享内存resize类似于view,但在size超出时会重新分配内存空间item若为单元素tensor,则返回python的scalarfrom_numpy从numpy数据填充numpy返回ndarray类型七、python 自动求导tensor对象通过一系列运算组成动态图,每个tensor对象都有以下几个控制求导的属性。变量作用requird_grad默认为False,表示变量是狗需要计算导数grad_fn变量的梯度函数grad变量对应的梯度八、pytorch 神经网络torch.nn提供了创建神经网络的基础构件,这些层都继承自Module类。下面是自己手动实现一个线性层(linear layer)。适当参考,以后直接调用现成的接口,这里稍微了解一下,无实际意义。 import torch class Linear(torch.nn.Module): def __init__(self, in_features, out_features, bias=True): super(Linear, self).__init__() # torch.randn() 返回一个符合均值为0,方差为1的正态分布 self.weight = torch.nn.Parameter(torch.randn(out_features, in_features)) if bias: self.bias = torch.nn.Parameter(torch.randn(out_features)) def forward(self, x): # xW+b x = x.mm(self.weight) if self.bias: x = x + self.bias.expand_as(x) return x if __name__ == '__main__': net = Linear(3,2) x = net.forward print('11',x) 下面表格中列出了比较重要的神经网络层组件。对应的在nn.functional模块中,提供这些层对应的函数实现。通常对于可训练参数的层使用module,而对于不需要训练参数的层如softmax这些,可以使用functional中的函数。一些容器:容器类型功能Module神经网络模块基类Sequential序贯模型,类似keras,用于构建序列型神经网络ModuleList用于存储层,不接受输入Parameters(t)模块的属性,用于保存其训练参数ParameterList参数列表1容器代码: # 方法1 像 model1 = nn.Sequential() model.add_module('fc1', nn.Linear(3,4)) model.add_module('fc2', nn.Linear(4,2)) model.add_module('output', nn.Softmax(2)) # 方法2 model2 = nn.Sequential( nn.Conv2d(1,20,5), nn.ReLU(), nn.Conv2d(20,64,5), nn.ReLU() ) # 方法3 model3 = nn.ModuleList([nn.Linear(3,4), nn.ReLU(), nn.Linear(4,2)]) torch.nn.Module提供了神经网络的基类,当实现神经网络时需要继承自此模块,并在初始化函数中创建网络需要包含的层,并实现forward函数完成前向计算,网络的反向计算会由自动求导机制处理。通常将需要训练的层写在init函数中,将参数不需要训练的层在forward方法里调用对应的函数来实现相应的层。编码三步走:在pytorch中就只需要分三步:写好网络;编写数据的标签和路径索引;把数据送到网络。
-
(1)@app.before_request请求到达视图函数之前,进行自定义操作,类似django中间件中的process_request,在app中使用则为全局,在蓝图中使用则针对当前蓝图注意正常状态下return值必须为None(2)@app.after_request响应返回到达客户端之前,进行自定义操作,类似jango中间件中的process_response,在app中使用则为全局,在蓝图中使用则针对当前蓝图注意正常状态下视图函数必须定义一个形参接收response对象,并通过return response返回(3)@app.errorhandler()错误状态码捕获执行函数,装饰器参数务必是4xx或者5xx的int型错误状态码(4) @app.template_global() :定义装饰全局模板可用的函数,直接可在模板中进行渲染使用@app.template_filter(): 定义装饰全局模板可用的过滤器函数,类似django中的自定义过滤器,直接可在模板中使用这两个特殊装饰器主要用在模板渲染!!!import apps from flask import request, session, redirect app = apps.create_app() @app.before_request def before1(): print("before1", request) @app.before_request def before2(): print("before2") if request.path == "/": return None else: #这里抛出了一个异常,会被@app.errorhandler(Exception) # 捕获到。 raise Exception("hahaha") @app.before_request def before3(): print("before3") @app.after_request def after1(res): print("after1") return res @app.after_request def after2(res): print("after2") return res @app.after_request def after3(res): print("after3") return res # 处理异常,接受参数,可以重定向到指定页面 @app.errorhandler(Exception) def error(e): print("error") return redirect("/") @app.route("/login") def login(): print("login") return "login" @app.route('/') def hello_world(): # put application's code here return 'Hello World!' if __name__ == '__main__': app.run()
-
Tensorflow1.xTensorFlow 1.x 和 TensorFlow 2.x 的 API 存在很大差异,如果您想要将 TensorFlow 1.x 中的 tensor 格式转换成字符串,可以按照以下步骤进行:导入 TensorFlow 1.x 和其他必要的 Python 库。import tensorflow.compat.v1 as tf import numpy as np定义一个 TensorFlow 1.x 的 Tensor。例如:x = tf.constant([[1, 2, 3], [4, 5, 6]], dtype=tf.float32) 使用 tf.as_string() 方法将 Tensor 转换为字符串。例如:str_tensor = tf.as_string(x) 在 TensorFlow 1.x 中,Tensor 对象可以在 Session 中运行以获得实际的值。因此,在使用上述方法将 Tensor 转换为字符串后,需要在 Session 中运行以获得字符串值。with tf.Session() as sess: str_tensor = sess.run(str_tensor) 在上面的例子中,我们使用了 TensorFlow 1.x 的 Session 来运行字符串 Tensor,最后 str_tensor 变量将包含 Tensor 的字符串表示形式。需要注意的是,在 TensorFlow 2.x 中,tf.as_string() 方法已经被 tf.strings.as_string() 方法所替代。同时,TensorFlow 2.x 中不需要使用 Session 来运行 Tensor 对象。Tensorflow2.x要将TensorFlow的Tensor格式转换为字符串,可以使用TensorFlow中的tf.strings方法。具体步骤如下:导入TensorFlow和其他必要的Python库。import tensorflow as tf import numpy as np 定义一个TensorFlow Tensor。例如:x = tf.constant([[1, 2, 3], [4, 5, 6]], dtype=tf.float32) 使用tf.strings.format()方法将Tensor转换为字符串。可以使用format()方法的模板字符串,将Tensor中的元素插入到字符串中。例如:str_tensor = tf.strings.format("Tensor: {}", x) 在上面的例子中,我们使用了"Tensor: {}"字符串作为模板,其中{}将被Tensor x中的元素替换。使用.numpy()方法将字符串Tensor转换为普通的Python字符串。例如:str_tensor = str_tensor.numpy().decode('utf-8') 在上面的例子中,我们首先使用.numpy()方法将Tensor转换为Numpy数组,然后使用.decode()方法将数组转换为UTF-8编码的字符串。最后,str_tensor变量将包含Tensor的字符串表示形式。
-
数据库连接配置HOST = "XXXXXXXXXXXXX" PORT = 3310 USERNAME = "root" PASSWORD = "@XXXXXXXXXXX" DATABASE = "mydb" SQLALCHEMY_DATABASE_URI = f"mysql+pymysql://{USERNAME}:{quote(PASSWORD)}@{HOST}:{PORT}/{DATABASE}?charset=utf8mb4" SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_ECHO = True 创建实体类from exts.DBServer import db from sqlalchemy import Column, Integer, String, Date, DateTime class Article(db.Model): __tablename__ = "article" id = Column(Integer, primay_key=True, autoincrement=True) title = Column(String(100), nullable=True) pub_time = Column(DateTime, nullable=True) author = Column(String(100), nullable=True) content = Column(String(10000), nullable=True) origin = Column(String(1000), nullable=True) controller:import json from flask.blueprints import Blueprint from exts.DBServer import db from ..model.Article import Article from flask_sqlalchemy.query import Query from flask_restful import marshal from flask_restful import fields article_bp = Blueprint("article", __name__, url_prefix="/article") article_fields = { "id": fields.Integer, "title": fields.String, "pub_time": fields.DateTime, "author": fields.String, "content": fields.String, "origin": fields.String } @article_bp.route("/queryAll") def queryAll(): query: Query = Article.query articles = query.all() article = query.get(1) article2 = query.filter_by(author="XXX") return json.dumps(marshal(articles, fields=article_fields),ensure_ascii=False) 配置打印SQL语句from exts.DBServer import db from sqlalchemy import Column, Integer, String class User(db.Model): __tablename__ = "user" id = Column(Integer, primary_key=True, autoincrement=True) username = Column(String(100), nullable=True) password = Column(String(100), nullable=True) def __repr__(self): return "User %r" % self.body 或、与、非和排序@user_bp.route("/query") def query_match(): query: Query = User.query result = query.filter(or_(User.username.contains("祥"), User.id == 1)) return json.dumps(marshal(result.all(), fields=user_fields), ensure_ascii=False) @user_bp.route("/in") def in_sql(): query: Query = User.query result = query.order_by(-User.password, -User.id) return json.dumps(marshal(result.all(), fields=user_fields), ensure_ascii=False)
-
一、构造函数 __init__ 与__new____new__ 作用: 创建对象,并分配内存__init__ 作用: 初始化对象的值注意:1、与java相比,java只有一个构造器。而python __new__ 方法与 __init__ 方法 组合,才能称为一个对应类似于java中的构造器 2、先执行__new__ ,创建对象,并分配内存.再执行 __init__,初始化对象的值。3、任何类都继承于object 类。我们一般不重写__new__ 方法。 我们不重写,就默认调用父类 的 __new__ 方法。4、__new__ 方法 ,一定要return 一个对象。 如果自己重写__new__ 方法,但是没有return出一个对象。连对象都没创建成功,后面是不会进行初始化对象的。例子1:class Person(object): def __init__(self,name,id,sex): self.name = name self.id = id self.sex = sex print("初始化对象的值") def __new__(cls, *args, **kwargs): print("开始创建对象,并分配内存") if __name__ == '__main__': p = Person("张三",12,"男") 运行结果,只执行了__new__ 方法,并没有执行 __init__方法。为啥呢? 因为new函数,没有返回一个 对象。正确的用法class Person(object): def __init__(self,name,id,sex): self.name = name self.id = id self.sex = sex print("初始化对象的值") def __new__(cls, *args, **kwargs): print("开始创建对象,并分配内存") self = super().__new__(cls) return self if __name__ == '__main__': p = Person("张三",12,"男")打印结果:开始创建对象,并分配内存初始化对象的值
-
如果想优雅地绘制一个足球,那首先需要绘制正二十面体 https://bbs.huaweicloud.com/forum/thread-0275112930670884059-1-1.html import numpy as np from itertools import product G = (np.sqrt(5)-1)/2 def getVertex(): pt2 = [(a,b) for a,b in product([1,-1], [G, -G])] pts = [(a,b,0) for a,b in pt2] pts += [(0,a,b) for a,b in pt2] pts += [(b,0,a) for a,b in pt2] return np.array(pts) def getDisMat(pts): N = len(pts) dMat = np.ones([N,N])*np.inf for i in range(N): for j in range(i): dMat[i,j] = np.linalg.norm([pts[i]-pts[j]]) return dMat pts = getVertex() dMat = getDisMat(pts) # 由于存在舍入误差,所以得到的边的数值可能不唯一 ix, jx = np.where((dMat-np.min(dMat))<0.01) # 获取正二十面体的边 edges = [pts[[i,j]] for i,j in zip(ix, jx)] def isFace(e1, e2, e3): pts = np.vstack([e1, e2, e3]) pts = np.unique(pts, axis=0) return len(pts)==3 from itertools import combinations # 获取正二十面体的面 faces = [es for es in combinations(edges, 3) if isFace(*es)] 为了克服plot_trisurf在xy坐标系中的bug,需要对足球做一点旋转,所以下面要写入旋转矩阵。 # 将角度转弧度后再求余弦 cos = lambda th : np.cos(np.deg2rad(th)) sin = lambda th : np.sin(np.deg2rad(th)) # 即 Rx(th) => Matrix Rx = lambda th : np.array([ [1, 0, 0], [0, cos(th), -sin(th)], [0, sin(th), cos(th)]]) Ry = lambda th : np.array([ [cos(th), 0, sin(th)], [0 , 1, 0], [-sin(th), 0, cos(th)] ]) Rz = lambda th : np.array([ [cos(th) , sin(th), 0], [-sin(th), cos(th), 0], [0 , 0, 1]]) 先画六边形足球其实就是正二十面体削掉顶点,正二十面体有20个面和12个顶点,每个面都是三角形。削掉顶点对于三角形而言就是削掉三个角,如果恰好选择在1/3的位置削角,则三角形就变成正六边形;而每个顶点处刚好有5条棱,顶点削去之后就变成了正五边形。而正好足球的六边形和五边形有着不同的颜色,所以可以分步绘制,先来搞定六边形。由于此前已经得到了正二十面体的所有面,同时还有这个面对应的所有边,故而只需在每一条边的1/3 和2/3处截断,就可以得到足球的正六边形。 def getHexEdges(face): pts = [] for st,ed in face: pts.append((2*st+ed)/3) pts.append((st+2*ed)/3) return np.vstack(pts) ax = plt.subplot(projection='3d') for f in faces: pt = getHexEdges(f) pt = Rx(1)@Ry(1)@pt.T ax.plot_trisurf(*pt, color="white") 再画五边形接下来要做的是,将五边形的窟窿补上,正如一开始说的,这个五边形可以理解为削去顶点而得到的,所以第一件事,就是要找到一个顶点周围的所有边。具体方法就是,对每一个顶点遍历所有边,如果某条边中存在这个顶点,那么就把这个边纳入到这个顶点的连接边。 def getPtEdges(pts, edges): N = len(pts) pEdge = [[] for pt in pts] for i,e in product(range(N),edges): if (pts[i] == e[0]).all(): pt = (2*pts[i]+e[1])/3 elif (pts[i] == e[1]).all(): pt = (2*pts[i]+e[0])/3 else: continue pEdge[i].append(pt) return np.array(pEdge) pEdge = getPtEdges(pts, edges) 接下来,就可以绘制足球了 ax = plt.subplot(projection='3d') for f in faces: pt = getHexEdges(f) pt = Rx(1)@Ry(1)@pt.T ax.plot_trisurf(*pt, color="white") for pt in pEdge: pt = Rx(1)@Ry(1)@pt.T ax.plot_trisurf(*pt, color="black") plt.show()
-
当感光元件像素的空间频率与影像中条纹的空间频率接近时,可能产生一种新的波浪形的干扰图案,即所谓的摩尔纹。传感器的网格状纹理构成了一个这样的图案。当图案中的细条状结构与传感器的结构以小角度交叉时,这种效应也会在图像中产生明显的干扰。这种现象在一些细密纹理情况下,比如时尚摄影中的布料上,非常普遍。这种摩尔纹可能通过亮度也可能通过颜色来展现。但是在这里,仅针对在翻拍过程中产生的图像摩尔纹进行处理。翻拍即从计算机屏幕上捕获图片,或对着屏幕拍摄图片;该方式会在图片上产生摩尔纹现象论文主要处理思路对原图作Haar变换得到四个下采样特征图(原图下二采样cA、Horizontal横向高频cH、Vertical纵向高频cV、Diagonal斜向高频cD)然后分别利用四个独立的CNN对四个下采样特征图卷积池化,提取特征信息原文随后对三个高频信息卷积池化后的结果的每个channel、每个像素点比对,取max将上一步得到的结果和cA卷积池化后的结果作笛卡尔积网络结构复现 如下图所示,本项目复现了论文的图像去摩尔纹方法,并对数据处理部分进行了修改,并且网络结构上也参考了源码中的结构,对图片产生四个下采样特征图,而不是论文中的三个,具体处理方式大家可以参考一下网络结构。import math import paddle import paddle.nn as nn import paddle.nn.functional as F # import pywt from paddle.nn import Linear, Dropout, ReLU from paddle.nn import Conv2D, MaxPool2D class mcnn(nn.Layer): def __init__(self, num_classes=1000): super(mcnn, self).__init__() self.num_classes = num_classes self._conv1_LL = Conv2D(3,32,7,stride=2,padding=1,) # self.bn1_LL = nn.BatchNorm2D(128) self._conv1_LH = Conv2D(3,32,7,stride=2,padding=1,) # self.bn1_LH = nn.BatchNorm2D(256) self._conv1_HL = Conv2D(3,32,7,stride=2,padding=1,) # self.bn1_HL = nn.BatchNorm2D(512) self._conv1_HH = Conv2D(3,32,7,stride=2,padding=1,) # self.bn1_HH = nn.BatchNorm2D(256) self.pool_1_LL = nn.MaxPool2D(kernel_size=2,stride=2, padding=0) self.pool_1_LH = nn.MaxPool2D(kernel_size=2,stride=2, padding=0) self.pool_1_HL = nn.MaxPool2D(kernel_size=2,stride=2, padding=0) self.pool_1_HH = nn.MaxPool2D(kernel_size=2,stride=2, padding=0) self._conv2 = Conv2D(32,16,3,stride=2,padding=1,) self.pool_2 = nn.MaxPool2D(kernel_size=2,stride=2, padding=0) self.dropout2 = Dropout(p=0.5) self._conv3 = Conv2D(16,32,3,stride=2,padding=1,) self.pool_3 = nn.MaxPool2D(kernel_size=2,stride=2, padding=0) self._conv4 = Conv2D(32,32,3,stride=2,padding=1,) self.pool_4 = nn.MaxPool2D(kernel_size=2,stride=2, padding=0) self.dropout4 = Dropout(p=0.5) # self.bn1_HH = nn.BatchNorm1D(256) self._fc1 = Linear(in_features=64,out_features=num_classes) self.dropout5 = Dropout(p=0.5) self._fc2 = Linear(in_features=2,out_features=num_classes) def forward(self, inputs1, inputs2, inputs3, inputs4): x1_LL = self._conv1_LL(inputs1) x1_LL = F.relu(x1_LL) x1_LH = self._conv1_LH(inputs2) x1_LH = F.relu(x1_LH) x1_HL = self._conv1_HL(inputs3) x1_HL = F.relu(x1_HL) x1_HH = self._conv1_HH(inputs4) x1_HH = F.relu(x1_HH) pool_x1_LL = self.pool_1_LL(x1_LL) pool_x1_LH = self.pool_1_LH(x1_LH) pool_x1_HL = self.pool_1_HL(x1_HL) pool_x1_HH = self.pool_1_HH(x1_HH) temp = paddle.maximum(pool_x1_LH, pool_x1_HL) avg_LH_HL_HH = paddle.maximum(temp, pool_x1_HH) inp_merged = paddle.multiply(pool_x1_LL, avg_LH_HL_HH) x2 = self._conv2(inp_merged) x2 = F.relu(x2) x2 = self.pool_2(x2) x2 = self.dropout2(x2) x3 = self._conv3(x2) x3 = F.relu(x3) x3 = self.pool_3(x3) x4 = self._conv4(x3) x4 = F.relu(x4) x4 = self.pool_4(x4) x4 = self.dropout4(x4) x4 = paddle.flatten(x4, start_axis=1, stop_axis=-1) x5 = self._fc1(x4) x5 = self.dropout5(x5) out = self._fc2(x5) return out model_res = mcnn(num_classes=2) paddle.summary(model_res,[(1,3,512,384),(1,3,512,384),(1,3,512,384),(1,3,512,384)]) --------------------------------------------------------------------------- Layer (type) Input Shape Output Shape Param # =========================================================================== Conv2D-1 [[1, 3, 512, 384]] [1, 32, 254, 190] 4,736 Conv2D-2 [[1, 3, 512, 384]] [1, 32, 254, 190] 4,736 Conv2D-3 [[1, 3, 512, 384]] [1, 32, 254, 190] 4,736 Conv2D-4 [[1, 3, 512, 384]] [1, 32, 254, 190] 4,736 MaxPool2D-1 [[1, 32, 254, 190]] [1, 32, 127, 95] 0 MaxPool2D-2 [[1, 32, 254, 190]] [1, 32, 127, 95] 0 MaxPool2D-3 [[1, 32, 254, 190]] [1, 32, 127, 95] 0 MaxPool2D-4 [[1, 32, 254, 190]] [1, 32, 127, 95] 0 Conv2D-5 [[1, 32, 127, 95]] [1, 16, 64, 48] 4,624 MaxPool2D-5 [[1, 16, 64, 48]] [1, 16, 32, 24] 0 Dropout-1 [[1, 16, 32, 24]] [1, 16, 32, 24] 0 Conv2D-6 [[1, 16, 32, 24]] [1, 32, 16, 12] 4,640 MaxPool2D-6 [[1, 32, 16, 12]] [1, 32, 8, 6] 0 Conv2D-7 [[1, 32, 8, 6]] [1, 32, 4, 3] 9,248 MaxPool2D-7 [[1, 32, 4, 3]] [1, 32, 2, 1] 0 Dropout-2 [[1, 32, 2, 1]] [1, 32, 2, 1] 0 Linear-1 [[1, 64]] [1, 2] 130 Dropout-3 [[1, 2]] [1, 2] 0 Linear-2 [[1, 2]] [1, 2] 6 =========================================================================== Total params: 37,592 Trainable params: 37,592 Non-trainable params: 0 --------------------------------------------------------------------------- Input size (MB): 9.00 Forward/backward pass size (MB): 59.54 Params size (MB): 0.14 Estimated Total Size (MB): 68.68 --------------------------------------------------------------------------- {'total_params': 37592, 'trainable_params': 37592} 数据预处理 与源代码不同的是,本项目将图像的小波分解部分集成在了数据读取部分,即改为了线上进行小波分解,而不是源代码中的线下进行小波分解并且保存图片。首先,定义小波分解的函数!pip install PyWavelets import numpy as np import pywt def splitFreqBands(img, levRows, levCols): halfRow = int(levRows/2) halfCol = int(levCols/2) LL = img[0:halfRow, 0:halfCol] LH = img[0:halfRow, halfCol:levCols] HL = img[halfRow:levRows, 0:halfCol] HH = img[halfRow:levRows, halfCol:levCols] return LL, LH, HL, HH def haarDWT1D(data, length): avg0 = 0.5; avg1 = 0.5; dif0 = 0.5; dif1 = -0.5; temp = np.empty_like(data) # temp = temp.astype(float) temp = temp.astype(np.uint8) h = int(length/2) for i in range(h): k = i*2 temp[i] = data[k] * avg0 + data[k + 1] * avg1; temp[i + h] = data[k] * dif0 + data[k + 1] * dif1; data[:] = temp # computes the homography coefficients for PIL.Image.transform using point correspondences def fwdHaarDWT2D(img): img = np.array(img) levRows = img.shape[0]; levCols = img.shape[1]; # img = img.astype(float) img = img.astype(np.uint8) for i in range(levRows): row = img[i,:] haarDWT1D(row, levCols) img[i,:] = row for j in range(levCols): col = img[:,j] haarDWT1D(col, levRows) img[:,j] = col return splitFreqBands(img, levRows, levCols) !cd "data/data188843/" && unzip -q 'total_images.zip' import os recapture_keys = [ 'ValidationMoire'] original_keys = ['ValidationClear'] def get_image_label_from_folder_name(folder_name): """ :param folder_name: :return: """ for key in original_keys: if key in folder_name: return 'original' for key in recapture_keys: if key in folder_name: return 'recapture' return 'unclear' label_name2label_id = { 'original': 0, 'recapture': 1,} src_image_dir = "data/data188843/total_images" dst_file = "data/data188843/total_images/train.txt" image_folder = [file for file in os.listdir(src_image_dir)] print(image_folder) image_anno_list = [] for folder in image_folder: label_name = get_image_label_from_folder_name(folder) # label_id = label_name2label_id.get(label_name, 0) label_id = label_name2label_id[label_name] folder_path = os.path.join(src_image_dir, folder) image_file_list = [file for file in os.listdir(folder_path) if file.endswith('.jpg') or file.endswith('.jpeg') or file.endswith('.JPG') or file.endswith('.JPEG') or file.endswith('.png')] for image_file in image_file_list: # if need_root_dir: # image_path = os.path.join(folder_path, image_file) # else: image_path = image_file image_anno_list.append(folder +"/"+image_path +"\t"+ str(label_id) + '\n') dst_path = os.path.dirname(src_image_dir) if not os.path.exists(dst_path): os.makedirs(dst_path) with open(dst_file, 'w') as fd: fd.writelines(image_anno_list) import paddle import numpy as np import pandas as pd import PIL.Image as Image from paddle.vision import transforms # from haar2D import fwdHaarDWT2D paddle.disable_static() # 定义数据预处理 data_transforms = transforms.Compose([ transforms.Resize(size=(448,448)), transforms.ToTensor(), # transpose操作 + (img / 255) # transforms.Normalize( # 减均值 除标准差 # mean=[0.31169346, 0.25506335, 0.12432463], # std=[0.34042713, 0.29819837, 0.1375536]) #计算过程:output[channel] = (input[channel] - mean[channel]) / std[channel] ]) # 构建Dataset class MyDataset(paddle.io.Dataset): """ 步骤一:继承paddle.io.Dataset类 """ def __init__(self, train_img_list, val_img_list, train_label_list, val_label_list, mode='train', ): """ 步骤二:实现构造函数,定义数据读取方式,划分训练和测试数据集 """ super(MyDataset, self).__init__() self.img = [] self.label = [] # 借助pandas读csv的库 self.train_images = train_img_list self.test_images = val_img_list self.train_label = train_label_list self.test_label = val_label_list if mode == 'train': # 读train_images的数据 for img,la in zip(self.train_images, self.train_label): self.img.append('/home/aistudio/data/data188843/total_images/'+img) self.label.append(paddle.to_tensor(int(la), dtype='int64')) else: # 读test_images的数据 for img,la in zip(self.test_images, self.test_label): self.img.append('/home/aistudio/data/data188843/total_images/'+img) self.label.append(paddle.to_tensor(int(la), dtype='int64')) def load_img(self, image_path): # 实际使用时使用Pillow相关库进行图片读取即可,这里我们对数据先做个模拟 image = Image.open(image_path).convert('RGB') # image = data_transforms(image) return image def __getitem__(self, index): """ 步骤三:实现__getitem__方法,定义指定index时如何获取数据,并返回单条数据(训练数据,对应的标签) """ image = self.load_img(self.img[index]) LL, LH, HL, HH = fwdHaarDWT2D(image) label = self.label[index] # print(LL.shape) # print(LH.shape) # print(HL.shape) # print(HH.shape) LL = data_transforms(LL) LH = data_transforms(LH) HL = data_transforms(HL) HH = data_transforms(HH) print(type(LL)) print(LL.dtype) return LL, LH, HL, HH, np.array(label, dtype='int64') def __len__(self): """ 步骤四:实现__len__方法,返回数据集总数目 """ return len(self.img) image_file_txt = '/home/aistudio/data/data188843/total_images/train.txt' with open(image_file_txt) as fd: lines = fd.readlines() train_img_list = list() train_label_list = list() for line in lines: split_list = line.strip().split() image_name, label_id = split_list train_img_list.append(image_name) train_label_list.append(label_id) # print(train_img_list) # print(train_label_list) # 测试定义的数据集 train_dataset = MyDataset(mode='train',train_label_list=train_label_list, train_img_list=train_img_list, val_img_list=train_img_list, val_label_list=train_label_list) # test_dataset = MyDataset(mode='test') # 构建训练集数据加载器 train_loader = paddle.io.DataLoader(train_dataset, batch_size=2, shuffle=True) # 构建测试集数据加载器 valid_loader = paddle.io.DataLoader(train_dataset, batch_size=2, shuffle=True) print('=============train dataset=============') for LL, LH, HL, HH, label in train_dataset: print('label: {}'.format(label)) break 模型训练model2 = paddle.Model(model_res) model2.prepare(optimizer=paddle.optimizer.Adam(parameters=model2.parameters()), loss=nn.CrossEntropyLoss(), metrics=paddle.metric.Accuracy()) model2.fit(train_loader, valid_loader, epochs=5, verbose=1, )
上滑加载中
推荐直播
-
华为云码道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华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签