通过图像进行三维身体测量:实用程序代码分析

<!– wp:paragraph –> 三维身体测量技术是一种用于体现人体形象的科学方法。该技术的一般流程是:抓取图片、进行图像处理、提取身体部位、最后进行三维渲染。今天我将为您分享如何使用图像处理技术实现三维身体测量的知识。 <!– /wp:paragraph –><!– wp:heading –> <h2 class=“wp-block-heading”> 三维身体测量技术:图像处理之美</h2> <!– /wp:heading –><!– wp:paragraph –> 三维身体测量技术的优点之一是它可以提供一种更真实的体验,比较于二维图像。这种技术的美学在于它能让我们以新的眼角看待人体形态,提升了对人体形态的理解。 <!– /wp:paragraph –><!– wp:paragraph –> 在实践中,我们需要使用图像处理技术将图像转换为三维数据。这可以通过识别图像中体素的大小和位置来实现。图像处理的良好应用可以使我们的三维模型精准、省时,同时渲染效果也会更加逼Realistic。 <!– /wp:paragraph –><!– wp:heading –> <h2 class=“wp-block-heading”>实用程序代码分析:探索三维身体测量之路</h2> <!– /wp:heading –><!– wp:paragraph –> 正如你所知,图像处理技术的优势在于它基于计算机视觉的算法,可以自动化大量的任务。然而,如果您对代码如何工作是如何进行三维雄体测量是感兴趣的,那么您将需要了解这些代码中的每一行。 <!– /wp:paragraph –><!– wp:paragraph –> 我将使用Python语言来展示我的代码,因为它有强大的算法库。我们将使用OpenCV库来处理图像,并将这些图像的像素转换为3D点云。 <!– /wp:paragraph –><!– wp:paragraph –> 我的代码结构如下: <!– /wp:paragraph –><!– wp:list {“ordered”:true} –> <!– wp:list-item –>1. 读取图像,使用OpenCV的cv2.imread()函数。 <!– /wp:list-item –><!– wp:list-item –>2. 转换图像到灰度图,使用OpenCV的cv2.cvtColor()函数。 <!– /wp:list-item –><!– wp:list-item –>3. 提取身体部位,使用OpenCV的cv2.findContours()函数。 <!– /wp:list-item –><!– wp:list-item –>4. 计算三维点云,使用OpenCV的cv2.convertTo()函数。 <!– /wp:list-item –> ...

April 14, 2024 · 1 min · jiezi

关于opencv:opencv高斯滤波

1.获取原图大小img = cv2.imread("text.jpg")h, w = img.shape[:2]测试图片是一张256×256×3的图片 2.图像补0#设置卷积核大小K_size = 3pad = K_size // 2out = np.zeros((h + pad * 2, w + pad * 2, 3), dtype=np.cfloat)out[pad: pad + h, pad: pad + w] = img.copy().astype(np.cfloat)若K_size = 21,图像就会在四周补充20个像素的0: 3.创立高斯卷积核#设置标准差sigmasigma = 1.3K = np.zeros((K_size, K_size), dtype=np.cfloat) for x in range(-pad, -pad + K_size): for y in range(-pad, -pad + K_size): K[y + pad, x + pad] = np.exp(-(x ** 2 + y ** 2) / (2 * (sigma ** 2)))K /= (2 * np.pi * sigma * sigma)K /= K.sum()4.进行高斯滤波tmp = out.copy() for y in range(h): for x in range(w): for z in range(3): out[pad + y, pad + x, z] = np.sum(K * tmp[y: y + K_size, x: x + K_size, z])out = np.clip(out, 0, 255)out = out[pad: pad + H, pad: pad + W].astype(np.uint8)当卷积核的大小为3,标准差为1.3时: ...

August 28, 2023 · 1 min · jiezi

关于opencv:numpy灰度可视化

1.创立一个800 * 800的矩形图img = np.zeros([800, 800], dtype=np.uint8)灰度图的亮度值依照规定应该是0~255总计256个值,相当于把从黑到白分循序变动分为了256个阶段,我上面所做的操作就是显示这256个阶段,不同灰度值的图像。 2.对256个区域赋予不同灰度值for i in range(16): for j in range(16): x = i * 50 y = j * 50 s = j + i * 16 img[x : x + 47, y : y + 47] = s失去了256个区域,按区域划分蕴含有16个行和16个列,每区域的像素大小为50 × 50,其中48 × 48个像素区域赋予灰度值,灰度值同一行逐步加一,同一列逐步加16,失去上面这张蕴含所有灰度值的图(0~255),共256个灰度: 冲破255的灰度可视化 for i in range(10): for j in range(26): x = i * 50 y = j * 50 s = j + i * 26 img[x: x + 47, y: y + 47] = s % 256当灰度值超过255时能够通过取余,使得右下角灰度值应该为256~259的区域变为0~4: ...

August 26, 2023 · 1 min · jiezi

关于opencv:关于人脸识别opencv和深度学习

对于人脸识别、opencv和深度学习这篇文章次要是 介绍下这三者的关系 还有从几个大的方面 能够说是宏观角度介绍下OpenCV 前言没有接触过这些的人可能搞不清楚他们的关系,咱们从人脸识别来说,人脸识别大家都晓得,支付宝刷脸、高铁火车进站刷脸,这些技术让咱们生存更加便当 就比如说以前进站要工作人员一个个看证件检票 当初设置几个闸机刷脸安检就ok了 所以说技术的呈现就是为了不便人们的生存 一说到人脸识别,你要辨认的话首先你得从图像中框出人脸才行,然而这其中又有很多问题,就比方进站的时候是间接应用闸机上摄像头的实时画面的截图,因为高矮胖瘦人脸部占比不同,而且脸的朝向角度、站的地位远近都会导致最终拍摄的图像品质产生差别。因而,人脸识别的第一步,是辨认人脸,光这一步就足够难倒不少英雄汉。前面的辨认过程就更不用说,须要兼顾准确性和效率,辨认不准当然不行,但为了准,辨认太久,让大家排着长队等也是不行的,难以兼顾。然而! OpenCV呈现了,当然OpenCV可不止可能做人脸识别 人脸识别只是它其中一小部分 字面意思来看 open是开 凋谢的 开源的 CV就是计算机视觉 computer vision计算机视觉方向也是深度学习外面 一个热门方向 计算机视觉这个词听起来高深莫测,艰深点来说就是钻研咱们平时闲着无聊瞎琢磨的图片和视频 其实图像和视频从技术角度来看是一回事。一段视频按时间轴拉开来,其实就是很多张的图像,咱们常说的视频帧,其实就是一张图像的意思。所以,以后计算机视觉最外围钻研对象,就是图像处理。 而后 计算机视觉和opencv的关系 opencv是计算机视觉外面 一个很火的工具 而且opencv比深度学习呈现得更早上面次要介绍 OpenCV (1)什么是OpenCv通过下面的介绍 大家都大略晓得OpenCV是一个开源的计算机视觉和机器学习库,其余方面来说,它能够运行在Linux Windows 和Android等操作系统上,轻量且高效,是有一系列C函数和C++类形成的 ,他也提供了python matlab等语言的接口 可能实现很多图像处理的算法 (2)计算机视觉软件计算机视觉方面没有规范的api 计算机视觉软件大抵能分为上面三种:①本人钻研代码 然而钻研过程慢,不稳固 还可能与其余库不兼容②商业化工具 比方Halcon Matlab+Simulink 这些 然而商业化工具 有肯定消耗③依赖硬件的解决方案 比方视频监控 控制系统 医疗设施 opencv致力于成长为简化计算机视觉程序和解决方案的规范api 一方面 它优化代码进步了执行速度 另一方面 依赖硬件 失去更高的处理速度(IPPICV减速 英特尔的集成性能基元(IPP)库 opencv3.0时领有了一个收费的IPP库的字库 称为IPPICV 你用的是英特尔处理器时 会主动调用IPPICV 放慢解决)PS: 对于opencv 和 Halcon (3)OpenCV利用场景①图像分类 或者叫图像识别 辨认图像中物体属于什么类别人脸识别 : 人脸方面的利用还是很多的 包含人脸识别 人脸匹配 人脸对齐等等 这也是计算机视觉很火的一个方向 当初广泛应用 ...

February 27, 2023 · 1 min · jiezi

关于opencv:基于OpenCV的人脸视频文字检测以及识别的项目一-项目准备

本文次要是对于人脸、视频、文字检测以及辨认的我的项目筹备opencv环境搭建 次要是 装置python+ numpy模块+opencv 1.配置python环境对于在vscode中配置python环境 比较简单 能够看这位大佬 很具体https://blog.csdn.net/qq_4546... 2装置numpy+opencv (他俩装置办法雷同)numpy是一个定义了数值数组和矩阵类型和它们的根本运算的语言扩大,OpenCV援用了numpy模块,所以装置OpenCV之前必须装置numpy。numpy:第一步:先去网站下载对应的numpy版本,这个numpy要对应你的python版本号 下载地址:https://www.lfd.uci.edu/~gohl...第二步 下载当前 间接cmd 执行命令 pip install d:\numpy\numpy_stl-2.17.1-cp311-cp311-win_amd64.whl//注: 我的python 是下的最新的3.11 所以对应numpy-cp311 install前面跟的是 你下载的文件门路 opencv:同样,先网站下载OpenCV对应的.whl版本压缩包,对应版本的 网址:https://www.lfd.uci.edu/~gohl... 而后cmd 运行命令 pip install d:\opencv-python\opencv_python-4.5.5-cp311-cp311-win_amd64.whl3.vscode上走一走而后就能够关上你的vscode创立 .py文件ok 简简单单环境配好了 本我的项目学习自:该大佬 https://github.com/vipstone/f...我的项目:https://github.com/vipstone/f...

February 19, 2023 · 1 min · jiezi

关于opencv:公众号接入-chatGPT-教程附源码

> 申明:本文仅供技术交换应用,浏览本文需具备肯定的开发能力 前置筹备一个域名一台服务器一个公众号域名配置在你的域名服务商新建二级域名并绑定服务器主机IP 服务器配置上传上面的python文件到你的服务器,并批改代码段中相应地位代码(token、api-key、port) import timefrom flask import Flask,make_response,requestimport openaifrom flask import Flask, requestfrom flask_caching import Cacheimport xml.etree.cElementTree as ETimport hashlibimport requestsimport reimport oscnt = 0my_wx_token = "" # 自定义字母和数字组合即可,后续须要填入公众号后盾my_gpt_key = "" # 这里填写你在OpenAI后盾创立的API-KEYmy_switch_chatgpt = Trueapp = Flask(__name__)env_dist = os.environcache = Cache(app, config={'CACHE_TYPE': 'simple', "CACHE_DEFAULT_TIMEOUT": 30})@app.route('/',methods=['GET','POST'])def wechat(): if request.method == 'GET': signature = request.args.get("signature", "") timestamp= request.args.get("timestamp", "") nonce= request.args.get("nonce", "") echostr= request.args.get("echostr", "") print(signature, timestamp, nonce, echostr) token=my_wx_token data =[token, timestamp, nonce] data.sort() temp = ''.join(data) sha1 = hashlib.sha1(temp.encode('utf-8')) hashcode=sha1.hexdigest() print(hashcode) if hashcode == signature: print("wechat commit check OK") return echostr else: print("GET error input msg") return "error-return\r\n" else: xmlData = ET.fromstring(request.stream.read()) msg_type = xmlData.find('MsgType').text if msg_type == 'text': ToUserName = xmlData.find('ToUserName').text FromUserName = xmlData.find('FromUserName').text CreateTime = xmlData.find('CreateTime').text print(ToUserName) print(FromUserName) print(CreateTime) global cnt cnt += 1 print('-------> ' + str(cnt)) return generate_response_xml(FromUserName, ToUserName, xmlData.find('Content').text) def text_reply(FromUserName, ToUserName, output_content): reply = ''' <xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[%s]]></Content> </xml> ''' response = make_response(reply % (FromUserName, ToUserName, str(int(time.time())), output_content)) response.content_type = 'application/xml' return responsedef generate_response_xml(FromUserName, ToUserName, input_content): output_content = generate_response(input_content) return text_reply(FromUserName, ToUserName, output_content)outofsevice_txt = "道歉,<a href=\"https://mp.weixin.qq.com/s/0LN37YiERJgMyvIDpzRcAQ\">攻城狮杰森的ChatGPT服务助手</a>正在保护中,临时无奈预估保护持续时间,请今天再来尝试吧。"@cache.memoize(timeout=60)def generate_response(prompt): if not my_switch_chatgpt: return outofsevice_txt openai.api_key = my_gpt_key response = openai.Completion.create( model="text-davinci-003", prompt=prompt, temperature=0, max_tokens=1024, top_p=1, frequency_penalty=0.0, presence_penalty=0.0, ) message = response.choices[0].text print(message) ans = message.strip() return ans if __name__ == '__main__': app.run(host='0.0.0.0', port=xxxx, debug=True)#凋谢xxxx端口应用宝塔是比拟快捷的配置形式,装置宝塔面板后,进入软件商店,装置上面两个插件 ...

February 16, 2023 · 2 min · jiezi

关于opencv:谈谈如何使用-opencv-进行图像识别

原文由hakaboom发表于TesterHome社区,点击原文链接可与作者间接交换。1)前言从18年开始,我接触了叉叉助手(平台曾经被请喝茶了),通过图色辨认,用来给常玩的游戏写挂机脚本,写了也有两三年.也算是我转行当游戏测试的理由.去年11月,也是用了这身技术,混进了外包,薪资还不错,属于是混日子了,岗位是在发行,接触到很多游戏,因为接不了poco,到手只有apk,与日俱增,游戏越来越多,项目组却还是只有这点人.为了加重本人的压力,就开始了UI自动化的不归路. 2)游戏UI自动化因为游戏引擎,是无奈通过appium等框架去获取,如果不接入一些SDK,那么辨认的办法只有图像识别.当初常见的开源框架 网易的Airtest,通过传统辨认进行自动化,还有airtestIDE能够简略疾速的编写airtest代码腾讯GameAISDK,通过深度学习进行自动化(没用过,良久不保护了)阿里的SoloPi,次要性能是录制、群控,有图像匹配辅助图像相干的常见办法: 传统的识别方法: 特色点、模板、轮廓 特色点: SIFT, ORB 下文会具体讲模板匹配: opencv的matchTemplate 最简略的计划,通过讲模板在指标图像中平移,找到最合乎的指标轮廓: HALCON Shape-based Matching, Canny 没用过,写不来,halcon的要花钱基于深度学习的办法: 文字辨认: PaddleOCR,tesseract paddleOCR基本上开箱即用,然而对于游戏内的艺术字,还须要额定的训练图像分类: paddleClas 没有理论用过,感觉能够用在辨别场景,而后去做更加具体的辨认.比方辨认弹窗指标检测: yolo 之前很火的Fps外挂,根本就是靠这个去辨认人体UI自动化的外围在于查找元素,并且在什么地位.那么重点就会放在图像识别上.基于深度学习的计划,须要大量的正负样本和标注工作,因而只能放弃.取而代之的是传统的辨认计划.在社区里、qq的测试群里就能发现,大多数人对传统图像识别的印象是:慢,不准.今年过年前,去张江面试过一家游戏公司,也是发行公司,聊了一个多小时,聊下来他们的计划是airtest一种机型截一个图去做适配.我大受震撼.总结下来图像识别的UI自动化难点: 辨认慢辨认后果不精确多分辨率不兼容性游戏UI更新,治理图片库的老本3)怎么解决那么我做了什么,我的项目就在这里:https://github.com/hakaboom/p...目前也是在重构,重构实现后可能起个好名字:https://github.com/hakaboom/i... 一开始是参考了airtest的aircv局部,过后不想有那么多依赖,就拆出来了.重构之后,通过对opencv一些api的封装,从新组织了构架和算法.目前成果感觉不错,也曾经给airtest提了pr,后续也会推动合并. 装置opencv-python倡议版本能够是4.5.5 pypi上有编译好的,然而只能用cpu办法: pip install opencv-pythonpip install opencv-contrib-python从源码编译,能够自定义更多的货色,比方减少cuda反对 先从opencv仓库克隆代码剩下的看这里 https://github.com/hakaboom/p...什么是特色点简略的了解: 用于形容图像特色的关键点 常见的特色点提取算法: SIFT: 尺度不变特色变换. opencv只有cpu实现SURF: surf的减速算法. opencv有cpu和cuda实现ORB: 应用FAST特色检测和BRIEF特征描述子. opencv有cpu和cuda实现他们的益处是什么: 尺度和旋转不变性,说白了就是兼容不同分辨率、旋转、尺度的变换速度排序: ORB(cuda)>SURF(cuda)>ORB>SURF>SIFT成果排序(成果不止是特色点的数量,更重要的是特色点的品质): SIFT>ORB>SURF 例子6.png(2532x1170)iphone12pro上的截图4.png(1922x1118 理论游戏渲染是1920x1080,多进去的是windows边框)崩三桌面端的截图, 裁剪了右上角的蓝色加号区域当模板import cv2import timefrom baseImage import Image, Rectfrom image_registration.matching import SIFTmatch = SIFT()im_source = Image('tests/image/6.png')im_search = Image('tests/image/4.png').crop(Rect(1498,68,50,56))start = time.time()result = match.find_all_results(im_source, im_search)print(time.time() - start)print(result)img = im_source.clone()for _ in result: img.rectangle(rect=_['rect'], color=(0, 0, 255), thickness=3)img.imshow('ret')cv2.waitKey(0)后果能够失去三个加号的地位 ...

April 25, 2022 · 2 min · jiezi

关于opencv:恒源云云GPU服务器如何使用OpenCV

文章起源 | 恒源云社区(专一人工智能/深度学习云 GPU 服务器训练平台,官网体验网址:恒源智享云) 原文地址 | OpenCV 小编明天体检去了,被抽了4管血,所以目前身娇体弱,不易适度操劳 所以,明天就简略分享个镜像内容吧——OpenCV OpenCVOpenCV 是一个计算机视觉库。用于开发实时的图像处理、计算机视觉以及模式识别程序。 官网镜像中曾经提供了独立的 OpenCV 镜像,该镜像环境下提供反对 GPU 的 C++、Python 的 OpenCV。其余框架镜像中蕴含的 OpenCV 是通过 PIP 装置。 环境阐明OpenCV 框架镜像的代码与装置门路: OpenCV 源码:/usr/src/opencv-4.5.4OpenCV 模块源码:/usr/src/opencv_contrib-4.5.4Build 门路:/usr/src/buildInstall 门路:/usr/local/opencv动态链接库门路已配置在 /etc/ld.so.conf.d/opencv.conf 文件中,pkg-config opencv --cflags --libs 可间接作为编译参数应用。 Python3 也应用通过源码编译出的 OpenCV。pip list 无奈查看到 OpenCV 的包,间接导入即可。 python3 -c "import cv2; print(cv2.__version__)"最初,祝还在日以继夜炼丹的你们,周三欢快呀~

December 22, 2021 · 1 min · jiezi

关于opencv:ApacheCN-计算机视觉译文集-20211110-更新

OpenCV3 和 Qt5 计算机视觉 零、前言一、OpenCV 和 Qt 简介二、创立咱们的第一个 Qt 和 OpenCV 我的项目三、创立一个全面的 Qt + OpenCV 我的项目四、Mat和QImage五、图形视图框架六、OpenCV 中的图像处理七、特色和描述符八、多线程九、视频剖析十、调试与测试十一、链接与部署十二、Qt Quick 利用精通 Python OpenCV4 零、前言第 1 局部:OpenCV 4 和 Python 简介 一、设置 OpenCV二、OpenCV 中的图像根底三、解决文件和图像四、在 OpenCV 中结构根本形态第 2 局部:OpenCV 中的图像处理 五、图像处理技术六、结构和建设直方图七、宰割技术八、轮廓检测,过滤和绘图九、加强事实第 3 局部:OpenCV 中的机器学习和深度学习 十、应用 OpenCV 的机器学习十一、人脸检测,跟踪和辨认十二、深度学习简介第 4 局部:挪动和 Web 计算机视觉 十三、应用 Python 和 OpenCV 的挪动和 Web 计算机视觉十四、答案Python OpenCV3 计算机视觉秘籍 零、前言一、I/O 和 GUI二、矩阵,色彩和过滤器三、轮廓和宰割四、指标检测与机器学习五、深度学习六、线性代数七、检测器和描述符八、图像和视频解决九、多视图几何Python OpenCV 3.x 示例 零、前言一、将几何变换利用于图像二、检测边缘并利用图像过滤器三、卡通化图像四、检测和跟踪不同的身材部位五、从图像中提取特色六、接缝雕刻七、检测形态和宰割图像八、对象跟踪九、对象辨认十、加强事实十一、通过人工神经网络的机器学习Qt5 和 OpenCV4 计算机视觉我的项目 零、前言一、构建图像查看器二、像专业人士一样编辑图像三、家庭平安利用四、人脸上的乐趣五、光学字符识别六、实时对象检测七、实时汽车检测和间隔测量八、OpenGL 图像高速过滤九、答案OpenCV 图像处理学习手册 ...

November 13, 2021 · 2 min · jiezi

关于opencv:经验分享windows-源码编译-opencv

 欢送关注我的公众号 [极智视界],回复001获取Google编程标准 O_o >_<  o_O O_o ~_~ o_O 本教程具体记录了在 windows 上源码编译 opencv 的办法。 后面曾经写过《【教训分享】ubuntu源码编译opencv》、《【教训分享】x86、aarch64、arm32环境编译/穿插编译opencv办法》,对于须要在 ubuntu x86、aarch64、arm32 机子上编译 opencv 的同学能够查阅,文本再拓展一下 windows 上源码编译 opencv 的办法。其实 opencv 官网提供了 windows 上编译好的库,所以对于用户来说,间接拿来用即可,这里咱们折腾一下,本人来编一编,我这里是基于 vs2017 应用 nmake 来编的。 1、下载源码包 opencv 官网下载链接:https://opencv.org/releases/   下载指定版本的源码包 source 即可。 这里以opencv4.3.0为例。 2、编译 opencv   留神要用 vs2017 自带的终端 - 实用于 VS2017 的 X64 本机工具命令提醒。 # 进入编译步骤cd <opencv-source-dir>mkdir buildcd buildcall "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Auxiliary\Build\vcvarsall.bat" amd64cmake -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%cd%/install -DWITH_TBB=ON -DWITH_V4L=ON -DBUILD_TIFF=ON ..nmakenmake install 编译装置胜利后,查看 <opencv-source-dir>/build/install/x64/vc15 下生成动静库和动态库,阐明编译胜利: ...

November 4, 2021 · 1 min · jiezi

关于opencv:OpenCV-查找轮廓

本文将联合实例代码,介绍 OpenCV 如何查找轮廓、获取边界框。 代码: contours.pyOpenCV 提供了 findContours 函数查找轮廓,须要以二值化图像作为输出、并指定些选项调用即可。 咱们以下图作为示例: 二值化图像代码工程 data/ 提供了小狗和红球的二值化掩膜图像: 其应用预训练好的实例宰割模型来生成的,脚本可见 detectron2_seg_threshold.py。模型检出后果,如下: 模型用的 Mask R-CNN 已有预测边框。但其余模型会有只出预测掩膜的,此时想要边框就能够应用 OpenCV 来提取。 本文代码也提供了依据色域来获取红球掩膜的方法: import cv2 as cvimport numpy as np# 读取图像img = cv.imread(args.image, cv.IMREAD_COLOR)# HSV 阈值,获取掩膜def _threshold_hsv(image, lower, upper): hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV) mask = cv.inRange(hsv, lower, upper) result = cv.bitwise_and(image, image, mask=mask) return result, mask_, thres = _threshold_hsv(img, np.array([0,110,190]), np.array([7,255,255]))# 革除小点(可选)kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3), (1, 1))thres = cv.morphologyEx(thres, cv.MORPH_OPEN, kernel)查找轮廓# 查找轮廓# cv.RETR_EXTERNAL: 只查找内部轮廓contours, hierarchy = cv.findContours( threshold, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)# 近似轮廓,减点(可选)contours_poly = [cv.approxPolyDP(c, 3, True) for c in contours]# 绘制轮廓h, w = threshold.shape[:2]drawing = np.zeros((h, w, 3), dtype=np.uint8)for i in range(len(contours)): cv.drawContours(drawing, contours_poly, i, (0, 255, 0), 1, cv.LINE_8, hierarchy)获取边界框boundingRect 获取边界框,并绘制: ...

June 7, 2021 · 1 min · jiezi

关于opencv:OpenCV-霍夫线检测练习直线绘制代码调整

概述黑马程序员人工智能教程_10小时学会图像处理OpenCV入门教程中,3.6霍夫线检测代码,对于直线绘制的局部,没有看懂,这里,依据本人的了解,对直线绘制的代码进行了实现。 原理与实现对于笛卡尔坐标系下y = ax + b,转换成极坐标系下有rho = x * cos(theta) + y * sin(theta),两边除以sin(theta)失去下式:y = - cos(theta) / sin(theta) * x + rho / sin(theta)当sin(theta) ==0时,有x = rho / cos(theta)当sin(theta) !=0时,有a = - cos(theta) / sin(theta) ; b = rho / sin(theta)由a, b能够失去直角坐标系下直线方程,能够失去两个点,即可画出直线。在图像上绘制直线的代码如下所示,最初的成果,与老师视频中的成果统一。代码如下所示 print('lines.shape =', lines.shape)h, w = img.shape[:2]for line in lines: rho, theta = line[0] if math.sin(theta) == 0: x = int(rho / math.cos(theta)) cv.line(img, (x, 0), (x, h - 1), (0, 255, 0)) else: a = - math.cos(theta) / math.sin(theta) b = rho / math.sin(theta) # y = a * x + b,计算直线中两个点 x1 = 0 y1 = int(b) x2 = w - 1 y2 = int(a * x1 + b) cv.line(img, (x1, y1), (x2, y2), (0, 255, 0))参考文献https://zhuanlan.zhihu.com/p/... (hough变换原理以及实现(转载) - 知乎) ...

May 3, 2021 · 1 min · jiezi

关于opencv:OpenCVVisual-Studio2019编译环境配置

装置了OpenCV,若想在VS中应用,须要几步操作。 第一步在VS中新建一个空我的项目新建后关上左上角视图,点击其余窗口,抉择属性管理器,就会在窗口右端呈现: 第二步抉择Debug|x64,右键,点击增加新我的项目属性表,能够将表重命名不便识别,点击增加。而后右键新建的表,点击属性,抉择VC++目录,编辑蕴含目录和库目录,增加新行如下图,具体门路参考本人的装置门路。再关上链接器,点击输出,附加依赖项增加:3413是OpenCV的版本号,依据理论更改。再同样地在Release|x64处新建一张一样的表,能够将这两将表保存起来,每次新建OpenCV我的项目只须要将两张表增加到对应地位就能够加重工作量了。 第三步再次点击左上角视图,关上解决方案资源管理器。在源文件处新建cpp项,就能够开始应用OpenCV的库来code了。

March 6, 2021 · 1 min · jiezi

关于opencv:ApacheCN-计算机视觉译文集-20210218-更新

新增了六个教程: OpenCV3 安卓利用编程 零、前言一、设置 OpenCV二、应用相机帧三、利用图像成果四、辨认和跟踪图像五、将图像跟踪与 3D 渲染相结合六、通过 JNI 混合 Java 和 C++OpenCV 即时入门 一、OpenCV 即时入门Python 机器人学习手册 零、前言一、机器人操作系统入门二、理解差动机器人的根底三、建模差动机器人四、应用 ROS 模仿差动机器人五、设计 ChefBot 硬件和电路六、将执行器和传感器连贯到机器人控制器七、视觉传感器与 ROS 接口八、构建 ChefBot 硬件和软件集成九、应用 Qt 和 Python 为机器人设计 GUI十、评估OpenCV2 计算机视觉利用编程秘籍 零、前言一、玩转图像二、操纵像素三、应用类解决图像四、应用直方图计算像素五、通过形态学运算转换图像六、过滤图像七、提取直线,轮廓和整机八、检测和匹配趣味点九、预计图像中的投影关系十、解决视频序列Python OpenCV 计算机视觉 零、前言一、设置 OpenCV二、解决文件,相机和 GUI三、过滤图像四、应用 Haar 级联跟踪人脸五、检测前景/背景区域和深度附录 A:与 Pygame 集成附录 B:为自定义指标生成 Haar 级联Python OpenCV 蓝图 零、前言一、过滤器的乐趣二、应用 Kinect 深度传感器的手势辨认三、通过特色匹配和透视变换查找对象四、应用静止构造重建 3D 场景五、跟踪视觉上显着的对象六、学习辨认交通标志七、学习辨认面部表情下载Dockerdocker pull apachecn0/apachecn-cv-zhdocker run -tid -p <port>:80 apachecn0/apachecn-cv-zh# 拜访 http://localhost:{port} PYPIpip install apachecn-cv-zhapachecn-cv-zh <port># 拜访 http://localhost:{port} NPMnpm install -g apachecn-cv-zhapachecn-cv-zh <port># 拜访 http://localhost:{port} 奉献指南本我的项目须要校对,欢送大家提交 Pull Request。 ...

February 19, 2021 · 1 min · jiezi

关于opencv:ApacheCN-计算机视觉译文集-20210212-更新

新增了六个教程: OpenCV 图像处理学习手册 零、前言一、解决图像和视频文件二、建设图像处理工具三、校对和加强图像四、解决色调五、视频图像处理六、计算摄影七、减速图像处理Python3 OpenCV4 计算机视觉学习手册 零、前言一、设置 OpenCV二、解决文件,相机和 GUI三、应用 OpenCV 解决图像四、深度预计和宰割三、检测和辨认人脸六、检索图像并将图像描述符用于搜寻七、建设自定义对象检测器八、追踪对象九、相机模型和加强事实十、应用 OpenCV 的神经网络简介十一、附录 A:应用“曲线”过滤器蜿蜒色彩空间应用计算机视觉实战我的项目精通 OpenCV 零、前言一、Android 的卡通化器和换肤器二、iPhone 或 iPad 上基于标记的加强事实三、无标记加强事实四、应用 OpenCV 摸索静止构造五、应用 SVM 和神经网络辨认车牌六、非刚性人脸跟踪七、应用 AAM 和 POSIT 的 3D 头部姿态预计八、应用 EigenFace 或 Fisherfaces 的人脸识别OpenCV 安卓编程示例 零、前言一、准备就绪二、利用 1-建设本人的暗室三、利用 2-软件扫描程序四、利用 2-利用透视校对五、利用 3-全景查看器六、利用 4 –主动自拍Python OpenCV 计算机视觉我的项目 零、前言第 1 局部:模块 1 一、设置 OpenCV二、解决文件,相机和 GUI三、过滤图像四、应用 Haar 级联跟踪人脸五、检测前景/背景区域和深度第 2 局部:模块 2 六、检测边缘并利用图像过滤器七、对图像进行卡通化八、检测和跟踪不同的身材部位九、从图像中提取特色十、创立全景图像十一、接缝雕刻十二、检测形态和宰割图像十三、对象跟踪十四、对象辨认十五、平面视觉和 3D 重建第 3 局部:模块 3 十六、加强事实十七、过滤器的乐趣十八、应用 Kinect 深度传感器的手势辨认十九、通过特色匹配和透视变换来查找对象二十、应用静止构造重建 3D 场景二十一、跟踪视觉上显着的对象二十二、学习辨认交通标志二十三、学习辨认面部表情附录 A:集成 Pygame附录 B:为自定义指标生成 Haar 级联附录 C:参考书目树莓派计算机视觉编程 ...

February 12, 2021 · 1 min · jiezi

关于opencv:OpenCV简介及其工程应用游戏色块检测

本文首发于:行者AIOpenCV是一个基于BSD许可(开源)发行的跨平台的计算机视觉和机器学习软件库,能够运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和大量 C++ 类形成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。 OpenCV在图像宰割、人脸识别、物体辨认、动作跟踪、动作剖析、机器视觉等畛域都有宽泛的利用。 以下是OpenCV的基本操作及其利用案例。 1. OpenCV基本操作1.1 读取、显示以及保留操作import cv2image = cv2.imread("test.jpg") # 读取操作cv2.imshow("test", image) # 显示操作cv2.waitKey() # 期待按键cv2.imwrite("save.jpg") # 保留操作1.2 扭转色调空间image = cv2.imread("test.jpg")hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # 转换到HSV空间hls = cv2.cvtColor(image, cv2.COLOR_BGR2HLS) # 转换到HLS空间lab = cv2.cvtColor(image, cv2.COLOR_BGR2Lab) # 转换到Lab空间gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 转换到GRAY空间(灰度图) HSV这个模型中色彩的参数别离是:色调(H),饱和度(S),明度(V),该模型罕用来做绿幕宰割。 在图像检测中,能够对样本进行色调空间转换实现数据加强,如将训练数据间接转换到HSV空间,或者调整V(明度)通道的大小,扭转图片的明暗,再转到BGR格局。 1.3 几何变换--缩放、平移、旋转a. 缩放image = cv2.imread("test.jpg")resize = cv2.resize(image, (), fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA) # 长宽放大到0.5倍b. 平移在对图像作平移操作时,需创立2行3列变换矩阵,M矩阵示意程度方向上平移为x,竖直方向上的平移间隔为y。 import cv2import numpy as npimage = cv2.imread("test.jpg")rows, cols, channels = image.shapeM = np.float32([[1,0,100],[0,1,50]])res = cv.warpAffine(image, M, (cols, rows))c. 旋转旋转所需的变换矩阵能够通过函数cv2.getRotationMatrix2D失去。 ...

February 6, 2021 · 2 min · jiezi

关于opencv:ApacheCN-计算机视觉译文集-20210203-更新

新增了五个教程: OpenCV3 和 Qt5 计算机视觉 零、前言一、OpenCV 和 Qt 简介二、创立咱们的第一个 Qt 和 OpenCV 我的项目三、创立一个全面的 Qt + OpenCV 我的项目四、Mat和QImage五、图形视图框架六、OpenCV 中的图像处理七、特色和描述符八、多线程九、视频剖析十、调试与测试十一、链接与部署十二、Qt Quick 利用精通 Python OpenCV4 零、前言第 1 局部:OpenCV 4 和 Python 简介 一、设置 OpenCV二、OpenCV 中的图像根底三、解决文件和图像四、在 OpenCV 中结构根本形态第 2 局部:OpenCV 中的图像处理 五、图像处理技术六、结构和建设直方图七、宰割技术八、轮廓检测,过滤和绘图九、加强事实第 3 局部:OpenCV 中的机器学习和深度学习 十、应用 OpenCV 的机器学习十一、人脸检测,跟踪和辨认十二、深度学习简介第 4 局部:挪动和 Web 计算机视觉 十三、应用 Python 和 OpenCV 的挪动和 Web 计算机视觉十四、答案Python OpenCV3 计算机视觉秘籍 零、前言一、I/O 和 GUI二、矩阵,色彩和过滤器三、轮廓和宰割四、指标检测与机器学习五、深度学习六、线性代数七、检测器和描述符八、图像和视频解决九、多视图几何Python OpenCV 3.x 示例 零、前言一、将几何变换利用于图像二、检测边缘并利用图像过滤器三、卡通化图像四、检测和跟踪不同的身材部位五、从图像中提取特色六、接缝雕刻七、检测形态和宰割图像八、对象跟踪九、对象辨认十、加强事实十一、通过人工神经网络的机器学习Qt5 和 OpenCV4 计算机视觉我的项目 零、前言一、构建图像查看器二、像专业人士一样编辑图像三、家庭平安利用四、人脸上的乐趣五、光学字符识别六、实时对象检测七、实时汽车检测和间隔测量八、OpenGL 图像高速过滤九、答案下载Dockerdocker pull apachecn0/apachecn-cv-zhdocker run -tid -p <port>:80 apachecn0/apachecn-cv-zh# 拜访 http://localhost:{port} PYPIpip install apachecn-cv-zhapachecn-cv-zh <port># 拜访 http://localhost:{port} NPMnpm install -g apachecn-cv-zhapachecn-cv-zh <port># 拜访 http://localhost:{port} 奉献指南本我的项目须要校对,欢送大家提交 Pull Request。 ...

February 3, 2021 · 1 min · jiezi

关于opencv:OpenCV-新版-451-发布

作者 | CV君报道 | 我爱计算机视觉(微信id:aicvml)公布亮点: OpenCV Github 我的项目终于冲破50000 stars!新的里程碑~ 这次公布的个性包含: 集成更多的GSoC 2020 我的项目的后果,包含: 1\. 开发了OpenCV.js DNN 模块,以不便再网页中应用,并提供了相干教程。 图像分类 指标检测 格调迁徙 语义宰割 姿势预计 2\. OpenCV.js WASM SIMD 优化 2.0,网页端调用OpenCV更快了 3\. 新增文本检测和辨认高级API 4\. SIFT算法优化,次要是16位整型高斯滤波指令减速 DNN模块的改良: 1\. 改良层/激活函数反对更多模型:1D卷积,1D池化 2\. 修复Resize, ReduceMean,多输入收集,导入Faster RCNN ONNX模型 3\. 反对INT32 ONNX张量 4\. 英特尔®推理引擎后端(OpenVINO™): 减少了对OpenVINO 2021.2版本的反对增加了对HDDL的预览反对 5\. 改良了DNN CUDA后端反对 G-API模块改良: 新增了对G-API框架和操作的改良,改良了OpenVINO™后端反对,新增了Microsoft®ONNX Runtime后端反对,改良了对Python的绑定 RISC-V port重大改良: 极大欠缺了universal intrinsics 的RISC-V后端 其余社区奉献更新: 1\. objdetect 模块新增蜿蜒QR码的检测与解码 ...

December 24, 2020 · 1 min · jiezi

关于opencv:OpenCV开发笔记七十一红胖子8分钟带你深入级联分类器训练

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/109096211各位读者,常识无穷而人力有穷,要么改需要,要么找专业人士,要么本人钻研红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中...(点击传送门) OpenCV开发专栏(点击传送门)上一篇:《OpenCV开发笔记(七十):红瘦子带你傻瓜式编译VS2017x64版本的openCV4》下一篇:继续补充中… 前言 红瘦子,来也! 做图像处理,常常头痛的是明明分离出来了(非色彩的),分为几块区域,那怎么晓得这几块区域到底哪一块是咱们须要的,那么这部分就波及到须要辨认了。 辨认能够本人写模板匹配、特色点辨认、级联分类器训练辨认。 本文章就是解说级联分类器的训练与辨认。 级联分类器相干 OpenCV的级联分类器分有两个,别离为Harr级联分类器和LBP级联分类器。具体级联分类器请查看: 《OpenCV开发笔记(五十四):红瘦子8分钟带你深刻理解Haar级联分类器进行人脸检测(图文并茂+浅显易懂+程序源码)》 《OpenCV开发笔记(五十五):红瘦子8分钟带你深刻理解Haar、LBP特色以及级联分类器辨认过程(图文并茂+浅显易懂+程序源码)》 明确指标 指标是辨认视频中的歌手,咱们先手动采集数据汇合。 视频为《绿色》,如下图: 训练分类器前的筹备工作采集正样本图片 正样本的尺寸不是必须统一的,然而要和生成的正样本矢量文件中的宽高有雷同的比例(因为训练过程中,会依据设置的宽高进行等比缩放,比方设置正版本图片是128x128的,那么样本为256x256会缩放,假如杨文为256x128的那么比例就不同了,这个图怎么解决?待定); 正样本图片应该尽可能蕴含少的烦扰背景信息。在训练过程中多余的背景信息也会成为正样本的一个部分特色,此处与深度学习不同,深度学习当初支流无脑深度学习,图像根本的一些去噪都可能不做。 数据起源尽可能做到多样化,比方样本为车,车的姿势场景应稍丰盛些。同一正样本指标的图像太多会使部分特色过于显著,造成这个指标的训练过拟合,影响检测精度,不利于训练器泛化应用。 咱们采集视频的人脸,先把视频解码后保留成jpg图片。 此处省略一万字...................................... 创立样本:opencv_createsamples.exe 应用opencv自带的命令行工具opencv_createsamples.exe [-info <collection_file_name>]样本阐明文件,每一行的内容为 xxx.jpg nums x y width height 例如:图片中有两个指标 xxx.jpg 2 0 0 100 100 200 200 100 100 生成样本在windows上依靠命令行 dir /b > pos.data[-img <image_file_name>] 通过一张图片的扭曲形变成多张图片作为样本,就填写这个参数,参数的内容为要扭曲的图片的门路。填入后,-info参数不再无效。 [-vec <vec_file_name>] 样本形容文件的名字及门路 [-bg <background_file_name>] 负样本形容文件的名字及门路,如果省略,则应用bgcolor的值填充作为背景。就是跟寄存负样本图片(背景图片)目录地位雷同的形容文件的门路,可用txt,dat等格局保留,每一行的内容为:xxx.jpg。 [-inv] 如果指定该标记,前景图像的色彩将翻转 [-randinv] 如果指定该标记,色彩将随机地翻转 [-num <number_of_samples = 1000>] 总共几个样本,能够省略,则依照输出的理论样本数量产生 ...

October 19, 2020 · 2 min · jiezi

关于opencv:OpenCV开发笔记七十红胖子带你傻瓜式编译VS2017x64版本的openCV4

若该文为原创文章,未经容许不得转载,经容许后转载请注明原文地址本文章博客地址:https://blog.csdn.net/qq21497936/article/details/107837715各位读者,常识无穷而人力有穷,要么改需要,要么找专业人士,要么本人钻研红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中...(点击传送门) OpenCV开发专栏(点击传送门)上一篇:OpenCV开发笔记(六十九):红瘦子8分钟带你应用传统办法辨认已知物体(图文并茂+浅显易懂+程序源码)下一篇:继续补充中… 前言 红瘦子来也!!! opencv_contrib是opencv提供额定的工具,提供一些根底算法,之前编译了不带opencv_contrib的版本,不带opencv_contrib的cuda硬减速版本, opencv+opentrib的版本。 OpenCV4是最新的版本,编译一个openCV4的msvc版本。 版本汇总- Qt5.2.0 mingw32 + Opencv2.4.10 版本《OpenCV开发笔记(〇):应用mingw530_32编译openCV3.4.1源码,搭建Qt5.9.3的openCV开发环境》 - Qt5.9.3 mingw32 + Opencv3.4.1 版本《OpenCV开发笔记(一):OpenCV介绍、编译》 - Opencv3.4.0 + cuda9.0 + VS2015版本《OpenCV开发笔记(十二):OpenCV编译反对Gpu(cuda) 减速开发之win-qt-msvc2015编译(opencv3.4.0、cuda9.0、VS2015)》 以上打包汇合下载地址:https://download.csdn.net/download/qq21497936/12255080 OpenCV4下载 应用版本4.4.0 官网下载地址:https://opencv.org CSDN下载地址:https://download.csdn.net/download/qq21497936/12917447 QQ群:1047134658(点击“文件”搜寻“opencv”,群内与博文同步更新) OpenCV编译步骤一:解压到编译文件夹 步骤二:CMake配置configure第一次 配置时,间接选中msvc 2017即可(带x64是64位,不带是32位) 步骤三:勾选局部配置,全局+opencv 其余不勾选了。 步骤四:Generate生成工程 步骤五:关上编译 进入VS2017,而后指标是win64,间接编译win64的release版本。 步骤六:编译胜利 模块化 在这里附上Qt工程文件要带的库文件引入配置 # 不带opencv_contrib的world版本 opencv4.4.0LIBS += -L$$PWD/openCV4.4.0/lib -lopencv_world440INCLUDEPATH += $${PWD}/openCV4.4.0/include \ $${PWD}/openCV4.4.0/include/opencv \ $${PWD}/openCV4.4.0/include/opencv2 测试Demovoid OpenCVManager::testRunNormal(){ cv::namedWindow("testRunNormal"); cv::waitKey(0);} ...

October 15, 2020 · 1 min · jiezi

关于opencv:Opencv-python之车辆识别项目

图片车辆辨认依据文章搭建好环境后开始进行做我的项目link import sysimport cv2from PyQt5.QtGui import *from PyQt5.QtWidgets import *from PyQt5.QtGui import QIcon, QPalette, QPixmap, QBrush, QRegExpValidatorclass mainWin(QWidget): def __init__(self): """ 构造函数 """ super().__init__() self.initUI() self.openBtn.clicked.connect(self.openFile) # 信号和槽 self.grayBtn.clicked.connect(self.imgGray) # 信号和槽 self.carCheckBtn.clicked.connect(self.carCheck) def initUI(self): # 设置窗口得大小 self.setFixedSize(860, 600) # 图标和背景 self.setWindowTitle("车辆检测") self.setWindowIcon(QIcon("img/icon.jpg")) # 图标 # 标签 self.leftLab = QLabel("原图:", self) self.leftLab.setGeometry(10, 50, 400, 400) # 设置相对地位 self.leftLab.setStyleSheet("background:white") self.newLab = QLabel("新图:", self) self.newLab.setGeometry(420, 50, 400, 400) # 设置相对地位 self.newLab.setStyleSheet("background-color:white") # 按钮 self.openBtn = QPushButton(" 关上文件", self) self.openBtn.setGeometry(10, 10, 80, 30) self.grayBtn = QPushButton(" 灰度解决", self) self.grayBtn.setGeometry(100, 10, 80, 30) self.carCheckBtn = QPushButton(" 视频检测", self) self.carCheckBtn.setGeometry(200, 10, 80, 30)关上文件办法 ...

September 2, 2020 · 2 min · jiezi

关于opencv:OpenCV开发笔记六十九红胖子8分钟带你使用传统方法识别已知物体图文并茂浅显易懂程序源码

若该文为原创文章,未经容许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062本文章博客地址:https://blog.csdn.net/qq21497936/article/details/107837715各位读者,常识无穷而人力有穷,要么改需要,要么找专业人士,要么本人钻研红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中...(点击传送门) OpenCV开发专栏(点击传送门)上一篇:《OpenCV开发笔记(六十八):红瘦子8分钟带你应用特色点Flann最邻近差值匹配辨认(图文并茂+浅显易懂+程序源码)》下一篇:继续补充中… 前言 红瘦子,来也! 特色点、匹配,那么如何应用特色点和匹配来辨认已有的物体,也就剩最要害的最初一步:寻找已知的物体了。 Demo 寻找已知物体本篇章应用sift/surf特色点sift特色点 尺度不变特色变换(Scale-invariant feature transform,SIFT),是用于图像处理畛域的一种形容。这种形容具备尺度不变性,可在图像中检测出关键点,是一种部分特征描述子。 surf特色点 SURF算法采纳了很多办法来对每一步进行优化从而进步速度。剖析显示在后果成果相当的状况下SURF的速度是SIFT的3倍。SURF长于解决具备含糊和旋转的图像,然而不长于解决视角变动和光照变动。(SIFT特色是部分特色,其对旋转、尺度缩放、亮度变动放弃不变性,对视角变动、仿射变换、噪声也放弃肯定水平的稳定性)。 针对图像场景的特点,抉择不同的特色点,列出之前特色点相干的博文: 《OpenCV开发笔记(六十三):红瘦子8分钟带你深刻理解SIFT特色点(图文并茂+浅显易懂+程序源码)》 《OpenCV开发笔记(六十四):红瘦子8分钟带你深刻理解SURF特色点(图文并茂+浅显易懂+程序源码)》 《OpenCV开发笔记(六十五):红瘦子8分钟带你深刻理解ORB特色点(图文并茂+浅显易懂+程序源码)》 本篇章使用暴力、最邻近差值匹配暴力匹配 最佳特色匹配总是尝试所有可能的匹配,从而使得它总可能找到最佳匹配,这也是BruteForce(暴力法)的原始含意,波及到的类为BFMatcher类。 《OpenCV开发笔记(六十七):红瘦子8分钟带你深刻理解特色点暴力匹配(图文并茂+浅显易懂+程序源码)》 最近邻差值匹配 一种近似法,算法更快然而找到的是最近邻近似匹配,所以当咱们须要找到一个绝对好的匹配然而不须要最佳匹配的时候往往应用FlannBasedMatcher。 《OpenCV开发笔记(六十八):红瘦子8分钟带你应用特色点Flann最邻近差值匹配辨认(图文并茂+浅显易懂+程序源码)》 概述 对已知物体:过滤、去噪后、提取已知物体的特色点; 对场景:过滤、去噪后、提取场景的特色点; 对已知物体特色点汇合和场景中的特色点汇合去匹配,计算投影矩阵; 若胜利计算变换矩阵就示意辨认到物体; 通过原始的四个点地位进行变换矩阵计算,即可失去场景中的已知物体的四个顶点,该四个顶点连接起来就是已知物体的地位。 特色点汇合计算变换矩阵函数原型Mat findHomography(InputArray srcPoints, InputArray dstPoints, int method = 0, double ransacReprojThreshold = 3, OutputArray mask=noArray(), const int maxIters = 2000, const double confidence = 0.995);参数一:InputArray类型的srcPoints,源立体上的对应点,能够是CV_32FC2的矩阵类型或者vector<Point2>;参数二:InputArray类型的dstPoints;指标立体上的对应点 , 可 以 是CV 32FC2 的矩阵类型或者 vector<Point2>; 参数三:int类型的method,用于计算单应矩阵的办法,如下图: 参数四:double类型的ransacReprojThreshold,最大容许重投影谬误将点对视为内联线(仅用于RANSAC和RHO办法);参数五:OutputArray类型的mask,由鲁棒办法(RANSAC或LMEDS)设置的可选输入掩码。留神输出掩码值被疏忽。;参数六:const int类型的maxIters,RANSAC迭代的最大数量。;参数七:const double类型的confidence,置信水平,介于0和1之间;矩阵变换函数原型void perspectiveTransform( InputArray src, InputArray dst, InputArray m);参数一:InputArray类型的src,输出两通道或三通道浮点数组;每个元素是要转换的二维/三维向量。参数二:InputArray类型的dst,与src大小和类型雷同的输入数组;参数三:InputArray类型的h,3x3或4x4浮点转换矩阵。 ...

August 6, 2020 · 6 min · jiezi

关于opencv:OpenCV开发笔记六十八红胖子8分钟带你使用特征点Flann最邻近差值匹配识别图文并茂浅显易懂程序源码

若该文为原创文章,未经容许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062本文章博客地址:https://blog.csdn.net/qq21497936/article/details/107357296各位读者,常识无穷而人力有穷,要么改需要,要么找专业人士,要么本人钻研红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中...(点击传送门) OpenCV开发专栏(点击传送门)上一篇:《OpenCV开发笔记(六十七):红瘦子8分钟带你深刻理解特色点暴力匹配(图文并茂+浅显易懂+程序源码)》下一篇:继续补充中… 前言 红瘦子,来也! 后面解说了特色点,那么匹配特色点,就是匹配两者的类似度,类似度达到肯定的阈值,则认为辨认了。 思考性能,除开暴力匹配外,还有最近邻匹配。 Demo 最近邻匹配(FLANN) FlannBasedMatcher中FLANN的含意是Fast Library forApproximate Nearest Neighbors,目前最残缺的(近似)最近邻匹配。岂但实现了一系列查找算法,还蕴含了一种主动选取最快算法的机制。 从字面意思可知它是一种近似法,算法更快然而找到的是最近邻近似匹配,所以当咱们须要找到一个绝对好的匹配然而不须要最佳匹配的时候往往应用FlannBasedMatcher。 当然也能够通过调整FlannBasedMatcher的参数来进步匹配的精度或者进步算法速度,然而相应地算法速度或者算法精度会受到影响。 本篇章应用sift/surf特色点sift特色点 尺度不变特色变换(Scale-invariant feature transform,SIFT),是用于图像处理畛域的一种形容。这种形容具备尺度不变性,可在图像中检测出关键点,是一种部分特征描述子。 surf特色点 SURF算法采纳了很多办法来对每一步进行优化从而进步速度。剖析显示在后果成果相当的状况下SURF的速度是SIFT的3倍。SURF长于解决具备含糊和旋转的图像,然而不长于解决视角变动和光照变动。(SIFT特色是部分特色,其对旋转、尺度缩放、亮度变动放弃不变性,对视角变动、仿射变换、噪声也放弃肯定水平的稳定性)。针对图像场景的特点,抉择不同的特色点,列出之前特色点相干的博文: 《OpenCV开发笔记(六十三):红瘦子8分钟带你深刻理解SIFT特色点(图文并茂+浅显易懂+程序源码)》 《OpenCV开发笔记(六十四):红瘦子8分钟带你深刻理解SURF特色点(图文并茂+浅显易懂+程序源码)》 《OpenCV开发笔记(六十五):红瘦子8分钟带你深刻理解ORB特色点(图文并茂+浅显易懂+程序源码)》 FlannBasedMatcher类的应用定义// 定义匹配器cv::Ptr<cv::FlannBasedMatcher> pFlannBasedMatcher = cv::FlannBasedMatcher::create();// 定义后果寄存std::vector<cv::DMatch> listDMatch;// 存储特色点检测器检测特色后的形容字cv::Mat descriptor1;cv::Mat descriptor2;特色点提取pFlannBasedMatcher->detectAndCompute(srcMat1, cv::Mat(), keyPoints1, descriptor1);pFlannBasedMatcher->detectAndCompute(srcMat1, cv::Mat(), keyPoints1, descriptor1);匹配// FlannBasedMatcher最近邻匹配pFlannBasedMatcher->match(descriptor1, descriptor2, listDMatch); FlannBasedMatcher相干函数原型static Ptr<FlannBasedMatcher> create() ;无参数 FlannBasedMatcher::match( InputArray queryDescriptors, InputArray trainDescriptors, std::vector<DMatch>& matches, InputArray mask=noArray() ) const;参数一:InputArray类型的queryDescriptors,查问描述符集,个别cv::Mat,某个特征提取的描述符。参数二:InputArray类型的trainDescriptors,训练描述符集,此处输出的应该是没有退出到类对象汇合种的(该类有训练的数据汇合),个别cv::Mat,某个特征提取的描述符。参数三:std::vector<DMatch>类型的matches。如果在掩码中屏蔽了查问描述符,则不会为此增加匹配项描述符。因而,匹配项的大小可能小于查问描述符计数。参数四:InputArray类型的mask,指定输出查问和训练矩阵之间容许的匹配的掩码描述符。绘制匹配关系图函数原型 void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1, InputArray img2, const std::vector<KeyPoint>& keypoints2, const std::vector<DMatch>& matches1to2, InputOutputArray outImg, const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1), const std::vector<char>& matchesMask=std::vector<char>(), int flags=DrawMatchesFlags::DEFAULT );参数一:InputArray类型的img1,图像1。参数二:std::vector<KeyPoint>类型的keypoints1,图像1的关键点。参数三:InputArray类型的img2,图像2。参数四:std::vector<KeyPoint>类型的keypoints2,图像2的关键点。参数五:std::vector<DMatch>类型的matchers1to2,从第一个图像匹配到第二个图像,这意味着keypoints1[i]在keypoints2中有一个对应的点[matches[i]]。参数六:InputOutputArray类型的outImg,为空时,默认并排绘制输入图像以及连贯关键点;若不为空,则在图像上绘制关系点。参数七:Scalar类型的matcherColor,匹配色彩匹配(线和连贯的关键点)的色彩。如果色彩为cv::Scalar::all(-1),则为随机色彩。参数八:Scalar类型的singlePointColor,色彩单个关键点(圆)的色彩,这意味着关键点没有匹配到的则认是该色彩。参数九:std::vector<char>类型的matchersMask,确定绘制的匹配我的项目,若是为空,则示意全副绘制。参数十:int类型的flags,查看枚举DrawMatchesFlags,如下: ...

July 23, 2020 · 5 min · jiezi

OpenCV开发笔记六十七红胖子8分钟带你深入了解特征点暴力匹配图文并茂浅显易懂程序源码

若该文为原创文章,未经容许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062本文章博客地址:https://blog.csdn.net/qq21497936/article/details/107348874红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) OpenCV开发专栏(点击传送门)上一篇:《OpenCV开发笔记(六十六):红瘦子8分钟带你总结形态学操作-收缩、侵蚀、开运算、闭运算、梯度、顶帽、黑帽(图文并茂+浅显易懂+程序源码)》下一篇:继续补充中… 前言 红瘦子,来也! 后面解说了特色点,那么匹配特色点,原始图像与指标图像之间存在哪些匹配的同类型的特色点,匹配点的多少则是作为类似度的输出,达到肯定类似度则认为匹配到了。 本篇章联合sift特色点和暴力匹配,进行特色点匹配实现步骤原理解说。 Demo 第四个图片的匹配成果不好,想要成果好须要依据图像特点去抉择特色点提取的形式,此处次要是为了解说流程。 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/107348874 最佳特色匹配(暴力匹配) 最佳特色匹配总是尝试所有可能的匹配,从而使得它总可能找到最佳匹配,这也是BruteForce(暴力法)的原始含意,波及到的类为BFMatcher类。 本篇章应用的是Sift特色点概述 SIFT,即尺度不变特色变换(Scale-invariant feature transform,SIFT),是用于图像处理畛域的一种形容。这种形容具备尺度不变性,可在图像中检测出关键点,是一种部分特征描述子。 SIFT算法特点以及SIFT相干函数的应用SIFT特色是部分特色,其对旋转、尺度缩放、亮度变动放弃不变性,对视角变动、仿射变换、噪声也放弃肯定水平的稳定性;辨别性(Distinctiveness)好,信息量丰盛,实用于在海量特色数据库中进行疾速、精确的匹配;多量性,即便多数的几个物体也能够产生大量的SIFT特征向量;高速性,经优化的SIFT匹配算法甚至能够达到实时的要求;可扩展性,能够很不便的与其余模式的特征向量进行联结; 无关sift、surf、orb和应用请查看博文 针对图像场景的特点,抉择不同的特色点,列出之前特色点相干的博文: 《OpenCV开发笔记(六十三):红瘦子8分钟带你深刻理解SIFT特色点(图文并茂+浅显易懂+程序源码)》 《OpenCV开发笔记(六十四):红瘦子8分钟带你深刻理解SURF特色点(图文并茂+浅显易懂+程序源码)》 《OpenCV开发笔记(六十五):红瘦子8分钟带你深刻理解ORB特色点(图文并茂+浅显易懂+程序源码)》 BFMatcher类的应用定义// 定义匹配器cv::Ptr<cv::BFMatcher> pBFMatcher;// 定义后果寄存std::vector<cv::DMatch> listDMatch;// 存储特色点检测器检测特色后的形容字cv::Mat descriptor1;cv::Mat descriptor2;特色点提取_pSift->detectAndCompute(srcMat1, cv::Mat(), keyPoints1, descriptor1);_pSift->detectAndCompute(srcMat1, cv::Mat(), keyPoints1, descriptor1);匹配// bfMatcher暴力匹配pBFMatcher->match(descriptor1, descriptor2, listDMatch);BFMatcher相干函数原型static Ptr<BFMatcher> create( int normType=NORM_L2, bool crossCheck=false ) ;参数一:int类型的normType,欧式间隔,NORM类型中:NORM_L1,NORM_L2,NORM_HAMMING,NORM_HAMMING 2,L1、L2是SIFT和SURF描述符的最优选抉择;NORM_HAMMING应与ORB、BRISK和BRIEF搭配应用;NORM_HAMMING2应该与ORB一起应用,当WTA_K==3或者4时。 参数二:bool类型的crossCheck,如果是false,这将是BFMatcher在找到k时的默认行为:每个查问描述符的最近街坊。如果crossCheck==true,则应用k=1只返回对(i,j),对于第i个查问描述符,在匹配器的汇合是最近的,反之亦然,即BFMatcher只返回统一的对。当存在异样值时,这种技术通常会产生最佳后果,而离群值数量很少够了。这是D.Lowe在筛纸中应用的比率测试的代替办法。void BFMatcher::match( InputArray queryDescriptors, InputArray trainDescriptors, std::vector<DMatch>& matches, InputArray mask=noArray() ) const;参数一:InputArray类型的queryDescriptors,查问描述符集,个别cv::Mat,某个特征提取的描述符。参数二:InputArray类型的trainDescriptors,训练描述符集,此处输出的应该是没有退出到类对象汇合种的(该类有训练的数据汇合),个别cv::Mat,某个特征提取的描述符。参数三:匹配匹配项。如果在掩码中屏蔽了查问描述符,则不会为此增加匹配项描述符。因而,匹配项的大小可能小于查问描述符计数。参数四:指定输出查问和训练矩阵之间容许的匹配的掩码描述符。绘制匹配关系图函数原型参数一:InputArray类型的img1,图像1。参数二:std::vector<KeyPoint>类型的keypoints1,图像1的关键点。参数三:InputArray类型的img2,图像2。参数四:std::vector<KeyPoint>类型的keypoints2,图像2的关键点。参数五:std::vector<DMatch>类型的matchers1to2,从第一个图像匹配到第二个图像,这意味着keypoints1[i]在keypoints2中有一个对应的点[matches[i]]。参数六:InputOutputArray类型的outImg,为空时,默认并排绘制输入图像以及连贯关键点;若不为空,则在图像上绘制关系点。参数七:Scalar类型的matcherColor,匹配色彩匹配(线和连贯的关键点)的色彩。如果色彩为cv::Scalar::all(-1),则为随机色彩。参数八:Scalar类型的singlePointColor,色彩单个关键点(圆)的色彩,这意味着关键点没有匹配到的则认是该色彩。参数九:std::vector<char>类型的matchersMask,确定绘制的匹配我的项目,若是为空,则示意全副绘制。参数十:int类型的flags,查看枚举DrawMatchesFlags,如下: Demovoid OpenCVManager::testBFMatcher(){ QString fileName1 = "13.jpg"; int width = 400; int height = 300; cv::Mat srcMat = cv::imread(fileName1.toStdString()); cv::resize(srcMat, srcMat, cv::Size(width, height)); cv::String windowName = _windowTitle.toStdString(); cvui::init(windowName); cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 2, srcMat.rows * 3), srcMat.type()); cv::Ptr<cv::xfeatures2d::SIFT> _pSift = cv::xfeatures2d::SiftFeatureDetector::create(); int k1x = 0; int k1y = 0; int k2x = 100; int k2y = 0; int k3x = 100; int k3y = 100; int k4x = 0; int k4y = 100; cv::Ptr<cv::BFMatcher> pBFMatcher; pBFMatcher = cv::BFMatcher::create(); std::vector<cv::DMatch> listDMatch; cv::Mat descriptor1; cv::Mat descriptor2; bool moveFlag = true; // 挪动的标记,不必每次都匹配 windowMat = cv::Scalar(0, 0, 0); while(true) { cv::Mat mat; { std::vector<cv::KeyPoint> keyPoints1; std::vector<cv::KeyPoint> keyPoints2; int k1xOld = k1x; int k1yOld = k1y; int k2xOld = k2x; int k2yOld = k2y; int k3xOld = k3x; int k3yOld = k3y; int k4xOld = k4x; int k4yOld = k4y; mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1), cv::Range(srcMat.cols * 0, srcMat.cols * 1)); mat = cv::Scalar(0); cvui::printf(windowMat, 0 + width * 0, 10 + height * 0, "k1x"); cvui::trackbar(windowMat, 0 + width * 0, 20 + height * 0, 165, &k1x, 0, 100); cvui::printf(windowMat, 0 + width * 0, 70 + height * 0, "k1y"); cvui::trackbar(windowMat, 0 + width * 0, 80 + height * 0, 165, &k1y, 0, 100); cvui::printf(windowMat, width / 2 + width * 0, 10 + height * 0, "k2x"); cvui::trackbar(windowMat, width / 2 + width * 0, 20 + height * 0, 165, &k2x, 0, 100); cvui::printf(windowMat, width / 2 + width * 0, 70 + height * 0, "k2y"); cvui::trackbar(windowMat, width / 2 + width * 0, 80 + height * 0, 165, &k2y, 0, 100); cvui::printf(windowMat, 0 + width * 0, 10 + height * 0 + height / 2, "k3x"); cvui::trackbar(windowMat, 0 + width * 0, 20 + height * 0 + height / 2, 165, &k3x, 0, 100); cvui::printf(windowMat, 0 + width * 0, 70 + height * 0 + height / 2, "k3y"); cvui::trackbar(windowMat, 0 + width * 0, 80 + height * 0 + height / 2, 165, &k3y, 0, 100); cvui::printf(windowMat, width / 2 + width * 0, 10 + height * 0 + height / 2, "k4x"); cvui::trackbar(windowMat, width / 2 + width * 0, 20 + height * 0 + height / 2, 165, &k4x, 0, 100); cvui::printf(windowMat, width / 2 + width * 0, 70 + height * 0 + height / 2, "k4y"); cvui::trackbar(windowMat, width / 2 + width * 0, 80 + height * 0 + height / 2, 165, &k4y, 0, 100); if( k1xOld != k1x || k1yOld != k1y || k2xOld != k2x || k2yOld != k2y || k3xOld != k3x || k3yOld != k3y || k4xOld != k4x || k4yOld != k4y) { moveFlag = true; } std::vector<cv::Point2f> srcPoints; std::vector<cv::Point2f> dstPoints; srcPoints.push_back(cv::Point2f(0.0f, 0.0f)); srcPoints.push_back(cv::Point2f(srcMat.cols - 1, 0.0f)); srcPoints.push_back(cv::Point2f(srcMat.cols - 1, srcMat.rows - 1)); srcPoints.push_back(cv::Point2f(0.0f, srcMat.rows - 1)); dstPoints.push_back(cv::Point2f(srcMat.cols * k1x / 100.0f, srcMat.rows * k1y / 100.0f)); dstPoints.push_back(cv::Point2f(srcMat.cols * k2x / 100.0f, srcMat.rows * k2y / 100.0f)); dstPoints.push_back(cv::Point2f(srcMat.cols * k3x / 100.0f, srcMat.rows * k3y / 100.0f)); dstPoints.push_back(cv::Point2f(srcMat.cols * k4x / 100.0f, srcMat.rows * k4y / 100.0f)); cv::Mat M = cv::getPerspectiveTransform(srcPoints, dstPoints); cv::Mat srcMat2; cv::warpPerspective(srcMat, srcMat2, M, cv::Size(srcMat.cols, srcMat.rows), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar::all(0)); mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1), cv::Range(srcMat.cols * 1, srcMat.cols * 2)); cv::addWeighted(mat, 0.0f, srcMat2, 1.0f, 0.0f, mat); if(moveFlag) { moveFlag = false; //特色点检测 // _pSift->detect(srcMat, keyPoints1); _pSift->detectAndCompute(srcMat, cv::Mat(), keyPoints1, descriptor1); //绘制特色点(关键点) cv::Mat resultShowMat; cv::drawKeypoints(srcMat, keyPoints1, resultShowMat, cv::Scalar(0, 0, 255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2), cv::Range(srcMat.cols * 0, srcMat.cols * 1)); cv::addWeighted(mat, 0.0f, resultShowMat, 1.0f, 0.0f, mat); //特色点检测 // _pSift->detect(srcMat2, keyPoints2); _pSift->detectAndCompute(srcMat2, cv::Mat(), keyPoints2, descriptor2); //绘制特色点(关键点) cv::Mat resultShowMat2; cv::drawKeypoints(srcMat2, keyPoints2, resultShowMat2, cv::Scalar(0, 0, 255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2), cv::Range(srcMat.cols * 1, srcMat.cols * 2)); cv::addWeighted(mat, 0.0f, resultShowMat2, 1.0f, 0.0f, mat); // bfMatcher暴力匹配 pBFMatcher->match(descriptor1, descriptor2, listDMatch); // drawMatch绘制进去,并排显示了,高度一样,宽度累加(因为两个宽度雷同,所以是两倍了) cv::Mat matchesMat; cv::drawMatches(srcMat, keyPoints1, srcMat2, keyPoints2, listDMatch, matchesMat); mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3), cv::Range(srcMat.cols * 0, srcMat.cols * 2)); cv::addWeighted(mat, 0.0f, matchesMat, 1.0f, 0.0f, mat); } } cv::imshow(windowName, windowMat); // 更新 cvui::update(); // 显示 // esc键退出 if(cv::waitKey(25) == 27) { break; } }} ...

July 14, 2020 · 4 min · jiezi

OpenCV开发笔记六十六红胖子8分钟带你总结形态学操作膨胀腐蚀开运算闭运算梯度顶帽黑帽

若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062本文章博客地址:https://blog.csdn.net/qq21497936/article/details/107106565红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门) Qt开发专栏:项目实战(点击传送门)OpenCV开发专栏(点击传送门)上一篇:《OpenCV开发笔记(六十五):红胖子8分钟带你深入了解ORB特征点(图文并茂+浅显易懂+程序源码)》下一篇:持续补充中… 前言 红胖子,来也! opencv之前讲解了各种形态学操作,使用了形态学对应的函数,除此之外,opencv在形态学上还提供了专门的函数处理,一个函数搞定所有,当然就不能实现自定义的一些算法,如3次膨胀,2次腐蚀了(之前的开、闭运算demo提供了这种操作)。 Demo 形态学 图像处理中的形态学,指数字形态学。 数学形态学是数学形态学图像处理的基本理论,其基本的运算包括:二值腐蚀和膨胀、二值开源算、骨架抽取、极限腐蚀、击中击不中变换、形态学梯度、Top-hat变换、合理分析、流域变换、灰值腐蚀和膨胀、灰值开运算、灰值形态学梯度。 形态学操作就是基于形状的一系列图像处理操作,OpenCV为进行图像的形态学变换提供了快捷、方便的函数。除了之前讲解的单个操作的函数外,OpenCV还为我们提供了一个形态学专有函数,通过枚举来进行不同的操作。 膨胀 膨胀(dilate)是求局部最大值的操作,从数据角度来说,膨胀是将图像与核进行卷积,实现了对目标像素点进行扩展的目的。 《OpenCV开发笔记(二十一):算法基础之形态学滤波-膨胀》 腐蚀 腐蚀(delate)与膨胀(ercode)是一对相反的操作,膨胀是求局部最大值的操作,那么膨胀就是求局部最小值的操作。 《OpenCV开发笔记(二十二):算法基础之形态学滤波-腐蚀》 开运算 开运算(Opening Operation)就是先腐蚀后膨胀的过程。、 开运算可以用来消除小物体,在纤细点处分离物体,并且在平滑较大物体的边界的同时不明显改变其面积(去除噪声及平滑目标边界)。 《OpenCV开发笔记(二十三):算法基础之形态学滤波-开运算(先腐蚀后膨胀)》 闭运算 闭运算(Closing Operation)就是先膨胀后腐蚀的过程。、 闭运算可以用拟合小裂缝,消除小型黑洞,并且在平滑较大物体的边界的同时不明显改变其面积。 闭运算能填充目标区域内的离散小空洞和分散部分。 《OpenCV开发笔记(二十四):算法基础之形态学滤波-闭运算(先膨胀后腐蚀)》 形态学梯度 形态学梯度(Morphological Gradient)是膨胀(被减数)和腐蚀(减数)的差别,结果看上去就像前景物体的轮廓。 形态学梯度可以保留物体的边缘轮廓。 《OpenCV开发笔记(二十五):算法基础之形态学滤波-形态学梯度》 顶帽(礼帽) 顶帽运算(Top Hat)又称作“礼帽”运算,是原图像(减数)与“开运算”(被减数)的结果图之差。开运算带来的结果是放大了裂缝或者局部降低亮度的区域。因此,从原图中减去开运算后的图,得到的效果突出了比原图轮廓周围的区域更明亮的区域,且这一操作与选择的核的大小相关。顶帽运算往往用来分离比邻近点亮一些的斑块。在一幅图像具有大幅的背景,而微小物品比较有规律的情况下,可以使用顶帽运算进行背景提取。 《OpenCV开发笔记(二十六):算法基础之形态学滤波-顶帽(礼帽)》 黑帽 黑帽(Black Hat)运算是闭运算(被减数)的结果图与原图像(减数)之差。 黑帽运算后的效果突出了比原图轮过周围的区域更暗的区域,且这一操作和选择的核大小相关。 所以与顶帽操作相反,黑帽操作是用来分离比邻近点暗一些的斑块,效果图有着非常完美的轮廓。 《OpenCV开发笔记(二十七):算法基础之形态学滤波-黑帽》本文章博客地址:https://blog.csdn.net/qq21497936/article/details/107106565 形态学函数原型void morphologyEx( InputArray src, OutputArray dst, int op, InputArray kernel, Point anchor = Point(-1,-1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar& borderValue = morphologyDefaultBorderValue() );参数一:InputArray类型,一般是cv::Mat,通道数是任意的,但是深度必须为CV_8U、CV_16U、CV_16S、CV_32F或CV_64F;参数二;OutputArray类型,输出的目标图像,和原图像有一样的尺寸和类型;参数三;int类型的op,表示形态学计算的操作类型,如下图: ...

July 5, 2020 · 3 min · jiezi

项目实战QtOpenCV图像处理与识别算法平台

若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062本文章博客地址:https://blog.csdn.net/qq21497936/article/details/107090002红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门) Qt开发专栏:项目实战(点击传送门)OpenCV开发专栏(点击传送门) 需求 做算法过程中,需要一个平台来实时查看效果,记录处理过程,可以一键查看效果; OpenCV的各种算法在Qt效果调试; 持续升级版本,敬请期待... 原理 基于Qt的OpenCV开发,依托Qt作为界面,OpenCV进行图像处理。 涉及技术博文 《OpenCV开发笔记(三十四):红胖子带你傻瓜式编译Qt+openCV3.4.1+opencv_contrib(全网最浅显易懂)》 《OpenCV开发笔记(四):OpenCV图片和视频数据的读取与存储》 《OpenCV开发笔记(十三):OpenCV图像对比度、亮度的调整》 《OpenCV开发笔记(十四):算法基础之线性滤波-方框滤波》 《OpenCV开发笔记(十五):算法基础之线性滤波-均值滤波》 《OpenCV开发笔记(十六):算法基础之线性滤波-高斯滤波》 《OpenCV开发笔记(十八):算法基础之非线性滤波-中值滤波》 《OpenCV开发笔记(十九):算法基础之非线性滤波-双边滤波》 《OpenCV开发笔记(二十一):算法基础之形态学滤波-膨胀》 《OpenCV开发笔记(二十二):算法基础之形态学滤波-腐蚀》 Demo:Qt+OpenCV算法平台 v1.4.0下载地址 CSDN:https://download.csdn.net/download/qq21497936/12570673 QQ群:1047134658(点击“文件”搜索“qtOpenCVTools”,群内与博文同步更新) 腐蚀 膨胀 双边滤波 中值滤波 高斯滤波 均值滤波 方框滤波 对比度与亮度 图片打开与保存 核心代码common.h#ifndef COMMON_H#define COMMON_H#include <QImage>#include <QDebug>#include <QFileDialog>#include <QColorDialog>#include <QMessageBox>#include <QHash>// opencv#include "opencv/highgui.h"#include "opencv/cxcore.h"#include "opencv2/core/core.hpp"#include "opencv2/highgui/highgui.hpp"#include "opencv2/opencv.hpp"#include "opencv2/xphoto.hpp"// opencv_contrib#include <opencv2/xphoto.hpp>#include <opencv2/ximgproc.hpp>#include <opencv2/calib3d.hpp>cv::Mat image2Mat(QImage image); // Qimage 转 cv::MatQImage mat2Image(cv::Mat mat); // cv::Mat 转 QImage#endif // COMMON_Hcommon.cpp#include "common.h"cv::Mat image2Mat(QImage image){ cv::Mat mat; switch(image.format()) { case QImage::Format_ARGB32: case QImage::Format_RGB32: case QImage::Format_ARGB32_Premultiplied: mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); cv::cvtColor(mat, mat, CV_BGRA2BGR); break; case QImage::Format_RGB888: mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); cv::cvtColor(mat, mat, CV_BGR2RGB); break; case QImage::Format_Indexed8: mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); break; } return mat;}QImage mat2Image(cv::Mat mat){ if(mat.type() == CV_8UC1) { QImage image(mat.cols, mat.rows, QImage::Format_Indexed8); // Set the color table (used to translate colour indexes to qRgb values) image.setColorCount(256); for(int i = 0; i < 256; i++) { image.setColor(i, qRgb(i, i, i)); } // Copy input Mat uchar *pSrc = mat.data; for(int row = 0; row < mat.rows; row ++) { uchar *pDest = image.scanLine(row); memcpy(pDest, pSrc, mat.cols); pSrc += mat.step; } return image; } else if(mat.type() == CV_8UC3) { const uchar *pSrc = (const uchar*)mat.data; QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888); return image.rgbSwapped(); } else if(mat.type() == CV_8UC4) { const uchar *pSrc = (const uchar*)mat.data; QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32); return image.copy(); } else { return QImage(); }}DemoContrastAndBrightnessWidget.h#ifndef DEMOCONTRASTANDBRIGHTNESSWIDGET_H#define DEMOCONTRASTANDBRIGHTNESSWIDGET_H#include <QWidget>#include "common.h"namespace Ui {class DemoContrastAndBrightnessWidget;}class DemoContrastAndBrightnessWidget : public QWidget{ Q_OBJECTpublic: explicit DemoContrastAndBrightnessWidget(QWidget *parent = 0); ~DemoContrastAndBrightnessWidget();public: void setFilePath(QString filePath);protected: void updateInfo(); void updateImage();private slots: void on_pushButton_openFile_clicked(); void on_horizontalSlider_beta_sliderMoved(int position); void on_horizontalSlider_alpha_sliderMoved(int position); void on_pushButton_broswer_clicked(); void on_spinBox_beta_valueChanged(int arg1); void on_doubleSpinBox_alpha_valueChanged(double arg1); void on_pushButton_showFile_clicked(); void on_pushButton_backgroundColor_clicked();private: Ui::DemoContrastAndBrightnessWidget *ui;private: QString _filePath; cv::Mat _srcMat; QImage _srcImage; cv::Mat _dstMat; QImage _dstImage;};#endif // DEMOCONTRASTANDBRIGHTNESSWIDGET_HDemoContrastAndBrightnessWidget.cpp#include "DemoContrastAndBrightnessWidget.h"#include "ui_DemoContrastAndBrightnessWidget.h"DemoContrastAndBrightnessWidget::DemoContrastAndBrightnessWidget(QWidget *parent) : QWidget(parent), ui(new Ui::DemoContrastAndBrightnessWidget){ ui->setupUi(this);}DemoContrastAndBrightnessWidget::~DemoContrastAndBrightnessWidget(){ delete ui;}void DemoContrastAndBrightnessWidget::setFilePath(QString filePath){ _filePath = filePath; ui->lineEdit_filePath->setText(_filePath);}void DemoContrastAndBrightnessWidget::updateInfo(){ if(_srcMat.data == 0) { return; } // mat行列与图片高度是对角线反向的 ui->label_size->setText(QString("%1 x %2").arg(_srcMat.rows).arg(_srcMat.cols)); ui->label_channels->setText(QString("%1").arg(_srcMat.channels())); ui->label_depth->setText(QString("%1").arg(_srcMat.depth())); ui->label_type->setText(QString("%1").arg(_srcMat.type()));}void DemoContrastAndBrightnessWidget::updateImage(){ if(_srcImage.isNull()) { return; } cv::Mat srcMat = image2Mat(_srcImage); // 增强对比度 float r; float g; float b; _dstMat = cv::Mat::zeros(srcMat.size(), srcMat.type()); int alpha = ui->horizontalSlider_alpha->value(); // 小于1,则降低对比度 int beta = ui->horizontalSlider_beta->value(); // 负数,则降低亮度 for(int row = 0; row < srcMat.rows; row++) { for(int col = 0; col < srcMat.cols; col++) { b = srcMat.at<cv::Vec3b>(row, col)[0]; g = srcMat.at<cv::Vec3b>(row, col)[1]; r = srcMat.at<cv::Vec3b>(row, col)[2]; // 对比度、亮度计算公式 cv::saturate_cast<uchar>(value):防止溢出 _dstMat.at<cv::Vec3b>(row, col)[0] = cv::saturate_cast<uchar>(b * alpha / 100.0f + beta); _dstMat.at<cv::Vec3b>(row, col)[1] = cv::saturate_cast<uchar>(g * alpha / 100.0f + beta); _dstMat.at<cv::Vec3b>(row, col)[2] = cv::saturate_cast<uchar>(r * alpha / 100.0f + beta); } } _dstImage = mat2Image(_dstMat); ui->widget_image->setImage(_dstImage);}void DemoContrastAndBrightnessWidget::on_pushButton_openFile_clicked(){ if(!_srcImage.load(_filePath)) { qDebug() << __FILE__ << __LINE__ << "Failed to load image:" << _filePath; return; } qDebug() << __FILE__<< __LINE__ << (int)_srcImage.format(); _srcMat = image2Mat(_srcImage); updateInfo(); updateImage();}void DemoContrastAndBrightnessWidget::on_horizontalSlider_beta_sliderMoved(int position){ ui->spinBox_beta->setValue(position); updateImage();}void DemoContrastAndBrightnessWidget::on_horizontalSlider_alpha_sliderMoved(int position){ ui->doubleSpinBox_alpha->setValue(position / 100.0f); updateImage();}void DemoContrastAndBrightnessWidget::on_pushButton_broswer_clicked(){ QString dir = ui->lineEdit_filePath->text(); dir = dir.mid(0, dir.lastIndexOf("/")); QString filePath = QFileDialog::getOpenFileName(0, "打开图片", dir, "PNG;JPEG;BMP(*.png;*.jpg;*.bmp);;JPEG(*.jpg);;PNG(*.png);;BMP(*.bmp)"); if(filePath.isEmpty()) { return; } _filePath = filePath; ui->lineEdit_filePath->setText(_filePath);}void DemoContrastAndBrightnessWidget::on_spinBox_beta_valueChanged(int arg1){ ui->horizontalSlider_beta->setValue(arg1); updateImage();}void DemoContrastAndBrightnessWidget::on_doubleSpinBox_alpha_valueChanged(double arg1){ ui->horizontalSlider_alpha->setValue(arg1 * 100); updateImage();}void DemoContrastAndBrightnessWidget::on_pushButton_showFile_clicked(){ if(_dstMat.data == 0) { QMessageBox::information(this, "提示", "使用opencv显示图片失败"); return; } cv::imshow("showFile", _dstMat);}void DemoContrastAndBrightnessWidget::on_pushButton_backgroundColor_clicked(){ QColor backgroundColor = ui->widget_image->getBackgroundColor(); backgroundColor = QColorDialog::getColor(backgroundColor, this, "底色"); if(!backgroundColor.isValid()) { return; } QColor color(backgroundColor.red(), backgroundColor.green(), backgroundColor.blue()); ui->widget_image->setBackgroundColor(color);} ...

July 2, 2020 · 3 min · jiezi

OpenCV开发笔记六十五红胖子8分钟带你深入了解ORB特征点图文并茂浅显易懂程序源码

若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106926496各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门) OpenCV开发专栏(点击传送门)上一篇:《OpenCV开发笔记(六十四):红胖子8分钟带你深入了解SURF特征点(图文并茂+浅显易懂+程序源码)》下一篇:持续补充中… 前言 红胖子,来也! 识别除了传统的模板匹配之外就是体征点了,前面介绍了Suft特征点,还有一个传统的就会ORB特征点了。 其实识别的特征点多种多样,既可以自己写也可以使用opencv为我们提供的,一般来说根据特征点的特性和效率,选择适合我们场景的特征就可以了。 本篇,介绍ORB特征提取。 Demo ORB特征点概述 ORB是ORiented Brief的简称,是briedf算法的改进版,于2011年在《ORB:an fficient alternative to SIFT or SURF》中提出。ORB算法分为两部分,分别是特征点提取和特征点描述: 特征提取:由FAST(Features from Accelerated Segment Test)算法发展来的;特征点描述:根据BRIEF(Binary Robust IndependentElementary Features)特征描述算法改进的。 ORB特征是将FAST特征点的检测方法与BRIEF特征描述子结合起来,并在它们原来的基础上做了改进与优化。据说,ORB算法的速度是sift的100倍,是surf的10倍。 Brief描述子 该特征描述子是在特征点附近随机选取若干点对,将这些点对的灰度值的大小,组合成一个二进制串,组合成一个二进制传,并将这个二进制串作为该特征点的特征描述子。 Brief的速度快,但是使用灰度值作为描述字计算的源头,毫无疑问会有一些显而易见的问题: 旋转后灰度变了导致无法识别,因其不具备旋转不变形;由于是计算灰度,噪声灰度化则无法去噪,所以对噪声敏感;尺度不同影响灰度计算,所以也不具备尺度不变形;ORB是试图使其具备旋转不变性和降低噪声敏感度而提出的。 特征检测步骤步骤一:使用brief算子的方式初步提取。 该步能够提取大量的特征点,但是有很大一部分的特征点的质量不高。从图像中选取一点P,以P为圆心画一个半径为N像素半径的圆。圆周上如果有连续n个像素点的灰度值比P点的灰度值大或者小,则认为P为特征点。 步骤二:机器学习的方法筛选最优特征点。 通俗来说就是使用ID3算法训练一个决策树,将特征点圆周上的16个像素输入决策树中,以此来筛选出最优的FAST特征点。 步骤三:非极大值抑制去除局部较密集特征点。 使用非极大值抑制算法去除临近位置多个特征点的问题。为每一个特征点计算出其响应大小。计算方式是特征点P和其周围16个特征点偏差的绝对值和。在比较临近的特征点中,保留响应值较大的特征点,删除其余的特征点。 步骤四:使用金字塔来实现多尺度不变形。步骤五:使用图像的矩判断特征点的旋转不变性 ORB算法提出使用矩(moment)法来确定FAST特征点的方向。也就是说通过矩来计算特征点以r为半径范围内的质心,特征点坐标到质心形成一个向量作为该特征点的方向。 ORB类的使用cv::Ptr<cv::ORB> _pOrb = cv::ORB::create();std::vector<cv::KeyPoint> keyPoints1;//特征点检测_pOrb->detect(srcMat, keyPoints1);ORB相关函数原型static Ptr<ORB> create(int nfeatures=500, float scaleFactor=1.2f, int nlevels=8, int edgeThreshold=31, int firstLevel=0, int WTA_K=2, int scoreType=ORB::HARRIS_SCORE, int patchSize=31, int fastThreshold=20);参数一:int类型的nfeatures,用于ORB的,保留最大的关键点数,默认值500;参数二:float类型的scaleFactor,比例因子,大于1时为金字塔抽取比。的等于2表示经典的金字塔,每一个下一层的像素比上一层少4倍,但是比例系数太大了将显著降低特征匹配分数。另一方面,太接近1个比例因子这意味着要覆盖一定的范围,你需要更多的金字塔级别,所以速度会受影响的,默认值1.2f;参数三:int类型的nlevels,nlevels金字塔级别的数目。最小级别的线性大小等于输入图像线性大小/功率(缩放因子,nlevels-第一级),默认值为8;参数四:int类型的edgeThreshold,edgeThreshold这是未检测到功能的边框大小。它应该大致匹配patchSize参数。;参数五:int类型的firstLevel,要将源图像放置到的金字塔级别。以前的图层已填充使用放大的源图像;参数六:int类型的WTA_K,生成定向简短描述符的每个元素的点数。这个默认值2是指取一个随机点对并比较它们的亮度,所以我们得到0/1的响应。其他可能的值是3和4。例如,3表示我们取3随机点(当然,这些点坐标是随机的,但是它们是由预定义的种子,因此简短描述符的每个元素都是从像素确定地计算出来的矩形),找到最大亮度点和获胜者的输出索引(0、1或2)。如此输出将占用2位,因此需要一个特殊的汉明距离变量,表示为NORM_HAMMING2(每箱2位)。当WTA_K=4时,我们取4个随机点计算每个点bin(也将占用可能值为0、1、2或3的2位)。;参数七:int类型的scoreType,HARRIS_SCORES表示使用HARRIS算法对特征进行排序(分数写入KeyPoint::score,用于保留最佳nfeatures功能);FAST_SCORE是产生稍微不稳定关键点的参数的替代值,但计算起来要快一点;参数八:int类型的patchSize,定向简短描述符使用的修补程序的大小。当然,在较小的金字塔层特征覆盖的感知图像区域将更大;参数九:int类型的fastThreshold,快速阈值;void xfeatures2d::SURT::detect( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask=noArray() );参数一:InputArray类型的image,输入cv::Mat;参数二:std::Vector<KeyPoint>类型的keypoints,检测到的关键点;参数三:InputArray类型的mask,默认为空,指定在何处查找关键点的掩码(可选)。它必须是8位整数感兴趣区域中具有非零值的矩阵。;void xfeatures2d::SURT::compute( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors );参数一:InputArray类型的image,输入cv::Mat;参数二:std::Vector<KeyPoint>类型的keypoints,描述符不能为其已删除计算的。有时可以添加新的关键点,例如:SIFT duplicates keypoint有几个主要的方向(每个方向);参数三:OutputArray类型的descriptors,计算描述符;// 该函数结合了detect和compute,参照detect和compute函数参数void xfeatures2d::SURT::detectAndCompute( InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints, OutputArray descriptors, bool useProvidedKeypoints=false );绘制关键点函数原型void drawKeypoints( InputArray image, const std::vector<KeyPoint>& keypoints, InputOutputArray outImage, const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT );参数一:InputArray类型的image,;参数二:std::Vector<KeyPoint>类型的keypoints,原图的关键点;参数三:InputOutputArray类型的outImage,其内容取决于定义在输出图像。请参阅参数五的标志flag);参数四:cv::Scalar类型的color,绘制关键点的颜色,默认为Scalar::all(-1)随机颜色,每个点都是这个颜色,那么随机时,每个点都是随机的;参数五:int类型的flags,默认为DEFAULT,具体参照DrawMatchesFlags枚举如下: ...

June 23, 2020 · 4 min · jiezi

OpenCV开发笔记六十四红胖子8分钟带你深入了解SURF特征点图文并茂浅显易懂程序源码

若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106816775各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门) OpenCV开发专栏(点击传送门)上一篇:《OpenCV开发笔记(六十三):红胖子8分钟带你深入了解SIFT特征点(图文并茂+浅显易懂+程序源码)》下一篇:持续补充中… 前言 红胖子,来也! 识别除了传统的模板匹配之外就是体征点了,前面介绍了SIFT特征点,而SUFT是改进后SIFT特征点。 Demo SURF特征点概述 SURF,即加速稳健特征(Speeded Up Robust Features)是一个稳健的图像识别和描述算法,首先于2006年发表在欧洲计算机视觉国际会议(Europeon Conference on Computer Vision,ECCV)。该算法可被用于计算机视觉任务,如物件识别和3D重构。他部分的灵感来自于SIFT算法。SURF标准的版本比SIFT要快数倍,并且其作者声称在不同图像变换方面比SIFT更加稳健。 SURF 基于近似的2D 离散小波变换响应和并且有效地利用了积分图。 在 SIFT 中, Lowe 在构建尺度空间时使用 DoG 对 LoG 进行近似。 SURF使用盒子滤波器(box_filter)对 LoG 进行近似。在进行卷积计算时可以利用积分图像(积分图像的一大特点是:计算图像中某个窗口内所有像素和时,计算量的大小与窗口大小无关) ,是盒子滤波器的一大优点。而且这种计算可以在不同尺度空间同时进行。同样 SURF 算法计算关键点的尺度和位置是也是依赖与 Hessian 矩阵行列式的。 SURF算法采用了很多方法来对每一步进行优化从而提高速度。分析显示在结果效果相当的情况下SURF的速度是SIFT的3倍。SURF善于处理具有模糊和旋转的图像,但是不善于处理视角变化和光照变化。(SIFT特征是局部特征,其对旋转、尺度缩放、亮度变化保持不变性,对视角变化、仿射变换、噪声也保持一定程度的稳定性) 特征检测步骤步骤一:构造Hessian矩阵,计算特征值 surf构造的金字塔图像与sift有很大不同,就是因为这些不同才加快了其检测的速度。Sift采用的是DOG图像,而surf采用的是Hessian矩阵行列式近似值图像。首先是图像中某个像素点的Hessian矩阵: 步骤二:构造高斯金字塔 相比于sift算法的高斯金字塔构造过程,sift算法速度有所提高。 在sift算法中,每一组(octave)的图像大小是不一样的,下一组是上一组图像的降采样(1/4大小);在每一组里面的几幅图像中,他们的大小是一样的,不同的是他们采用的尺度不同。而且在模糊的过程中,他们的高斯模板大小总是不变的,只是尺度改变。对于surf算法,图像的大小总是不变的,改变的只是高斯模糊模板的尺寸,当然,尺度也是在改变的。 上图中a为高斯模板保持不变,图像大小改变的情况,适用于sift算法,图b是高斯模板改变,图像大小保持不变的情况,适用于surf算法。因为surf算法没有了降采样的过程,因此处理速度得到提高。 步骤三:关键点定位 在每个候选的位置上,通过一个拟合精细的模型来确定位置和尺度。关键点的选择依据于它们的稳定程度。 步骤四:方向确定 将经过hessian矩阵处理过的每个像素点与其3维领域的26个点进行大小比较,如果它是这26个点中的最大值或者最小值,则保留下来,当做初步的特征点。 步骤五:关键点描述 在特征点周围取一个正方形框,框的边长为20s(s是所检测到该特征点所在的尺度)。该框带方向,方向当然就是第4步检测出来的主方向了。然后把该框分为16个子区域,每个子区域统计25个像素的水平方向和垂直方向的haar小波特征,这里的水平和垂直方向都是相对主方向而言的。该haar小波特征为水平方向值之和,水平方向绝对值之和,垂直方向之和,垂直方向绝对值之和。该过程的示意图如下所示: SurfFeatureDetector类 该类是opencv中nonfree模块中的,之前没有勾选,需要需要重新勾选编译才会有的,所以按照3.4的最新版本为3.4.10,笔者重新编译了一个版本,带contrib模块,编译请参考博文《OpenCV开发笔记(三十四):红胖子带你小白式编译Qt+openCV3.4.1+opencv_contrib(全网最简单最强,可读性最高,没有之一)》,配置时,需要额外勾选下图显示的项: 编译好后,头文件和库替换,重新连接到3.4.10版本,要使用surf,需要添加头文件: #include <opencv2/xfeatures2d/nonfree.hpp> 编译时仍然报错,如下: 但是确实勾选了,配置也打出来了支持nonfree模块,也许是编译抽风了,所以重新编译一下,发现还是一样错误,索性直接定位到错误文件,修改源码, 如下图: 编译可以成功了。 SurfFeatureDetector类的使用cv::Ptr<cv::xfeatures2d::SURF> _pSurf = cv::xfeatures2d::SurfFeatureDetector::create();std::vector<cv::KeyPoint> keyPoints1;//特征点检测_pSurf->detect(srcMat, keyPoints1);SURF宏定义typedef SURF SurfFeatureDetector;typedef SURF SurfDescriptorExtractor;SURF相关函数原型static Ptr<SURF> create(double hessianThreshold=100, int nOctaves = 4, int nOctaveLayers = 3, bool extended = false, bool upright = false);参数一:double类型的hessianThreshold,默认值100,用于SURF的hessian关键点检测器的阈值;参数二:int类型的nOctaves,默认值4,关键点检测器将使用的金字塔倍频程数;参数三:int类型的nOctaveLayers,默认值3,每八度音阶的层数。3是D.Lowe纸张中使用的值。这个八度音阶数是根据图像分辨率自动计算出来的;参数四:bool类型的extended,扩展描述符标志(true-使用扩展的128个元素描述符;false-使用64个元素描述符),默认false;参数五:bool类型的upright,向上向右或旋转的特征标志(true-不计算特征的方向;faslse-计算方向),默认false;void xfeatures2d::SURT::detect( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask=noArray() );参数一:InputArray类型的image,输入cv::Mat;参数二:std::Vector<KeyPoint>类型的keypoints,检测到的关键点;参数三:InputArray类型的mask,默认为空,指定在何处查找关键点的掩码(可选)。它必须是8位整数感兴趣区域中具有非零值的矩阵。;void xfeatures2d::SURT::compute( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors );参数一:InputArray类型的image,输入cv::Mat;参数二:std::Vector<KeyPoint>类型的keypoints,描述符不能为其已删除计算的。有时可以添加新的关键点,例如:SIFT duplicates keypoint有几个主要的方向(每个方向);参数三:OutputArray类型的descriptors,计算描述符;// 该函数结合了detect和compute,参照detect和compute函数参数void xfeatures2d::SURT::detectAndCompute( InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints, OutputArray descriptors, bool useProvidedKeypoints=false );绘制关键点函数原型void drawKeypoints( InputArray image, const std::vector<KeyPoint>& keypoints, InputOutputArray outImage, const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT );参数一:InputArray类型的image,;参数二:std::Vector<KeyPoint>类型的keypoints,原图的关键点;参数三:InputOutputArray类型的outImage,其内容取决于定义在输出图像。请参阅参数五的标志flag);参数四:cv::Scalar类型的color,绘制关键点的颜色,默认为Scalar::all(-1)随机颜色,每个点都是这个颜色,那么随机时,每个点都是随机的;参数五:int类型的flags,默认为DEFAULT,具体参照DrawMatchesFlags枚举如下: ...

June 17, 2020 · 4 min · jiezi

项目实战QtOpenCV激光射击游识别激光识别圆

若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106647346红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门) Qt开发专栏:项目实战(点击传送门)OpenCV开发专栏(点击传送门) 需求 激光射击游戏,外设激光射击目标圆圈,计分游戏。 原理 使用OpenCV打开摄像头,识别圆圈,识别激光,判断激光点是否在圆圈内。 注意 需要摄像头,摄像头对准白色矩形区域,游戏钱需要先对摄像头进行手动校准,提供调整校准标定的功能,调整到圆圈和激光都可识别。 相关博客 **《项目实战:Qt+OpenCV操作摄像头拍照、调节参数和视频录制》 《OpenCV开发笔记(一):OpenCV介绍、编译》 《OpenCV开发笔记(五):OpenCV读取与操作摄像头》 《OpenCV开发笔记(七):OpenCV基础图形绘制》 《OpenCV开发笔记(十):OpenCV图像颜色通道分离和图像颜色多通道混合》 《OpenCV开发笔记(二十一):算法基础之形态学滤波-膨胀》 《OpenCV开发笔记(二十二):算法基础之形态学滤波-腐蚀》 《OpenCV开发笔记(二十八):带你学习图像识别之阈值化》 《OpenCV开发笔记(三十六):红胖子8分钟带你深入了解缩放与图像金字塔(图文并茂+浅显易懂+程序源码)》 《OpenCV开发笔记(五十三):红胖子8分钟带你深入了解模板匹配识别(图文并茂+浅显易懂+程序源码)》** Demo:激光射击游戏 v1.0.0 下载地址 CSDN:https://download.csdn.net/download/qq21497936/12507420 QQ群:1047134658(点击“文件”搜索“shootGame”,群内与博文同步更新所有可开源的源码模板) 核心代码#ifndef SHOOTGAMEWIDGET_H#define SHOOTGAMEWIDGET_H#include <QWidget>#include "OpenCVManager.h"#include <QTimer>#include <QThread>namespace Ui {class ShootGameWidget;}class ShootGameWidget : public QWidget{ Q_OBJECTpublic: explicit ShootGameWidget(QWidget *parent = 0); ~ShootGameWidget();protected slots: void slot_captureOneFrame(cv::Mat mat); bool slot_recognize(cv::Mat mat, bool show = false); void slot_timeOut();private slots: void on_pushButton_start_clicked(); void on_pushButton_out_clicked(); void on_pushButton_startCameraTest_clicked(); void on_pushButton_stopCameraTest_clicked(); void on_pushButton_add1_clicked(); void on_pushButton_dec1_clicked(); void on_pushButton_add2_clicked(); void on_pushButton_dec2_clicked(); void on_pushButton_add3_clicked(); void on_pushButton_dec3_clicked();private: void paintEvent(QPaintEvent *event); void timerEvent(QTimerEvent *event);private: Ui::ShootGameWidget *ui; OpenCVManager *_pOpenCVManager; QThread *_pOpenCVManagerThread; cv::Mat _srcMat; QImage _srcImage; int _r; int _penWidth; cv::Mat _circleMat; cv::Mat _dotMat; cv::Mat _dot2Mat; cv::Mat _dot3Mat; cv::Mat _dot4Mat; cv::Mat _dot5Mat; cv::Mat _dot6Mat; cv::Mat _dot7Mat; int _timerId; double _f; int _margin; int _count; int _totalTime; // 总时间,默认60s int _currentTime; // 当前时间 bool _running; // 是否游戏开始 QPoint _centerPoint; // 刷新圆圈的位置 bool _hitFlag; // 是否击中标志,每次刷新位置,设置false,判断是否第一次击中用于计分 int _score; // 得分 QTimer *_pTimer; // 定时器,定时减少秒数 bool _result; // 标记是否打完出结果};#endif // SHOOTGAMEWIDGET_Hvoid ShootGameWidget::on_pushButton_start_clicked(){ if(!_pOpenCVManager->startCapture(0, 800, 600)) { QMessageBox::information(0, "错误", "检测摄像头失败"); return; } ui->label_title->setVisible(false); ui->pushButton_start->setVisible(false); ui->pushButton_out->setVisible(false); ui->groupBox->setVisible(false); _hitFlag = false; _score = 0; _currentTime = _totalTime; _running = true; _result = false; _pTimer->start();}void ShootGameWidget::paintEvent(QPaintEvent *event){ if(ui->pushButton_stopCameraTest->isEnabled() || _running) { QPainter painter(this); painter.fillRect(rect(), Qt::black); painter.setPen(QPen(Qt::white, 1)); painter.drawRect(_margin, _margin, rect().width() - _margin * 2, rect().height() - _margin * 2); QPen pen = painter.pen(); pen.setWidth(10); pen.setColor(Qt::green); painter.setPen(pen); painter.drawEllipse(_centerPoint, _r/2, _r/2);// painter.setPen(QPen(Qt::red, 10));// painter.drawPoint(_centerPoint); if(_running) { painter.setPen(QPen(Qt::white, 1)); painter.drawText(300, 50, QString("得分: %1").arg(_score)); painter.drawText(500, 50, QString("倒计时: %1").arg(_currentTime)); if(_hitFlag) { painter.drawText(700, 50, QString("已击中")); }else{ painter.drawText(700, 50, QString("未击中")); } } } if(_result) { QPainter painter(this); painter.setPen(QPen(Qt::black, 4)); QFont font = painter.font(); font.setPixelSize(64); painter.setFont(font); painter.drawText(rect(), Qt::AlignCenter, QString("游戏结束,您的得分为 %1 !!!").arg(_score)); }}void ShootGameWidget::slot_timeOut(){ if(_running) { _currentTime--; if(_currentTime == 0) { if(!_pOpenCVManager->stopCapture()) { } ui->label_title->setVisible(true); ui->pushButton_start->setVisible(true); ui->pushButton_out->setVisible(true); ui->groupBox->setVisible(true); _hitFlag = false; _currentTime = _totalTime; _running = false; _pTimer->stop(); _result = true; } update(); }} ...

June 9, 2020 · 2 min · jiezi

OpenCV开发笔记六十一红胖子8分钟带你深入了解ShiTomasi角点检测图文并茂浅显易懂程序源码

若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106436768 各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门) OpenCV开发专栏(点击传送门)上一篇:《OpenCV开发笔记(六十):红胖子8分钟带你深入了解Harris角点检测(图文并茂+浅显易懂+程序源码)》 下一篇:持续补充中… 前言 红胖子,来也! 做识别,有时候遇到需求,比如识别一个三角形,并求得三角形三个顶点的角度,这种属于教育集合场景,还有其他类似场景,那么检测角点就显得很重要了。 Demo 图像特征三大类型边缘:图像强度发生突变的区域,其实就是高强度梯度区域;角点:两个边缘相交的地方,看起来像一个角;斑点:按特征划分的区域,强度特别高、强度特别低或具备特定纹理的区域; Shi-Tomasi角点概述 Shi-Tomasi角点检测是改进了Harris算法,次算法最原始的定义是将矩阵M的行列式与M的迹想见,再将差值进行同预先给定的预制进行比较,后来再次改进,若两个特征值中较小的一个大于最小阈值,则会得到强角点。 原理 由于Harris算法的稳定性和k值有关,Shi-Tomasi发现,角点的稳定性和矩阵M的较小特征值有关,改进的Harris算法即直接计算出矩阵M的特征值,用较小的特征值与阈值比较,大于阈值的即为强特征点。 Harris角点概述 Harris角点检测是一种基于灰度图像的角点提取算法,稳定性高,在opencv中harris角点检测的性能相对较低,因为其使用了高斯滤波。 基于灰度图像的角点检测又分为基于梯度、基于模板和基于模板梯度组合三类型的方法,而Harris算法就是基于灰度图像中的基于模板类型的算法。 Harris角点原理 人眼对角点的识别通常是通过一个局部的小窗口内完成的:如果在各个方向上移动这个小窗口,窗口内的灰度发生了较大的变化,那么说明窗口内存在角点,具体分为以下三种情况: 如果在各个方向移动,灰度几乎不变,说明是平坦区域;如果只沿着某一个方向移动,灰度几乎不变,说明是直线;如果沿各个方向移动,灰度均发生变化,说明是角点。 基本的原理,如下图: 具体的计算公式如下: 泰勒展开: 代入得到: 其中: 二次项函数本质上就是一个椭圆函数,椭圆的扁平率和尺寸是由矩阵M的两个特征值决定的。 矩阵M的两个特征值与图像中的角点,边缘,平坦区域的关系。 Harris定义角点响应函数即: 即R=Det(M)-ktrace(M)trace(M),k为经验常数0.04~0.06 。 定义当R>threshold时且为局部极大值的点时,定义为角点。 Shi-Tomasi检测角点函数原型// 重载函数:九个参数void goodFeaturesToTrack( InputArray image, OutputArray corners, int maxCorners, double qualityLevel, double minDistance, InputArray mask = noArray(), int blockSize = 3, bool useHarrisDetector = false, double k = 0.04);// 重载函数:十个参数void goodFeaturesToTrack( InputArray image, OutputArray corners, int maxCorners, double qualityLevel, double minDistance, InputArray mask, int blockSize, int gradientSize, bool useHarrisDetector = false, double k = 0.04 );参数一:InputArray类型的image,输入图像,即源图像,填Mat类的对象 即可,且须为单通道8位或者浮点型32位单通道图像;参数二:OutputArray类型的corners,检测到的角点的输出向量;参数三:int类型的maxCorners,角点的最大数据量;参数四:double类型的qualityLevel,角点检测可接受的最小特征值。其实实际用于过滤角点的最小特征是qualityLevel与图像中最大特征值的乘积。所以qualityLevel通常不会超过1(常用的值为0.10或者0.01)。检测完后所有的交点后,还要进一步提出掉一些距离较近的角点;参数五:double类型的minDistance,角点之间的最细小距离,次参数用于保证返回的角点之间的距离不小于minDistance;参数六:InputArray类型的mask,可选参数,表示感情兴的区域,默认为noArray(),若此参数非空则必须需为CV_8UC1类型,且和第一个参数image有相同的尺寸;参数七:int类型的blockSize,有默认值3,是计算导数自相关矩阵时指定的领域范围;参数八:bool类型的useHarrisDetector,只是是否使用Harris角点检测,默认为false,不使用;参数九:double类型的k,为用于设置Hessian自相关矩阵韩烈士的相对权重的权重系数,默认值为0.04; ...

May 30, 2020 · 3 min · jiezi

RuntimeError-filter-weights-array-has-incorrect-shape

完整代码如下 import cv2import numpy as npfrom scipy import ndimagekernel133 = np.array([ [-1, -1, -1], [-1, 8, -1], [-1, -1, -1]])kernel133_D = np.array([ [1, 1, 1], [1, -8, 1], [1, 1, 1]])img = cv2.imread('jj.jpg')img = ndimage.convolve(img, kernel133_D)cv2.imshow('enhanced', img)cv2.waitKey(0)完整的报错如下 Traceback (most recent call last): File "D:/Python/测试专用文件夹/opencv测试.py", line 19, in <module> img = ndimage.convolve(img, kernel133_D) File "C:\Users\yjc\AppData\Local\Programs\Python\Python37\lib\site-packages\scipy\ndimage\filters.py", line 745, in convolve origin, True) File "C:\Users\yjc\AppData\Local\Programs\Python\Python37\lib\site-packages\scipy\ndimage\filters.py", line 595, in _correlate_or_convolve raise RuntimeError('filter weights array has incorrect shape.')RuntimeError: filter weights array has incorrect shape.通过这个文章,我知道了,要加一个 ...

July 3, 2019 · 1 min · jiezi

Mac环境安装OpenCVVScode调试C程序

背景最近在研究图像识别相关代码——OpenCV,为了便于调试,就要在Mac上搭建一个调试c++程序的调试环境。我这跑通了,分享给大家。 环境Mac OS 10.14.5xcode-select v2354Visual Studio code 1.35.1OpenCV 3.4.5Clang 1001.0.46.4CMake 3.14.5步骤说明编译环境准备安装OpenCV安装VScode 插件VScode 项目配置OpenCV HelloWorld 环境准备Mac 自带有C/C++环境,就不再赘述。 Xcode Command Line Tools是必须的,可通过一下命令行触发安装程序,或者下载安装。 命令安装 xcode-select sudo xcode-select --install下载 xcode-select 安装Apple Developer Download 选择下载文件注意这里提示的版本号!命令行安装速度很慢,且失败率很高,建议通过下载dmg文件安装CMake 准备 编译OpenCV时要用到cmake。同样可以通过homebrew或者下载安装。下载方式安装的CMake,cmake可执行程序在/Applications/CMake.app/Contents/bin/cmake. 如果你用的homebrew方式安装opencv那么CMake就不是必须的.pkg-config 安装编译引用有opencv库的c/c++代码需要附带很多参数来告知include path,libs等,用pkg-config就能精简编译参数。 brew install pkg-config安装OpenCV有两种方式安装。 brew install## 一个命令安装好opencv3brew install opencv3用homebrew安装很方便,就是安装时间很长(我用了一个大白天)。额外还会安装python-opencv。编译安装点击下载源代码。这里我选择的是Sources 3.4.5 解压后,进入目录 cd <opencv 解压后目录>mkdir releasecd releasecmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local makesudo make install这里创建的release目录会放cmake命令产生的成果。CMAKE_INSTALL_PREFIX配置的目录会存make命令产生的成果。 到这里如果都没报错就算安装成功了。 一般都不会出问题,在虚拟环境不一定能成功。参考自 编译安装opencv 写个C++ Hello World先写一个只引用了标准库的C++代码试试看。 /// ./main.cpp#include <stdio.h>#include <iostream>int main(int argc, const char * argv[]) { std::cout << "Hello, World!\n"; return 0;}结果如下。没问题就继续尝试在代码引入OpenCV库。 ...

June 28, 2019 · 3 min · jiezi

OpenCV搞定腾讯滑块验证码

前言废话滑块验证码破解是一直都想搞的项目,毕竟多数网站都会采用滑块验证码,于是最近在修改论文的闲暇之余把这事儿给解决了。要搞现在的滑块验证码绕不开图像处理,图像处理当然是首推OpenCV-Python啦!当然我的OpenCV非常菜(P.S.两天速成不敢保证代码质量),发现问题就直接指出嘛,不用走流程啦! 环境首先需要一个python,然后安装opencv的python库,如下:pip install opencv-python然后测试一下是否可用,如下: import cv2 as cvimport numpy as npif __name__ == '__main__': img = np.ones((200, 200, 3), np.uint8) * 255 cv.rectangle(img, (50, 50), (150, 150), (0, 0, 255), 2) cv.imshow('test', img) cv.waitKey(0) cv.destroyAllWindows()正常的话就会如下显示: OpenCV的使用相关的API我也是边用边查的,用得也是相当生疏!具体的常用方法大家只好自行百度了,我就不献丑了! 实现原理及方法腾讯滑块验证这次搞得目标就是腾讯滑块验证码,调用腾讯滑块这个接口的网站还是挺多的,比如非常好用的在线画图网站ProcessOn,其中滑块验证部分类似这样子的: 抓个包发现只有滑块图和带缺口的图,如下:破解滑块验证码最为关键的地方在于找到滑块缺口的位置,找到缺口位置后就可以利用Selenium模拟拖动滑块到指定位置实现破解,之前的老办法就是将完整图的像素点和带缺口图的像素点进行比较从而得到缺口位置,但是现在一般不会将完整图暴露给我们,所以只有在带有缺口的图上进行处理。我这里一共有两种方案进行缺口位置识别,一种是基于模板匹配的,另一种是基于轮廓检测的,下面会细讲两种方案的实现方法。 模板匹配识别缺口具体是实现过程如下:1.处理滑块的图片 灰度化滑块图片处理一下滑块图中滑块的外圈使用inRange二值化滑块图使用开运算去除白色噪点运行结果如下所示(左侧为原始滑块,右侧为处理后的滑块): 2.处理带缺口的图片 先来个高斯滤波去噪灰度化带缺口图使用阈值二值化该图运行结果如下所示(左侧为原始图,右侧为处理后的图): 3.进行模板匹配调用模板匹配API并圈出匹配上的区域,结果如下所示: 警告警告警告这种方法的缺口识别率在50%左右,很大一部分原因是滑块图的背景为纯白色,这在匹配时会产生很大的干扰,要是能将滑块图的背景变为透明,正确的匹配率可以达到90%以上 如果大家有任何将滑块图的背景变为透明的办法,可以留言到评论区,我真的万分感谢!!!下面是现阶段的实现代码: # encoding:utf-8import cv2 as cvimport numpy as np# 对滑块进行二值化处理def handle_img1(image): kernel = np.ones((8, 8), np.uint8) # 去滑块的前景噪声内核 gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) width, heigth = gray.shape for h in range(heigth): for w in range(width): if gray[w, h] == 0: gray[w, h] = 96 # cv.imshow('gray', gray) binary = cv.inRange(gray, 96, 96) res = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel) # 开运算去除白色噪点 # cv.imshow('res', res) return res# 模板匹配(用于寻找缺口有点误差)def template_match(img_target, img_template): tpl = handle_img1(img_template) # 误差来源就在于滑块的背景图为白色 blurred = cv.GaussianBlur(img_target, (3, 3), 0) # 目标图高斯滤波 gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY) ret, target = cv.threshold(gray, 127, 255, cv.THRESH_BINARY) # 目标图二值化 # cv.imshow("template", tpl) # cv.imshow("target", target) method = cv.TM_CCOEFF_NORMED width, height = tpl.shape[:2] result = cv.matchTemplate(target, tpl, method) min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result) left_up = max_loc right_down = (left_up[0] + height, left_up[1] + width) cv.rectangle(img_target, left_up, right_down, (0, 0, 255), 2) cv.imshow('res', img_target)if __name__ == '__main__': img0 = cv.imread('./demo/3/hycdn_3.jpg') img1 = cv.imread('./demo/3/hycdn_3_2.png') template_match(img0, img1) cv.waitKey(0) cv.destroyAllWindows()轮廓检测识别缺口基于轮廓检测缺口的思路简单很多,加上合理的条件识别率在95%以上,实现过程如下: ...

May 18, 2019 · 2 min · jiezi

OpenCV调用摄像头

OpenCV调用摄像头环境python:python3.6摄像头:网络摄像头Python库:openCV # -*- coding: utf-8 -*-# @author leone# @desc 使用 python 的 openCV 获取网络摄像头的数据# @version 2018-12-23import cv2import sys# 根据摄像头设置IP及rtsp端口url = 'rtsp://account:password@192.168.0.35:554/11'# 读取视频流cap = cv2.VideoCapture(url)# 设置视频参数cap.set(3, 480)print(cap.isOpened())print(sys.version)print(cv2.__version__)while cap.isOpened(): ret_flag, img_camera = cap.read() cv2.imshow("camera", img_camera) # 每帧数据延时 1ms, 延时为0, 读取的是静态帧 k = cv2.waitKey(1) if k == ord('s'): cv2.imwrite("test.jpg", img_camera) if k == ord('q'): break# 释放所有摄像头cap.release()# 删除窗口cv2.destroyAllWindows()由于网络摄像头的RTSP:实时流协议要手动开启,进入你的摄像头管理界面,例如:192.168.0.35 找到设置->网络设置->RTSP设置->开启RTSP开关 最好保存设置,并重启摄像头。 另外附上基于python的人脸识别demo支持多张人脸github

April 26, 2019 · 1 min · jiezi

Canny 边缘检测及相关应用

该内容为 《学习图像局部特征检测和描述-基于OpenCV源码分析的算法与实现》《OpenCV 3 计算机视觉-Python语言实现》OpenCV官方网站的 https://docs.opencv.org/maste...的学习内容 1 Canny 边缘检测Canny 边缘检测方法是由 Canny 于1996 年提出的一种公认为效果较好的边缘检测方法。 一个好的边缘检测方法应该满足三项指标 1、低失误率,即不能漏检也不能错检2、高的位置精度,标定的边缘像素点与真正的边缘中心之间距离应该最小3、每个边缘应该由唯一的响应,即得到单像素宽度的边缘。基于此,Canny提出了判定边缘检测算子的3个准则: 1 - 信噪比准则2 - 定位精度准则3 - 单边缘响应准则Canny 算子实现过程共有4(5)个步骤: 1 - 平滑处理,使用高斯滤波器对图像进行去噪处理2 - 计算梯度3 - 非极大值抑制,即在图像边缘上使用非最大抑制NMS4 - 滞后阈值处理,即在检测到的边缘上使用双阈值去除假阳性(false positive)5 - 最后分析所有边缘及其之间的连接,以确保保留真正的边缘,同时消除不明显的边缘

April 21, 2019 · 1 min · jiezi

自己动手玩转深度学习项目

摘要: 深度学习项目何其多?对于入门而言,合适且有趣的项目能产生积极的影响,本文总结了一份计算机视觉领域的几个有趣项目,感兴趣的可以动手尝试一下。自从2012年AlexNet网络在ImageNet挑战赛上取得巨大成功之后,计算机视觉和深度学习等领域再一次迎来研究热潮。计算机视觉,从字面意义上理解就是让计算机等机器也具备人类视觉,研究让机器进行图像分类、目标检测等。在这近十年里,该领域取得的成就让人大吃一惊,有些研究已经超越了人类的表现水平。对于想入门或者从事深度学习领域的工作者而言,一般是从计算机视觉入手,网上有很多资料去介绍理论方面的知识,进行相应的实践也必不可少。本文总结一些在计算机视觉和深度学习领域的一些实践项目,供读者针对自己的感兴趣点挑选并实践。如果不熟悉上述术语,可以从下面的文章中了解更多的相关信息:一份“新奇”的深度学习介绍两个月探索深度学习和计算机视觉从神经科学到计算机视觉Andrew Ng在Coursera上的计算机视觉课程下面进行正文介绍:1.使用OpenCV进行手部动作跟踪项目地址:akshaybahadur21/HandMovementTracking为了执行视频跟踪,算法分析连续视频帧并输出帧之间的目标移动。针对这类问题,有各种各样的算法,每种算法都有各自的优缺点。在选择使用哪种算法时,针对实际应用场景考虑是很重要的。视觉跟踪系统有两个主要组成部分:目标表示和局部化,以及过滤和数据关联。视频跟踪是使用相机随时间定位移动物体(或多个物体)的过程。它有多种用途,比如:人机交互、安全和监控、视频通信和压缩、增强现实、交通控制、医学成像和视频编辑等。项目代码如下:import numpy as npimport cv2import argparsefrom collections import dequecap=cv2.VideoCapture(0)pts = deque(maxlen=64)Lower_green = np.array([110,50,50])Upper_green = np.array([130,255,255])while True: ret, img=cap.read() hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV) kernel=np.ones((5,5),np.uint8) mask=cv2.inRange(hsv,Lower_green,Upper_green) mask = cv2.erode(mask, kernel, iterations=2) mask=cv2.morphologyEx(mask,cv2.MORPH_OPEN,kernel) #mask=cv2.morphologyEx(mask,cv2.MORPH_CLOSE,kernel) mask = cv2.dilate(mask, kernel, iterations=1) res=cv2.bitwise_and(img,img,mask=mask) cnts,heir=cv2.findContours(mask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2:] center = None if len(cnts) > 0: c = max(cnts, key=cv2.contourArea) ((x, y), radius) = cv2.minEnclosingCircle(c) M = cv2.moments(c) center = (int(M[“m10”] / M[“m00”]), int(M[“m01”] / M[“m00”])) if radius > 5: cv2.circle(img, (int(x), int(y)), int(radius),(0, 255, 255), 2) cv2.circle(img, center, 5, (0, 0, 255), -1) pts.appendleft(center) for i in xrange (1,len(pts)): if pts[i-1]is None or pts[i] is None: continue thick = int(np.sqrt(len(pts) / float(i + 1)) * 2.5) cv2.line(img, pts[i-1],pts[i],(0,0,225),thick) cv2.imshow(“Frame”, img) cv2.imshow(“mask”,mask) cv2.imshow(“res”,res) k=cv2.waitKey(30) & 0xFF if k==32: break# cleanup the camera and close any open windowscap.release()cv2.destroyAllWindows()54行代码即可解决这个问题,很简单吧!该项目依赖Opencv包,需要在计算机中安装OpenCV才能执行这个项目,下面是针对Mac系统、Ubuntu系统以及Windows系统的安装方法:Mac系统:如何在MacOS上安装OpenCV3Ubuntu系统:OpenCV:在Ubuntu中安装OpenCV-PythonWindows系统:在Windows中安装OpenCV-Python2.使用OpenCV进行睡意检测项目地址:akshaybahadur21/Drowsiness_Detection睡意检测对于长时间驾驶、工厂生产等场景很重要,由于长时间开车时,容易产生睡意,进而可能导致事故。当用户昏昏欲睡时,此代码可以通过检测眼睛来发出警报。依赖包CV2immutilsDLIBSciPy实现算法每只眼睛用6个(x,y)坐标表示,从眼睛的左角开始,然后顺时针绕眼睛工作:条件它检查20个连续帧,如果眼睛纵横比低于0.25,则生成警报。关系实现3.使用Softmax回归进行数字手写体识别项目地址:akshaybahadur21/Digit-Recognizer此代码使用softmax回归对不同的数字进行分类,依赖的包有点多,可以安装下Conda,它包含了机器学习所需要的所有依赖包。描述Softmax回归(同义词:多项Logistic、最大熵分类器、多类Logistic回归)是逻辑回归的推广,可以将其用于多类分类(假设类间是互斥的)。相反,在二分类任务中使用(标准)Logistic回归模型。Python实现使用的是MNIST数字手写体数据集,每张图像大小为28×28,这里尝试使用三种方法对0到9的数字进行分类,分别是Logistic回归、浅层神经网络和深度神经网络。Logistic回归:import numpy as npimport matplotlib.pyplot as pltdef softmax(z): z -= np.max(z) sm = (np.exp(z).T / np.sum(np.exp(z), axis=1)) return smdef initialize(dim1, dim2): """ :param dim: size of vector w initilazied with zeros :return: """ w = np.zeros(shape=(dim1, dim2)) b = np.zeros(shape=(10, 1)) return w, bdef propagate(w, b, X, Y): """ :param w: weights for w :param b: bias :param X: size of data(no of features, no of examples) :param Y: true label :return: """ m = X.shape[1] # getting no of rows # Forward Prop A = softmax((np.dot(w.T, X) + b).T) cost = (-1 / m) * np.sum(Y * np.log(A)) # backwar prop dw = (1 / m) * np.dot(X, (A - Y).T) db = (1 / m) * np.sum(A - Y) cost = np.squeeze(cost) grads = {“dw”: dw, “db”: db} return grads, costdef optimize(w, b, X, Y, num_iters, alpha, print_cost=False): """ :param w: weights for w :param b: bias :param X: size of data(no of features, no of examples) :param Y: true label :param num_iters: number of iterations for gradient :param alpha: :return: """ costs = [] for i in range(num_iters): grads, cost = propagate(w, b, X, Y) dw = grads[“dw”] db = grads[“db”] w = w - alpha * dw b = b - alpha * db # Record the costs if i % 50 == 0: costs.append(cost) # Print the cost every 100 training examples if print_cost and i % 50 == 0: print(“Cost after iteration %i: %f” % (i, cost)) params = {“w”: w, “b”: b} grads = {“dw”: dw, “db”: db} return params, grads, costsdef predict(w, b, X): """ :param w: :param b: :param X: :return: """ # m = X.shape[1] # y_pred = np.zeros(shape=(1, m)) # w = w.reshape(X.shape[0], 1) y_pred = np.argmax(softmax((np.dot(w.T, X) + b).T), axis=0) return y_preddef model(X_train, Y_train, Y,X_test,Y_test, num_iters, alpha, print_cost): """ :param X_train: :param Y_train: :param X_test: :param Y_test: :param num_iterations: :param learning_rate: :param print_cost: :return: """ w, b = initialize(X_train.shape[0], Y_train.shape[0]) parameters, grads, costs = optimize(w, b, X_train, Y_train, num_iters, alpha, print_cost) w = parameters[“w”] b = parameters[“b”] y_prediction_train = predict(w, b, X_train) y_prediction_test = predict(w, b, X_test) print(“Train accuracy: {} %”, sum(y_prediction_train == Y) / (float(len(Y))) * 100) print(“Test accuracy: {} %”, sum(y_prediction_test == Y_test) / (float(len(Y_test))) * 100) d = {“costs”: costs, “Y_prediction_test”: y_prediction_test, “Y_prediction_train”: y_prediction_train, “w”: w, “b”: b, “learning_rate”: alpha, “num_iterations”: num_iters} # Plot learning curve (with costs) #costs = np.squeeze(d[‘costs’]) #plt.plot(costs) #plt.ylabel(‘cost’) #plt.xlabel(‘iterations (per hundreds)’) #plt.title(“Learning rate =” + str(d[“learning_rate”])) #plt.plot() #plt.show() #plt.close() #pri(X_test.T, y_prediction_test) return ddef pri(X_test, y_prediction_test): example = X_test[2, :] print(“Prediction for the example is “, y_prediction_test[2]) plt.imshow(np.reshape(example, [28, 28])) plt.plot() plt.show()浅层神经网络:import numpy as npimport matplotlib.pyplot as pltdef softmax(z): z -= np.max(z) sm = (np.exp(z).T / np.sum(np.exp(z),axis=1)) return smdef layers(X, Y): "”” :param X: :param Y: :return: """ n_x = X.shape[0] n_y = Y.shape[0] return n_x, n_ydef initialize_nn(n_x, n_h, n_y): """ :param n_x: :param n_h: :param n_y: :return: """ np.random.seed(2) W1 = np.random.randn(n_h, n_x) * 0.01 b1 = np.random.rand(n_h, 1) W2 = np.random.rand(n_y, n_h) b2 = np.random.rand(n_y, 1) parameters = {“W1”: W1, “b1”: b1, “W2”: W2, “b2”: b2} return parametersdef forward_prop(X, parameters): W1 = parameters[‘W1’] b1 = parameters[‘b1’] W2 = parameters[‘W2’] b2 = parameters[‘b2’] Z1 = np.dot(W1, X) + b1 A1 = np.tanh(Z1) Z2 = np.dot(W2, A1) + b2 A2 = softmax(Z2.T) cache = {“Z1”: Z1, “A1”: A1, “Z2”: Z2, “A2”: A2} return A2, cachedef compute_cost(A2, Y, parameters): m = Y.shape[1] W1 = parameters[‘W1’] W2 = parameters[‘W2’] logprobs = np.multiply(np.log(A2), Y) cost = - np.sum(logprobs) / m cost = np.squeeze(cost) return costdef back_prop(parameters, cache, X, Y): m = Y.shape[1] W1 = parameters[‘W1’] W2 = parameters[‘W2’] A1 = cache[‘A1’] A2 = cache[‘A2’] dZ2 = A2 - Y dW2 = (1 / m) * np.dot(dZ2, A1.T) db2 = (1 / m) * np.sum(dZ2, axis=1, keepdims=True) dZ1 = np.multiply(np.dot(W2.T, dZ2), 1 - np.square(A1)) dW1 = (1 / m) * np.dot(dZ1, X.T) db1 = (1 / m) * np.sum(dZ1, axis=1, keepdims=True) grads = {“dW1”: dW1, “db1”: db1, “dW2”: dW2, “db2”: db2} return gradsdef update_params(parameters, grads, alpha): W1 = parameters[‘W1’] b1 = parameters[‘b1’] W2 = parameters[‘W2’] b2 = parameters[‘b2’] dW1 = grads[‘dW1’] db1 = grads[‘db1’] dW2 = grads[‘dW2’] db2 = grads[‘db2’] W1 = W1 - alpha * dW1 b1 = b1 - alpha * db1 W2 = W2 - alpha * dW2 b2 = b2 - alpha * db2 parameters = {“W1”: W1, “b1”: b1, “W2”: W2, “b2”: b2} return parametersdef model_nn(X, Y,Y_real,test_x,test_y, n_h, num_iters, alpha, print_cost): np.random.seed(3) n_x,n_y = layers(X, Y) parameters = initialize_nn(n_x, n_h, n_y) W1 = parameters[‘W1’] b1 = parameters[‘b1’] W2 = parameters[‘W2’] b2 = parameters[‘b2’] costs = [] for i in range(0, num_iters): A2, cache = forward_prop(X, parameters) cost = compute_cost(A2, Y, parameters) grads = back_prop(parameters, cache, X, Y) if (i > 1500): alpha1 = 0.95alpha parameters = update_params(parameters, grads, alpha1) else: parameters = update_params(parameters, grads, alpha) if i % 100 == 0: costs.append(cost) if print_cost and i % 100 == 0: print(“Cost after iteration for %i: %f” % (i, cost)) predictions = predict_nn(parameters, X) print(“Train accuracy: {} %”, sum(predictions == Y_real) / (float(len(Y_real))) * 100) predictions=predict_nn(parameters,test_x) print(“Train accuracy: {} %”, sum(predictions == test_y) / (float(len(test_y))) * 100) #plt.plot(costs) #plt.ylabel(‘cost’) #plt.xlabel(‘iterations (per hundreds)’) #plt.title(“Learning rate =” + str(alpha)) #plt.show() return parametersdef predict_nn(parameters, X): A2, cache = forward_prop(X, parameters) predictions = np.argmax(A2, axis=0) return predictions深度神经网络:import numpy as npimport matplotlib.pyplot as pltdef softmax(z): cache = z z -= np.max(z) sm = (np.exp(z).T / np.sum(np.exp(z), axis=1)) return sm, cachedef relu(z): """ :param z: :return: """ s = np.maximum(0, z) cache = z return s, cachedef softmax_backward(dA, cache): """ :param dA: :param activation_cache: :return: """ z = cache z -= np.max(z) s = (np.exp(z).T / np.sum(np.exp(z), axis=1)) dZ = dA * s * (1 - s) return dZdef relu_backward(dA, cache): """ :param dA: :param activation_cache: :return: """ Z = cache dZ = np.array(dA, copy=True) # just converting dz to a correct object. dZ[Z <= 0] = 0 return dZdef initialize_parameters_deep(dims): """ :param dims: :return: """ np.random.seed(3) params = {} L = len(dims) for l in range(1, L): params[‘W’ + str(l)] = np.random.randn(dims[l], dims[l - 1]) * 0.01 params[‘b’ + str(l)] = np.zeros((dims[l], 1)) return paramsdef linear_forward(A, W, b): """ :param A: :param W: :param b: :return: """ Z = np.dot(W, A) + b cache = (A, W, b) return Z, cachedef linear_activation_forward(A_prev, W, b, activation): """ :param A_prev: :param W: :param b: :param activation: :return: """ if activation == “softmax”: Z, linear_cache = linear_forward(A_prev, W, b) A, activation_cache = softmax(Z.T) elif activation == “relu”: Z, linear_cache = linear_forward(A_prev, W, b) A, activation_cache = relu(Z) cache = (linear_cache, activation_cache) return A, cachedef L_model_forward(X, params): """ :param X: :param params: :return: """ caches = [] A = X L = len(params) // 2 # number of layers in the neural network # Implement [LINEAR -> RELU](L-1). Add “cache” to the “caches” list. for l in range(1, L): A_prev = A A, cache = linear_activation_forward(A_prev, params[“W” + str(l)], params[“b” + str(l)], activation=‘relu’) caches.append(cache) A_last, cache = linear_activation_forward(A, params[“W” + str(L)], params[“b” + str(L)], activation=‘softmax’) caches.append(cache) return A_last, cachesdef compute_cost(A_last, Y): """ :param A_last: :param Y: :return: """ m = Y.shape[1] cost = (-1 / m) * np.sum(Y * np.log(A_last)) cost = np.squeeze(cost) # To make sure your cost’s shape is what we expect (e.g. this turns [[17]] into 17). return costdef linear_backward(dZ, cache): """ :param dZ: :param cache: :return: """ A_prev, W, b = cache m = A_prev.shape[1] dW = (1. / m) * np.dot(dZ, cache[0].T) db = (1. / m) * np.sum(dZ, axis=1, keepdims=True) dA_prev = np.dot(cache[1].T, dZ) return dA_prev, dW, dbdef linear_activation_backward(dA, cache, activation): """ :param dA: :param cache: :param activation: :return: """ linear_cache, activation_cache = cache if activation == “relu”: dZ = relu_backward(dA, activation_cache) dA_prev, dW, db = linear_backward(dZ, linear_cache) elif activation == “softmax”: dZ = softmax_backward(dA, activation_cache) dA_prev, dW, db = linear_backward(dZ, linear_cache) return dA_prev, dW, dbdef L_model_backward(A_last, Y, caches): """ :param A_last: :param Y: :param caches: :return: """ grads = {} L = len(caches) # the number of layers m = A_last.shape[1] Y = Y.reshape(A_last.shape) # after this line, Y is the same shape as A_last dA_last = - (np.divide(Y, A_last) - np.divide(1 - Y, 1 - A_last)) current_cache = caches[-1] grads[“dA” + str(L)], grads[“dW” + str(L)], grads[“db” + str(L)] = linear_activation_backward(dA_last, current_cache, activation=“softmax”) for l in reversed(range(L - 1)): current_cache = caches[l] dA_prev_temp, dW_temp, db_temp = linear_activation_backward(grads[“dA” + str(l + 2)], current_cache, activation=“relu”) grads[“dA” + str(l + 1)] = dA_prev_temp grads[“dW” + str(l + 1)] = dW_temp grads[“db” + str(l + 1)] = db_temp return gradsdef update_params(params, grads, alpha): """ :param params: :param grads: :param alpha: :return: """ L = len(params) // 2 # number of layers in the neural network for l in range(L): params[“W” + str(l + 1)] = params[“W” + str(l + 1)] - alpha * grads[“dW” + str(l + 1)] params[“b” + str(l + 1)] = params[“b” + str(l + 1)] - alpha * grads[“db” + str(l + 1)] return paramsdef model_DL( X, Y, Y_real, test_x, test_y, layers_dims, alpha, num_iterations, print_cost): # lr was 0.009 """ Implements a L-layer neural network: [LINEAR->RELU]*(L-1)->LINEAR->SIGMOID. Arguments: X – data, numpy array of shape (number of examples, num_px * num_px * 3) Y – true “label” vector (containing 0 if cat, 1 if non-cat), of shape (1, number of examples) layers_dims – list containing the input size and each layer size, of length (number of layers + 1). alpha – learning rate of the gradient descent update rule num_iterations – number of iterations of the optimization loop print_cost – if True, it prints the cost every 100 steps Returns: params – params learnt by the model. They can then be used to predict. """ np.random.seed(1) costs = [] # keep track of cost params = initialize_parameters_deep(layers_dims) for i in range(0, num_iterations): A_last, caches = L_model_forward(X, params) cost = compute_cost(A_last, Y) grads = L_model_backward(A_last, Y, caches) if (i > 800 and i<1700): alpha1 = 0.80 * alpha params = update_params(params, grads, alpha1) elif(i>=1700): alpha1 = 0.50 * alpha params = update_params(params, grads, alpha1) else: params = update_params(params, grads, alpha) if print_cost and i % 100 == 0: print(“Cost after iteration %i: %f” % (i, cost)) if print_cost and i % 100 == 0: costs.append(cost) predictions = predict(params, X) print(“Train accuracy: {} %”, sum(predictions == Y_real) / (float(len(Y_real))) * 100) predictions = predict(params, test_x) print(“Test accuracy: {} %”, sum(predictions == test_y) / (float(len(test_y))) * 100) #plt.plot(np.squeeze(costs)) #plt.ylabel(‘cost’) #plt.xlabel(‘iterations (per tens)’) #plt.title(“Learning rate =” + str(alpha)) #plt.show() return paramsdef predict(parameters, X): A_last, cache = L_model_forward(X, parameters) predictions = np.argmax(A_last, axis=0) return predictions通过网络摄像头执行写入运行代码python Dig-Rec.py通过网络摄像头显示图像运行代码python Digit-Recognizer.py梵文字母识别项目地址:akshaybahadur21/Devanagiri-Recognizer此代码可帮助您使用CNN对不同梵文字母进行分类。使用技术使用了卷积神经网络,使用Tensorflow作为框架和Keras API来提供高级抽象。网络结构CONV2D→MAXPOOL→CONV2D→MAXPOOL→FC→Softmax→Classification额外的要点1.可以尝试不同的网络结构;2.添加正则化以防止过拟合;3.可以向训练集添加其他图像以提高准确性;Python实现使用Dataset-DHCD(Devnagari Character Dataset)数据集,每张图大小为32 X 32,详细代码请参考项目地址。运行代码python Dev-Rec.py4.使用FaceNet进行面部识别项目地址:akshaybahadur21/Face-Recoinion此代码使用facenet进行面部识别。facenet的概念最初是在一篇研究论文中提出的,主要思想是谈到三重损失函数来比较不同人的图像。为了提供稳定性和更好的检测,额外添加了自己的几个功能。本项目依赖的包如下:numpy matplotlib cv2 keras dlib h5py scipy描述面部识别系统是能够从数字图像或来自视频源的视频帧识别或验证人的技术。面部识别系统有多种方法,但一般来说,它们都是通过将给定图像中的选定面部特征与数据库中的面部进行比较来工作。功能增加1.仅在眼睛睁开时检测脸部(安全措施);2.使用dlib中的面部对齐功能在实时流式传输时有效预测;Python实现1.网络使用 - Inception Network;2.原始论文 - Google的Facenet;程序1.如果想训练网络,运行Train-inception.py,但是不需要这样做,因为已经训练了模型并将其保存为face-rec_Google.h5,在运行时只需加载这个文件即可;2.现在需要在数据库中放置一些图像。检查/images文件夹,可以将图片粘贴到此,也可以使用网络摄像头拍摄;3.运行rec-feat.py以运行该应用程序;5.表情识别器项目地址akshaybahadur21/Emojinator此项目可识别和分类不同的表情符号。但是目前为止,只支持手势表达的情绪。代码依赖包numpy matplotlib cv2 keras dlib h5py scipy描述表情符号是电子信息和网页中使用的表意文字和表情的符号。表情符号存在于各种类型中,包括面部表情、常见物体、地点和天气以及动物等。功能1.用于检测手的过滤器;2.CNN用于训练模型;Python实现1.网络使用 - 卷积神经网络程序1.首先,创建一个手势数据库。为此,运行CreateGest.py。尝试在框架内稍微移动一下手,以确保模型在训练时不会发生过拟合;2.对所需的所有功能重复此操作;3.运行CreateCSV.py将图像转换为CSV文件;4.训练模型,运行TrainEmojinator.py;5.运行Emojinator.py通过网络摄像头测试模型;总结这些项目都令人印象深刻,所有这些项目都可以在计算机上运行。如果你不想安装任何东西,可以更轻松地在Deep Cognition平台上运行,并且可以在线运行。感谢网络上各种开源项目的贡献。尝试一下各种感兴趣的项目,运行它们并获得灵感。上述这些这只是深度学习和计算机视觉可以做的事情中的一小部分,还有很多事情可以尝试,并且可以将其转变为帮助世界变得更美好的事情,code change world!此外,每个人都应该对许多不同的事情感兴趣。我认为这样可以改善世界、改善生活、改善工作方式,思考和解决问题的方式,如果我们依据现在所掌握的资源,使这些知识领域共同发挥作用,我们就可以在世界和生活中产生巨大的积极影响。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

April 8, 2019 · 9 min · jiezi

活体检测很复杂?仅使用opencv就能实现!(附源码)

摘要: 活体检测在各行各业应用比较广泛,如何实现一个活体检测系统呢?早期实现很困难,现在仅使用opencv即可实现,快来尝试一下吧。什么是活体检测,为什么需要它?随着时代的发展,人脸识别系统的应用也正变得比以往任何时候都更加普遍。从智能手机上的人脸识别解锁、到人脸识别打卡、门禁系统等,人脸识别系统正在各行各业得到应用。然而,人脸识别系统很容易被“非真实”的面孔所欺骗。比如将人的照片放在人脸识别相机,就可以骗过人脸识别系统,让其识别为人脸。为了使人脸识别系统更安全,我们不仅要识别出人脸,还需要能够检测其是否为真实面部,这就要用到活体检测了。目前有许多活体检测方法,包括:纹理分析(Texture analysis),包括计算面部区域上的局部二进制模式(LBP)并使用SVM将面部分类为真脸或假脸;频率分析(Frequency analysis),例如检查面部的傅里叶域;可变聚焦分析(ariable focusing analysis),例如检查两个连续帧之间的像素值的变化。基于启发式的算法(Heuristic-based algorithms),包括眼球运动、嘴唇运动和眨眼检测;光流算法(Optical Flow algorithms),即检查从3D对象和2D平面生成的光流的差异和属性;3D脸部形状,类似于Apple的iPhone脸部识别系统所使用的脸部形状,使脸部识别系统能够区分真人脸部和其他人的打印输出的照片图像;面部识别系统工程师可以组合上述方法挑选和选择适合于其特定应用的活体检测模型。但本教程将采用图像处理中常用方法——卷积神经网络(CNN)来构建一个能够区分真实面部和假面部的深度神经网络(称之为“LivenessNet”网络),将活体检测视为二元分类问题。首先检查一下数据集。活动检测视频为了让例子更加简单明了,本文构建的活体检测器将侧重于区分真实面孔与屏幕上的欺骗面孔。且该算法可以很容易地扩展到其他类型的欺骗面孔,包括打印输出、高分辨率打印等。活体检测数据集来源:iPhone纵向/自拍;录制了一段约25秒在办公室里走来走去的视频;重播了相同的25秒视频,iPhone重录视频;获得两个示例视频,一个用于“真实”面部,另一个用于“假/欺骗”面部。最后,将面部检测应用于两组视频,以提取两个类的单个面部区域。项目结构$ tree –dirsfirst –filelimit 10.├── dataset│ ├── fake [150 entries]│ └── real [161 entries]├── face_detector│ ├── deploy.prototxt│ └── res10_300x300_ssd_iter_140000.caffemodel├── pyimagesearch│ ├── init.py│ └── livenessnet.py├── videos│ ├── fake.mp4│ └── real.mov├── gather_examples.py├── train_liveness.py├── liveness_demo.py├── le.pickle├── liveness.model└── plot.png6 directories, 12 files项目中主要有四个目录:*dataset /:数据集目录,包含两类图像:在播放脸部视频时,手机录屏得到的假脸;手机自拍视频中真脸;face_detector /:由预训练Caffe面部检测器组成,用于定位面部区域;pyimagesearch /:模块包含LivenessNet类函数;video/:提供了两个用于训练了LivenessNet分类器的输入视频;另外还有三个Python脚本:gather_examples.py:此脚本从输入视频文件中获取面部区域,并创建深度学习面部数据集;train_liveness.py:此脚本将训练LivenessNet分类器。训练会得到以下几个文件:1.le .pickle:类别标签编码器;2.liveness.model:训练好的Keras模型;3.plot.png:训练历史图显示准确度和损失曲线;liveness_demo.py:该演示脚本将启动网络摄像头以进行面部实时活体检测;从训练数据集中检测和提取面部区域数据目录:1.dataset / fake /:包含假.mp4文件中的面部区域;2.dataset / real /:保存来自真实.mov文件的面部区域;打开 gather_examples.py文件并插入以下代码:# import the necessary packagesimport numpy as npimport argparseimport cv2import os# construct the argument parse and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-i", “–input”, type=str, required=True, help=“path to input video”)ap.add_argument("-o", “–output”, type=str, required=True, help=“path to output directory of cropped faces”)ap.add_argument("-d", “–detector”, type=str, required=True, help=“path to OpenCV’s deep learning face detector”)ap.add_argument("-c", “–confidence”, type=float, default=0.5, help=“minimum probability to filter weak detections”)ap.add_argument("-s", “–skip”, type=int, default=16, help="# of frames to skip before applying face detection")args = vars(ap.parse_args())首先导入所需的包:第8-19行解析命令行参数:input:输入视频文件的路径;output:输出目录的路径;detector:人脸检测器的路径;confidence:人脸检测的最小概率。默认值为0.5;skip:检测时略过的帧数,默认值为16;之后加载面部检测器并初始化视频流:# load our serialized face detector from diskprint("[INFO] loading face detector…")protoPath = os.path.sep.join([args[“detector”], “deploy.prototxt”])modelPath = os.path.sep.join([args[“detector”], “res10_300x300_ssd_iter_140000.caffemodel”])net = cv2.dnn.readNetFromCaffe(protoPath, modelPath)# open a pointer to the video file stream and initialize the total# number of frames read and saved thus farvs = cv2.VideoCapture(args[“input”])read = 0saved = 0此外还初始化了两个变量,用于读取的帧数以及循环执行时保存的帧数。创建一个循环来处理帧:# loop over frames from the video file streamwhile True: # grab the frame from the file (grabbed, frame) = vs.read() # if the frame was not grabbed, then we have reached the end # of the stream if not grabbed: break # increment the total number of frames read thus far read += 1 # check to see if we should process this frame if read % args[“skip”] != 0: continue下面进行面部检测: # grab the frame dimensions and construct a blob from the frame (h, w) = frame.shape[:2] blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0)) # pass the blob through the network and obtain the detections and # predictions net.setInput(blob) detections = net.forward() # ensure at least one face was found if len(detections) > 0: # we’re making the assumption that each image has only ONE # face, so find the bounding box with the largest probability i = np.argmax(detections[0, 0, :, 2]) confidence = detections[0, 0, i, 2]为了执行面部检测,需要从图像中创建一个区域,该区域有300×300的宽度和高度,以适应Caffe面部检测器。此外脚本假设视频的每一帧中只有一个面部,这有助于防止误报。获得最高概率的面部检测指数,并使用索引提取检测的置信度,之后将低概率的进行过滤,并将结果写入磁盘: # ensure that the detection with the largest probability also # means our minimum probability test (thus helping filter out # weak detections) if confidence > args[“confidence”]: # compute the (x, y)-coordinates of the bounding box for # the face and extract the face ROI box = detections[0, 0, i, 3:7] * np.array([w, h, w, h]) (startX, startY, endX, endY) = box.astype(“int”) face = frame[startY:endY, startX:endX] # write the frame to disk p = os.path.sep.join([args[“output”], “{}.png”.format(saved)]) cv2.imwrite(p, face) saved += 1 print("[INFO] saved {} to disk".format(p))# do a bit of cleanupvs.release()cv2.destroyAllWindows()提取到面部区域后,就可以得到面部的边界框坐标。然后为面部区域生成路径+文件名,并将其写入磁盘中。构建活体检测图像数据集打开终端并执行以下命令来提取“假/欺骗”类别的面部图像:$ python gather_examples.py –input videos/real.mov –output dataset/real \ –detector face_detector –skip 1[INFO] loading face detector…[INFO] saved datasets/fake/0.png to disk[INFO] saved datasets/fake/1.png to disk[INFO] saved datasets/fake/2.png to disk[INFO] saved datasets/fake/3.png to disk[INFO] saved datasets/fake/4.png to disk[INFO] saved datasets/fake/5.png to disk…[INFO] saved datasets/fake/145.png to disk[INFO] saved datasets/fake/146.png to disk[INFO] saved datasets/fake/147.png to disk[INFO] saved datasets/fake/148.png to disk[INFO] saved datasets/fake/149.png to disk同理也可以执行以下命令获得“真实”类别的面部图像:$ python gather_examples.py –input videos/fake.mov –output dataset/fake \ –detector face_detector –skip 4[INFO] loading face detector…[INFO] saved datasets/real/0.png to disk[INFO] saved datasets/real/1.png to disk[INFO] saved datasets/real/2.png to disk[INFO] saved datasets/real/3.png to disk[INFO] saved datasets/real/4.png to disk…[INFO] saved datasets/real/156.png to disk[INFO] saved datasets/real/157.png to disk[INFO] saved datasets/real/158.png to disk[INFO] saved datasets/real/159.png to disk[INFO] saved datasets/real/160.png to disk注意,这里要确保数据分布均衡。执行脚本后,统计图像数量:假:150张图片真:161张图片总计:311张图片实施“LivenessNet”深度学习活体检测模型LivenessNet实际上只是一个简单的卷积神经网络,尽量将这个网络设计的尽可能浅,参数尽可能少,原因有两个:减少过拟合可能性;确保活体检测器能够实时运行;打开livenessnet .py并插入以下代码:# import the necessary packagesfrom keras.models import Sequentialfrom keras.layers.normalization import BatchNormalizationfrom keras.layers.convolutional import Conv2Dfrom keras.layers.convolutional import MaxPooling2Dfrom keras.layers.core import Activationfrom keras.layers.core import Flattenfrom keras.layers.core import Dropoutfrom keras.layers.core import Densefrom keras import backend as Kclass LivenessNet: @staticmethod def build(width, height, depth, classes): # initialize the model along with the input shape to be # “channels last” and the channels dimension itself model = Sequential() inputShape = (height, width, depth) chanDim = -1 # if we are using “channels first”, update the input shape # and channels dimension if K.image_data_format() == “channels_first”: inputShape = (depth, height, width) chanDim = 1 # first CONV => RELU => CONV => RELU => POOL layer set model.add(Conv2D(16, (3, 3), padding=“same”, input_shape=inputShape)) model.add(Activation(“relu”)) model.add(BatchNormalization(axis=chanDim)) model.add(Conv2D(16, (3, 3), padding=“same”)) model.add(Activation(“relu”)) model.add(BatchNormalization(axis=chanDim)) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) # second CONV => RELU => CONV => RELU => POOL layer set model.add(Conv2D(32, (3, 3), padding=“same”)) model.add(Activation(“relu”)) model.add(BatchNormalization(axis=chanDim)) model.add(Conv2D(32, (3, 3), padding=“same”)) model.add(Activation(“relu”)) model.add(BatchNormalization(axis=chanDim)) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) # first (and only) set of FC => RELU layers model.add(Flatten()) model.add(Dense(64)) model.add(Activation(“relu”)) model.add(BatchNormalization()) model.add(Dropout(0.5)) # softmax classifier model.add(Dense(classes)) model.add(Activation(“softmax”)) # return the constructed network architecture return model创建活体检测器训练脚本打开train_liveness .py文件并插入以下代码:# set the matplotlib backend so figures can be saved in the backgroundimport matplotlibmatplotlib.use(“Agg”)# import the necessary packagesfrom pyimagesearch.livenessnet import LivenessNetfrom sklearn.preprocessing import LabelEncoderfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import classification_reportfrom keras.preprocessing.image import ImageDataGeneratorfrom keras.optimizers import Adamfrom keras.utils import np_utilsfrom imutils import pathsimport matplotlib.pyplot as pltimport numpy as npimport argparseimport pickleimport cv2import os# construct the argument parser and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-d", “–dataset”, required=True, help=“path to input dataset”)ap.add_argument("-m", “–model”, type=str, required=True, help=“path to trained model”)ap.add_argument("-l", “–le”, type=str, required=True, help=“path to label encoder”)ap.add_argument("-p", “–plot”, type=str, default=“plot.png”, help=“path to output loss/accuracy plot”)args = vars(ap.parse_args())此脚本接受四个命令行参数:dataset:输入数据集的路径;model:输出模型文件保存路径;le:输出序列化标签编码器文件的路径;plot:训练脚本将生成一个图;下一个代码块将执行初始化并构建数据:# initialize the initial learning rate, batch size, and number of# epochs to train forINIT_LR = 1e-4BS = 8EPOCHS = 50# grab the list of images in our dataset directory, then initialize# the list of data (i.e., images) and class imagesprint("[INFO] loading images…")imagePaths = list(paths.list_images(args[“dataset”]))data = []labels = []for imagePath in imagePaths: # extract the class label from the filename, load the image and # resize it to be a fixed 32x32 pixels, ignoring aspect ratio label = imagePath.split(os.path.sep)[-2] image = cv2.imread(imagePath) image = cv2.resize(image, (32, 32)) # update the data and labels lists, respectively data.append(image) labels.append(label)# convert the data into a NumPy array, then preprocess it by scaling# all pixel intensities to the range [0, 1]data = np.array(data, dtype=“float”) / 255.0之后对标签进行独热编码并对将数据划分为训练数据(75%)和测试数据(25%):# encode the labels (which are currently strings) as integers and then# one-hot encode themle = LabelEncoder()labels = le.fit_transform(labels)labels = np_utils.to_categorical(labels, 2)# partition the data into training and testing splits using 75% of# the data for training and the remaining 25% for testing(trainX, testX, trainY, testY) = train_test_split(data, labels, test_size=0.25, random_state=42)之后对数据进行扩充并对模型进行编译和训练:# construct the training image generator for data augmentationaug = ImageDataGenerator(rotation_range=20, zoom_range=0.15, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.15, horizontal_flip=True, fill_mode=“nearest”)# initialize the optimizer and modelprint("[INFO] compiling model…")opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS)model = LivenessNet.build(width=32, height=32, depth=3, classes=len(le.classes_))model.compile(loss=“binary_crossentropy”, optimizer=opt, metrics=[“accuracy”])# train the networkprint("[INFO] training network for {} epochs…".format(EPOCHS))H = model.fit_generator(aug.flow(trainX, trainY, batch_size=BS), validation_data=(testX, testY), steps_per_epoch=len(trainX) // BS, epochs=EPOCHS)模型训练后,可以评估效果并生成仿真曲线图:# evaluate the networkprint("[INFO] evaluating network…")predictions = model.predict(testX, batch_size=BS)print(classification_report(testY.argmax(axis=1), predictions.argmax(axis=1), target_names=le.classes_))# save the network to diskprint("[INFO] serializing network to ‘{}’…".format(args[“model”]))model.save(args[“model”])# save the label encoder to diskf = open(args[“le”], “wb”)f.write(pickle.dumps(le))f.close()# plot the training loss and accuracyplt.style.use(“ggplot”)plt.figure()plt.plot(np.arange(0, EPOCHS), H.history[“loss”], label=“train_loss”)plt.plot(np.arange(0, EPOCHS), H.history[“val_loss”], label=“val_loss”)plt.plot(np.arange(0, EPOCHS), H.history[“acc”], label=“train_acc”)plt.plot(np.arange(0, EPOCHS), H.history[“val_acc”], label=“val_acc”)plt.title(“Training Loss and Accuracy on Dataset”)plt.xlabel(“Epoch #")plt.ylabel(“Loss/Accuracy”)plt.legend(loc=“lower left”)plt.savefig(args[“plot”])训练活体检测器执行以下命令开始模型训练:$ python train.py –dataset dataset –model liveness.model –le le.pickle[INFO] loading images…[INFO] compiling model…[INFO] training network for 50 epochs…Epoch 1/5029/29 [==============================] - 2s 58ms/step - loss: 1.0113 - acc: 0.5862 - val_loss: 0.4749 - val_acc: 0.7436Epoch 2/5029/29 [==============================] - 1s 21ms/step - loss: 0.9418 - acc: 0.6127 - val_loss: 0.4436 - val_acc: 0.7949Epoch 3/5029/29 [==============================] - 1s 21ms/step - loss: 0.8926 - acc: 0.6472 - val_loss: 0.3837 - val_acc: 0.8077…Epoch 48/5029/29 [==============================] - 1s 21ms/step - loss: 0.2796 - acc: 0.9094 - val_loss: 0.0299 - val_acc: 1.0000Epoch 49/5029/29 [==============================] - 1s 21ms/step - loss: 0.3733 - acc: 0.8792 - val_loss: 0.0346 - val_acc: 0.9872Epoch 50/5029/29 [==============================] - 1s 21ms/step - loss: 0.2660 - acc: 0.9008 - val_loss: 0.0322 - val_acc: 0.9872[INFO] evaluating network… precision recall f1-score support fake 0.97 1.00 0.99 35 real 1.00 0.98 0.99 43 micro avg 0.99 0.99 0.99 78 macro avg 0.99 0.99 0.99 78weighted avg 0.99 0.99 0.99 78[INFO] serializing network to ’liveness.model’…从上述结果来看,在测试集上获得99%的检测精度!合并起来:使用OpenCV进行活体检测最后一步是将所有部分组合在一起:访问网络摄像头/视频流;对每个帧应用面部检测;对于检测到的每个脸部,应用活体检测器模型;打开liveness_demo.py并插入以下代码:# import the necessary packagesfrom imutils.video import VideoStreamfrom keras.preprocessing.image import img_to_arrayfrom keras.models import load_modelimport numpy as npimport argparseimport imutilsimport pickleimport timeimport cv2import os# construct the argument parse and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-m", "--model", type=str, required=True, help="path to trained model")ap.add_argument("-l", "--le", type=str, required=True, help="path to label encoder")ap.add_argument("-d", "--detector", type=str, required=True, help="path to OpenCV's deep learning face detector")ap.add_argument("-c", "--confidence", type=float, default=0.5, help="minimum probability to filter weak detections")args = vars(ap.parse_args())上述代码导入必要的包,并加载模型。下面初始化人脸检测器、LivenessNet模型以及视频流:# load our serialized face detector from diskprint("[INFO] loading face detector...")protoPath = os.path.sep.join([args["detector"], "deploy.prototxt"])modelPath = os.path.sep.join([args["detector"], "res10_300x300_ssd_iter_140000.caffemodel"])net = cv2.dnn.readNetFromCaffe(protoPath, modelPath)# load the liveness detector model and label encoder from diskprint("[INFO] loading liveness detector...")model = load_model(args["model"])le = pickle.loads(open(args["le"], "rb").read())# initialize the video stream and allow the camera sensor to warmupprint("[INFO] starting video stream...")vs = VideoStream(src=0).start()time.sleep(2.0)之后开始循环遍历视频的每一帧以检测面部是否真实:# loop over the frames from the video streamwhile True: # grab the frame from the threaded video stream and resize it # to have a maximum width of 600 pixels frame = vs.read() frame = imutils.resize(frame, width=600) # grab the frame dimensions and convert it to a blob (h, w) = frame.shape[:2] blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0)) # pass the blob through the network and obtain the detections and # predictions net.setInput(blob) detections = net.forward()使用OpenCV blobFromImage函数生成一个面部数据,然后将其传递到面部检测器网络继续进行推理。核心代码如下: # loop over the detections for i in range(0, detections.shape[2]): # extract the confidence (i.e., probability) associated with the # prediction confidence = detections[0, 0, i, 2] # filter out weak detections if confidence &gt; args["confidence"]: # compute the (x, y)-coordinates of the bounding box for # the face and extract the face ROI box = detections[0, 0, i, 3:7] * np.array([w, h, w, h]) (startX, startY, endX, endY) = box.astype("int") # ensure the detected bounding box does fall outside the # dimensions of the frame startX = max(0, startX) startY = max(0, startY) endX = min(w, endX) endY = min(h, endY) # extract the face ROI and then preproces it in the exact # same manner as our training data face = frame[startY:endY, startX:endX] face = cv2.resize(face, (32, 32)) face = face.astype("float") / 255.0 face = img_to_array(face) face = np.expand_dims(face, axis=0) # pass the face ROI through the trained liveness detector # model to determine if the face is "real" or "fake" preds = model.predict(face)[0] j = np.argmax(preds) label = le.classes_[j] # draw the label and bounding box on the frame label = "{}: {:.4f}".format(label, preds[j]) cv2.putText(frame, label, (startX, startY - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2) cv2.rectangle(frame, (startX, startY), (endX, endY), (0, 0, 255), 2)首先过滤掉弱检测结果,然后提取面部图像并对其进行预处理,之后送入到活动检测器模型来确定面部是“真实的”还是“假的/欺骗的”。最后,在原图上绘制标签和添加文本以及矩形框,最后进行展示和清理。 # show the output frame and wait for a key press cv2.imshow("Frame", frame) key = cv2.waitKey(1) &amp; 0xFF # if the q` key was pressed, break from the loop if key == ord(“q”): break# do a bit of cleanupcv2.destroyAllWindows()vs.stop()将活体检测器应用到实时视频上打开终端并执行以下命令:$ python liveness_demo.py –model liveness.model –le le.pickle \ –detector face_detectorUsing TensorFlow backend.[INFO] loading face detector…[INFO] loading liveness detector…[INFO] starting video stream…可以看到,活体检测器成功地区分了真实和伪造的面孔。下面的视频作为一个更长时间的演示:视频地址进一步的工作本文设计的系统还有一些限制和缺陷,主要限制实际上是数据集有限——总共只有311个图像。这项工作的第一个扩展之一是简单地收集额外的训练数据,比如其它人,其它肤色或种族的人。此外,活体检测器只是通过屏幕上的恶搞攻击进行训练,它并没有经过打印出来的图像或照片的训练。因此,建议添加不同类型的图像源。最后,我想提一下,活体检测没有最好的方法,只有最合适的方法。一些好的活体检测器包含多种活体检测方法。总结在本教程中,学习了如何使用OpenCV进行活动检测。使用此活体检测器就可以在自己的人脸识别系统中发现伪造的假脸并进行反面部欺骗。此外,创建活动检测器使用了OpenCV、Deep Learning和Python等领域的知识。整个过程如下:第一步是收集真假数据集。数据来源有:智能手机录制自己的视频(即“真”面);手机录播(即“假”面);对两组视频应用面部检测以形成最终数据集。第二步,获得数据集之后,实现了“LivenessNet”网络,该网络设计的比较浅层,这是为了确保:减少了过拟合小数据集的可能性;该模型本身能够实时运行;总的来说,本文设计的活体检测器能够在验证集上获得99%的准确度。此外,活动检测器也能够应用于实时视频流。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 18, 2019 · 9 min · jiezi

ApacheCN 翻译活动进度公告 2019.3.17

【主页】 apachecn.org【Github】@ApacheCN暂时下线: 社区暂时下线: cwiki 知识库自媒体平台微博:@ApacheCN知乎:@ApacheCNCSDN | 简书 | OSChina | 博客园头条号 | 搜狐号 | bilibili 专栏We are ApacheCN Open Source Organization, not ASF! We are fans of AI, and have no relationship with ASF!合作or侵权,请联系【fonttian】<fonttian@gmail.com> | 请抄送一份到 <apachecn@163.com>seaborn 0.9 中文文档参与方式:https://github.com/apachecn/s…整体进度:https://github.com/apachecn/s…项目仓库:https://github.com/apachecn/s…认领:6/74,翻译:2/74序号章节译者进度1An introduction to seaborn@yiran7324 2Installing and getting started@neolei100%3Visualizing statistical relationships@JNJYan100%4Plotting with categorical data@hold2010 5Visualizing the distribution of a dataset@alohahahaha 6Visualizing linear relationships 7Building structured multi-plot grids@keyianpai 8Controlling figure aesthetics 9Choosing color palettes 10seaborn.relplot 11seaborn.scatterplot 12seaborn.lineplot 13seaborn.catplot 14seaborn.stripplot 15seaborn.swarmplot 16seaborn.boxplot 17seaborn.violinplot 18seaborn.boxenplot 19seaborn.pointplot 20seaborn.barplot 21seaborn.countplot 22seaborn.jointplot 23seaborn.pairplot 24seaborn.distplot 25seaborn.kdeplot 26seaborn.rugplot 27seaborn.lmplot 28seaborn.regplot 29seaborn.residplot 30seaborn.heatmap 31seaborn.clustermap 32seaborn.FacetGrid 33seaborn.FacetGrid.map 34seaborn.FacetGrid.map_dataframe 35seaborn.PairGrid 36seaborn.PairGrid.map 37seaborn.PairGrid.map_diag 38seaborn.PairGrid.map_offdiag 39seaborn.PairGrid.map_lower 40seaborn.PairGrid.map_upper 41seaborn.JointGrid 42seaborn.JointGrid.plot 43seaborn.JointGrid.plot_joint 44seaborn.JointGrid.plot_marginals 45seaborn.set 46seaborn.axes_style 47seaborn.set_style 48seaborn.plotting_context 49seaborn.set_context 50seaborn.set_color_codes 51seaborn.reset_defaults 52seaborn.reset_orig 53seaborn.set_palette 54seaborn.color_palette 55seaborn.husl_palette 56seaborn.hls_palette 57seaborn.cubehelix_palette 58seaborn.dark_palette 59seaborn.light_palette 60seaborn.diverging_palette 61seaborn.blend_palette 62seaborn.xkcd_palette 63seaborn.crayon_palette 64seaborn.mpl_palette 65seaborn.choose_colorbrewer_palette 66seaborn.choose_cubehelix_palette 67seaborn.choose_light_palette 68seaborn.choose_dark_palette 69seaborn.choose_diverging_palette 70seaborn.load_dataset 71seaborn.despine 72seaborn.desaturate 73seaborn.saturate 74seaborn.set_hls_values HBase 3.0 中文参考指南参与方式:https://github.com/apachecn/h…整体进度:https://github.com/apachecn/h…项目仓库:https://github.com/apachecn/h…认领:18/31,翻译:11/31章节译者进度Preface@xixici100%Getting Started@xixici100%Apache HBase Configuration@xixici100%Upgrading@xixici100%The Apache HBase Shell@xixici100%Data Model@Winchester-Yi HBase and Schema Design@RaymondCode100%RegionServer Sizing Rules of Thumb HBase and MapReduce@BridgetLai100%Securing Apache HBase Architecture@RaymondCode In-memory Compaction@mychaow Backup and Restore@mychaow Synchronous Replication@mychaow Apache HBase APIs@xixici100%Apache HBase External APIs@xixici100%Thrift API and Filter Language@xixici100%HBase and Spark@TsingJyujing100%Apache HBase Coprocessors@TsingJyujing Apache HBase Performance Tuning Troubleshooting and Debugging Apache HBase Apache HBase Case Studies Apache HBase Operational Management Building and Developing Apache HBase Unit Testing HBase Applications Protobuf in HBase@TsingJyujing Procedure Framework (Pv2): HBASE-12439 AMv2 Description for Devs ZooKeeper Community Appendix PyTorch 1.0 中文文档参与方式:https://github.com/apachecn/p…整体进度:https://github.com/apachecn/p…项目仓库:https://github.com/apachecn/p…教程部分:认领:37/37,翻译:34/37;文档部分:认领:37/39,翻译:34/39章节贡献者进度教程部分–Deep Learning with PyTorch: A 60 Minute Blitz@bat67100%What is PyTorch?@bat67100%Autograd: Automatic Differentiation@bat67100%Neural Networks@bat67100%Training a Classifier@bat67100%Optional: Data Parallelism@bat67100%Data Loading and Processing Tutorial@yportne13100%Learning PyTorch with Examples@bat67100%Transfer Learning Tutorial@jiangzhonglian100%Deploying a Seq2Seq Model with the Hybrid Frontend@cangyunye100%Saving and Loading Models@bruce1408100%What is torch.nn really?@lhc741100%Finetuning Torchvision Models@ZHHAYO100%Spatial Transformer Networks Tutorial@PEGASUS1993100%Neural Transfer Using PyTorch@bdqfork100%Adversarial Example Generation@cangyunye100%Transfering a Model from PyTorch to Caffe2 and Mobile using ONNX@PEGASUS1993100%Chatbot Tutorial@a625687551100%Generating Names with a Character-Level RNN@hhxx2015100%Classifying Names with a Character-Level RNN@hhxx2015100%Deep Learning for NLP with Pytorch@bruce1408100%Introduction to PyTorch@guobaoyo100%Deep Learning with PyTorch@bdqfork100%Word Embeddings: Encoding Lexical Semantics@sight007100%Sequence Models and Long-Short Term Memory Networks@ETCartman100%Advanced: Making Dynamic Decisions and the Bi-LSTM CRF@JohnJiangLA Translation with a Sequence to Sequence Network and Attention@mengfu188100%DCGAN Tutorial@wangshuai9517100%Reinforcement Learning (DQN) Tutorial@friedhelm739100%Creating Extensions Using numpy and scipy@cangyunye100%Custom C++ and CUDA Extensions@Lotayou Extending TorchScript with Custom C++ Operators@cloudyyyyy Writing Distributed Applications with PyTorch@firdameng100%PyTorch 1.0 Distributed Trainer with Amazon AWS@yportne13100%ONNX Live Tutorial@PEGASUS1993100%Loading a PyTorch Model in C++@talengu100%Using the PyTorch C++ Frontend@solerji100%文档部分–Autograd mechanics@PEGASUS1993100%Broadcasting semantics@PEGASUS1993100%CUDA semantics@jiangzhonglian100%Extending PyTorch@PEGASUS1993100%Frequently Asked Questions@PEGASUS1993100%Multiprocessing best practices@cvley100%Reproducibility@WyattHuang1 Serialization semantics@yuange250100%Windows FAQ@PEGASUS1993100%torch torch.Tensor@hijkzzz100%Tensor Attributes@yuange250100%Type Info@PEGASUS1993100%torch.sparse@hijkzzz100%torch.cuda@bdqfork100%torch.Storage@yuange250100%torch.nn@yuange250 torch.nn.functional@hijkzzz100%torch.nn.init@GeneZC100%torch.optim@qiaokuoyuan Automatic differentiation package - torch.autograd@gfjiangly100%Distributed communication package - torch.distributed@univeryinli100%Probability distributions - torch.distributions@hijkzzz100%Torch Script@keyianpai100%Multiprocessing package - torch.multiprocessing@hijkzzz100%torch.utils.bottleneck@belonHan100%torch.utils.checkpoint@belonHan100%torch.utils.cpp_extension@belonHan100%torch.utils.data@BXuan694100%torch.utils.dlpack@kunwuz100%torch.hub@kunwuz100%torch.utils.model_zoo@BXuan694100%torch.onnx@guobaoyo100%Distributed communication package (deprecated) - torch.distributed.deprecated torchvision Reference@BXuan694100%torchvision.datasets@BXuan694100%torchvision.models@BXuan694100%torchvision.transforms@BXuan694100%torchvision.utils@BXuan694100%AirFlow 中文文档参与方式:https://github.com/apachecn/a…整体进度:https://github.com/apachecn/a…项目仓库:https://github.com/apachecn/a…认领:25/30,翻译:24/30章节贡献者进度1 项目@zhongjiajie100%2 协议-100%3 快速开始@ImPerat0R_100%4 安装@Thinking Chen100%5 教程@ImPerat0R_100%6 操作指南@ImPerat0R_100%7 设置配置选项@ImPerat0R_100%8 初始化数据库后端@ImPerat0R_100%9 使用操作器@ImPerat0R_100%10 管理连接@ImPerat0R_100%11 保护连接@ImPerat0R_100%12 写日志@ImPerat0R_100%13 使用Celery扩大规模@ImPerat0R_100%14 使用Dask扩展@ImPerat0R_100%15 使用Mesos扩展(社区贡献)@ImPerat0R_100%16 使用systemd运行Airflow@ImPerat0R_100%17 使用upstart运行Airflow@ImPerat0R_100%18 使用测试模式配置@ImPerat0R_100%19 UI /截图@ImPerat0R_100%20 概念@ImPerat0R_100%21 数据分析@ImPerat0R_100%22 命令行接口@ImPerat0R_100%23 调度和触发器@Ray100%24 插件@ImPerat0R_100%25 安全 26 时区 27 实验性 Rest API@ImPerat0R_100%28 集成 29 Lineage 30 常见问题@zhongjiajie 31 API 参考 UCB CS61b:Java 中的数据结构参与方式:https://github.com/apachecn/c…整体进度:https://github.com/apachecn/c…项目仓库:https://github.com/apachecn/c…认领:5/12,翻译:1/12标题译者进度一、算法复杂度@leader402二、抽象数据类型@Allenyep100%三、满足规范 四、序列和它们的实现@biubiubiuboomboomboom五、树@biubiubiuboomboomboom六、搜索树 七、哈希 八、排序和选择@Rachel-Hu九、平衡搜索 十、并发和同步 十一、伪随机序列 十二、图 UCB Prob140:面向数据科学的概率论参与方式:https://github.com/apachecn/p…整体进度:https://github.com/apachecn/p…项目仓库:https://github.com/apachecn/p…认领:21/25,翻译:19/25标题译者翻译进度一、基础飞龙100%二、计算几率飞龙100%三、随机变量飞龙100%四、事件之间的关系@biubiubiuboomboomboom100%五、事件集合 >0%六、随机计数@viviwong100%七、泊松化@YAOYI626100%八、期望 50%九、条件(续)@YAOYI626100%十、马尔科夫链喵十八100%十一、马尔科夫链(续)喵十八100%十二、标准差缺只萨摩 100%十三、方差和协方差缺只萨摩 100%十四、中心极限定理喵十八100%十五、连续分布@ThunderboltSmile十六、变换十七、联合密度@Winchester-Yi100%十八、正态和 Gamma 族@Winchester-Yi100%十九、和的分布平淡的天100%二十、估计方法平淡的天100%二十一、Beta 和二项@lvzhetx100%二十二、预测 50%二十三、联合正态随机变量@JUNE951234二十四、简单线性回归@ThomasCai100%二十五、多元回归@lanhaixuan100%OpenCV 4.0 中文文档参与方式:https://github.com/apachecn/o…整体进度:https://github.com/apachecn/o…项目仓库:https://github.com/apachecn/o…认领:51/51,翻译:19/51。章节贡献者进度1. 简介@wstone00111.1 OpenCV-Python教程简介-100%1.2 安装OpenCV—Python-100%2. GUI功能@ranxx2.1 图像入门-100%2.2 视频入门-100%2.3 绘图功能-100%2.4 鼠标作为画笔-100%2.5 作为调色板的跟踪栏-100%3. 核心操作@luxinfeng3.1 图像基本操作-100%3.2 图像的算术运算-100%3.3 性能测量和改进技术-100%4. 图像处理@friedhelm7394.1 更改颜色空间-100%4.2 图像的几何变换-100%4.3 图像阈值-100%4.4 平滑图像-4.5 形态转换-4.6 图像梯度-4.7 Canny边缘检测-4.8 影像金字塔-4.9 轮廓-4.10 直方图-4.11 图像转换-4.12 模板匹配-4.13 霍夫线变换-4.14 霍夫圆变换-4.15 基于分水岭算法的图像分割-基于GrabCut算法的交互式前景提取-5. 特征检测和描述@3lackrush5.1 了解功能-100%5.2 Harris角点检测-5.3 Shi-Tomasi角点检测和追踪的良好特征-5.4 SIFT简介(尺度不变特征变换)-5.5 SURF简介(加速鲁棒特性)-5.6 角点检测的FAST算法-5.7 简介(二进制鲁棒独立基本特征)-5.8 ORB(定向快速和快速旋转)-5.9 特征匹配-5.10 特征匹配+ Homography查找对象-6. 视频分析@xmmmmmovo6.1 Meanshift和Camshift-100%6.2 光流-100%6.3 背景减法-100%7. 相机校准和3D重建@xmmmmmovo 7.1 相机校准-7.2 姿势估计-7.3 极线几何-7.4 立体图像的深度图-8. 机器学习@wstone00118.1 K-最近邻-8.2 支持向量机(SVM)-8.3 K-Means聚类-9. 计算摄影@ranxx9.1 图像去噪-9.2 图像修复-9.3 高动态范围(HDR)-10. 目标检测@jiangzhonglian 10.1 使用Haar Cascades进行人脸检测-100%11. OpenCV-Python绑定@daidai21 11.1 OpenCV-Python绑定如何工作?-100%翻译征集要求:机器学习/数据科学相关或者编程相关原文必须在互联网上开放不能只提供 PDF 格式(我们实在不想把精力都花在排版上)请先搜索有没有人翻译过请回复本文。赞助我们 ...

March 17, 2019 · 3 min · jiezi

ApacheCN 翻译活动进度公告 2019.3.10

【主页】 apachecn.org【Github】@ApacheCN暂时下线: 社区暂时下线: cwiki 知识库自媒体平台微博:@ApacheCN知乎:@ApacheCNCSDN简书OSChina博客园We are ApacheCN Open Source Organization, not ASF! We are fans of AI, and have no relationship with ASF!合作or侵权,请联系【fonttian】fonttian@gmail.com | 请抄送一份到 apachecn@163.comPyTorch 1.0 中文文档参与方式:https://github.com/apachecn/p…整体进度:https://github.com/apachecn/p…项目仓库:https://github.com/apachecn/p…教程部分:认领:37/37,翻译:32/37;文档部分:认领:37/39,翻译:34/39章节贡献者进度教程部分–Deep Learning with PyTorch: A 60 Minute Blitz@bat67100%What is PyTorch?@bat67100%Autograd: Automatic Differentiation@bat67100%Neural Networks@bat67100%Training a Classifier@bat67100%Optional: Data Parallelism@bat67100%Data Loading and Processing Tutorial@yportne13100%Learning PyTorch with Examples@bat67100%Transfer Learning Tutorial@jiangzhonglian100%Deploying a Seq2Seq Model with the Hybrid Frontend@cangyunye100%Saving and Loading Models@bruce1408 What is torch.nn really?@lhc741100%Finetuning Torchvision Models@ZHHAYO100%Spatial Transformer Networks Tutorial@PEGASUS1993100%Neural Transfer Using PyTorch@bdqfork100%Adversarial Example Generation@cangyunye100%Transfering a Model from PyTorch to Caffe2 and Mobile using ONNX@PEGASUS1993100%Chatbot Tutorial@a625687551100%Generating Names with a Character-Level RNN@hhxx2015100%Classifying Names with a Character-Level RNN@hhxx2015100%Deep Learning for NLP with Pytorch@bruce1408 Introduction to PyTorch@guobaoyo100%Deep Learning with PyTorch@bdqfork100%Word Embeddings: Encoding Lexical Semantics@sight007100%Sequence Models and Long-Short Term Memory Networks@ETCartman100%Advanced: Making Dynamic Decisions and the Bi-LSTM CRF@JohnJiangLA Translation with a Sequence to Sequence Network and Attention@mengfu188100%DCGAN Tutorial@wangshuai9517100%Reinforcement Learning (DQN) Tutorial@friedhelm739100%Creating Extensions Using numpy and scipy@cangyunye100%Custom C++ and CUDA Extensions@Lotayou Extending TorchScript with Custom C++ Operators@cloudyyyyy Writing Distributed Applications with PyTorch@firdameng100%PyTorch 1.0 Distributed Trainer with Amazon AWS@yportne13100%ONNX Live Tutorial@PEGASUS1993100%Loading a PyTorch Model in C++@talengu100%Using the PyTorch C++ Frontend@solerji100%文档部分–Autograd mechanics@PEGASUS1993100%Broadcasting semantics@PEGASUS1993100%CUDA semantics@jiangzhonglian100%Extending PyTorch@PEGASUS1993100%Frequently Asked Questions@PEGASUS1993100%Multiprocessing best practices@cvley100%Reproducibility@WyattHuang1 Serialization semantics@yuange250100%Windows FAQ@PEGASUS1993100%torch torch.Tensor@hijkzzz100%Tensor Attributes@yuange250100%Type Info@PEGASUS1993100%torch.sparse@hijkzzz100%torch.cuda@bdqfork100%torch.Storage@yuange250100%torch.nn@yuange250 torch.nn.functional@hijkzzz100%torch.nn.init@GeneZC100%torch.optim@qiaokuoyuan Automatic differentiation package - torch.autograd@gfjiangly100%Distributed communication package - torch.distributed@univeryinli100%Probability distributions - torch.distributions@hijkzzz100%Torch Script@keyianpai100%Multiprocessing package - torch.multiprocessing@hijkzzz100%torch.utils.bottleneck@belonHan100%torch.utils.checkpoint@belonHan100%torch.utils.cpp_extension@belonHan100%torch.utils.data@BXuan694100%torch.utils.dlpack@kunwuz100%torch.hub@kunwuz100%torch.utils.model_zoo@BXuan694100%torch.onnx@guobaoyo100%Distributed communication package (deprecated) - torch.distributed.deprecated torchvision Reference@BXuan694100%torchvision.datasets@BXuan694100%torchvision.models@BXuan694100%torchvision.transforms@BXuan694100%torchvision.utils@BXuan694100%HBase 3.0 中文参考指南参与方式:https://github.com/apachecn/h…整体进度:https://github.com/apachecn/h…项目仓库:https://github.com/apachecn/h…认领:13/31,翻译:9/31章节译者进度Preface@xixici100%Getting Started@xixici100%Apache HBase Configuration@xixici100%Upgrading@xixici100%The Apache HBase Shell@xixici100%Data Model@Winchester-Yi HBase and Schema Design@RaymondCode100%RegionServer Sizing Rules of Thumb HBase and MapReduce@BridgetLai Securing Apache HBase Architecture@RaymondCode In-memory Compaction Backup and Restore Synchronous Replication Apache HBase APIs@xixici100%Apache HBase External APIs@xixici100%Thrift API and Filter Language@xixici100%HBase and Spark@TsingJyujing Apache HBase Coprocessors Apache HBase Performance Tuning Troubleshooting and Debugging Apache HBase Apache HBase Case Studies Apache HBase Operational Management Building and Developing Apache HBase Unit Testing HBase Applications Protobuf in HBase Procedure Framework (Pv2): HBASE-12439 AMv2 Description for Devs ZooKeeper Community Appendix AirFlow 中文文档参与方式:https://github.com/apachecn/a…整体进度:https://github.com/apachecn/a…项目仓库:https://github.com/apachecn/a…认领:25/30,翻译:24/30。章节贡献者进度1 项目@zhongjiajie100%2 协议-100%3 快速开始@ImPerat0R_100%4 安装@Thinking Chen100%5 教程@ImPerat0R_100%6 操作指南@ImPerat0R_100%7 设置配置选项@ImPerat0R_100%8 初始化数据库后端@ImPerat0R_100%9 使用操作器@ImPerat0R_100%10 管理连接@ImPerat0R_100%11 保护连接@ImPerat0R_100%12 写日志@ImPerat0R_100%13 使用Celery扩大规模@ImPerat0R_100%14 使用Dask扩展@ImPerat0R_100%15 使用Mesos扩展(社区贡献)@ImPerat0R_100%16 使用systemd运行Airflow@ImPerat0R_100%17 使用upstart运行Airflow@ImPerat0R_100%18 使用测试模式配置@ImPerat0R_100%19 UI /截图@ImPerat0R_100%20 概念@ImPerat0R_100%21 数据分析@ImPerat0R_100%22 命令行接口@ImPerat0R_100%23 调度和触发器@Ray100%24 插件@ImPerat0R_100%25 安全 26 时区 27 实验性 Rest API@ImPerat0R_100%28 集成 29 Lineage 30 常见问题@zhongjiajie 31 API 参考 OpenCV 4.0 中文文档参与方式:https://github.com/apachecn/o…整体进度:https://github.com/apachecn/o…项目仓库:https://github.com/apachecn/o…认领:47/51,翻译:17/51。章节贡献者进度1. 简介@wstone00111.1 OpenCV-Python教程简介-100%1.2 安装OpenCV—Python-2. GUI功能@ranxx2.1 图像入门-100%2.2 视频入门-100%2.3 绘图功能-100%2.4 鼠标作为画笔-100%2.5 作为调色板的跟踪栏-100%3. 核心操作@luxinfeng3.1 图像基本操作-100%3.2 图像的算术运算-100%3.3 性能测量和改进技术-100%4. 图像处理@friedhelm7394.1 更改颜色空间-100%4.2 图像的几何变换-100%4.3 图像阈值-4.4 平滑图像-4.5 形态转换-4.6 图像梯度-4.7 Canny边缘检测-4.8 影像金字塔-4.9 轮廓-4.10 直方图-4.11 图像转换-4.12 模板匹配-4.13 霍夫线变换-4.14 霍夫圆变换-4.15 基于分水岭算法的图像分割-基于GrabCut算法的交互式前景提取-5. 特征检测和描述@3lackrush5.1 了解功能-100%5.2 Harris角点检测-5.3 Shi-Tomasi角点检测和追踪的良好特征-5.4 SIFT简介(尺度不变特征变换)-5.5 SURF简介(加速鲁棒特性)-5.6 角点检测的FAST算法-5.7 简介(二进制鲁棒独立基本特征)-5.8 ORB(定向快速和快速旋转)-5.9 特征匹配-5.10 特征匹配+ Homography查找对象-6. 视频分析@xmmmmmovo6.1 Meanshift和Camshift-100%6.2 光流-100%6.3 背景减法-100%7. 相机校准和3D重建 7.1 相机校准 7.2 姿势估计 7.3 极线几何 7.4 立体图像的深度图 8. 机器学习@wstone00118.1 K-最近邻-8.2 支持向量机(SVM)-8.3 K-Means聚类-9. 计算摄影@ranxx9.1 图像去噪-9.2 图像修复-9.3 高动态范围(HDR)-10. 目标检测@jiangzhonglian 10.1 使用Haar Cascades进行人脸检测-100%11. OpenCV-Python绑定@daidai21 11.1 OpenCV-Python绑定如何工作?-100%UCB CS61b:Java 中的数据结构参与方式:https://github.com/apachecn/c…整体进度:https://github.com/apachecn/c…项目仓库:https://github.com/apachecn/c…认领:2/12,翻译:1/12。标题译者进度一、算法复杂度@leader402二、抽象数据类型@Allenyep100%三、满足规范 四、序列和它们的实现 五、树 六、搜索树 七、哈希 八、排序和选择 九、平衡搜索 十、并发和同步 十一、伪随机序列 十二、图 UCB Prob140:面向数据科学的概率论参与方式:https://github.com/apachecn/p…整体进度:https://github.com/apachecn/p…项目仓库:https://github.com/apachecn/p…认领:23/25,翻译:19/25。标题译者翻译进度一、基础飞龙100%二、计算几率飞龙100%三、随机变量飞龙100%四、事件之间的关系@biubiubiuboomboomboom100%五、事件集合@PEGASUS1993>0%六、随机计数@viviwong100%七、泊松化@YAOYI626100%八、期望@PEGASUS199350%九、条件(续)@YAOYI626100%十、马尔科夫链喵十八100%十一、马尔科夫链(续)喵十八100%十二、标准差缺只萨摩 100%十三、方差和协方差缺只萨摩 100%十四、中心极限定理喵十八100%十五、连续分布@ThunderboltSmile十六、变换十七、联合密度@Winchester-Yi100%十八、正态和 Gamma 族@Winchester-Yi100%十九、和的分布平淡的天100%二十、估计方法平淡的天100%二十一、Beta 和二项@lvzhetx100%二十二、预测 50%二十三、联合正态随机变量@JUNE951234二十四、简单线性回归@ThomasCai100%二十五、多元回归@lanhaixuan100%翻译征集要求:机器学习/数据科学相关或者编程相关原文必须在互联网上开放不能只提供 PDF 格式(我们实在不想把精力都花在排版上)请先搜索有没有人翻译过请回复本文。赞助我们 ...

March 10, 2019 · 3 min · jiezi

使用Opencv构建一个简单的图像相似检测器(MSE、SSIM)

摘要: 本文使用opencv。numpy等简单的工具库,根据mse及ssim两种算法来评估两张图像的相似度,便于理解与实践。介绍作为人类,我们通常非常善于发现图像中的差异。例如,常见的游戏——两张图像找不同。现在让我们玩下这个游戏吧,首先让我们看看上面的图像,三十秒内看看是否能够从中找出有什么不同的地方。答案:水果、冰淇淋和饮料的颜色发生了明显改变,窗帘、太阳也发生了改变,这是不是很简单呢?如果有补充的答案,请在留言处给出哦!这类问题对于人类来说看起来是一件轻而易举的事情,但是,对于计算机来说,这可不是一件容易的事儿。这是由于计算机只能从我们训练它的模型中学习,才最终具有这类能力。目前有很多很好的模型可以对批量图像进行分类,比如TensorFlow和Keras等开源工具。借助于这类开源工具库,计算机视觉领域的研究得以高发展。现在我们也可以借助于这类工具箱创建非常复杂的模型以及解决比较复杂的问题,例如kaggle:Animals-10,该数据集包含数十种不同类型动物的图像以及非动物图像。所要做的就是创建一个模型来预测图片是哪种类型的动物。MSE和SSIM然而,上述任务较为简单,比如常见的手写体数字识别MNIST等,一般也都能取得很高的精度。在这里,我想增加一点难度,创建一个图像分类器,以分辨出两个图像的相似程度。并且,不依赖任何复杂的工具库,如TensorFlow、Keras等。本文采用传统的机器学习方法,这里从中选取两种方法,用于查找图像是否与另一个图像相似。这两种方法分别为均方误差(MSE)、结构相似度指数(SSIM)。上述公式看起来非常复杂,但不要害怕。借助于NumPy,可以相当容易地计算出MSE;另外,由于SSIM是Sci-Kit图像库的内置方法的一部分,因此也可以很容易地计算出SSIM。在进行编码之前,这里先对这两种方法予以简单的说明。MSE将计算正在比较的两个图像的每个像素之间的均方误差。而SSIM做的事情与MSE恰好相反,寻找像素值的相似之处。 也就是,如果两个图像中的像素排列相似或具有相似的像素密度值。MSE方法遇到的一个的问题是其结果往往具有任意大的值,因此很难给出标准的评判标准。一般而言,MSE越高,表明两张图像的相似程度越低。如果图像之间的MSE值是随机值,则很难说明二者是否相似。另一方面,SSIM将所有内容归一化到-1~1的范围内(很难得到小于0的分数)。得分为1表示二者非常相似,得分为-1表示二者非常不同。基于此,SSIM相较于MSE而言是一个更好的衡量指标。实现现在使用代码实现上述想法:加载必要的库:本文使用常见的图像处理工具箱OpenCV实现图像的读取和编辑。如果你对其它图像处理工具箱熟悉,你也可以使用自己熟悉的工具箱完成此类操作,比如matplotlibden。编写MSE公式:使用Numpy操作起来很简单吧!由于SSIM已经通过skimage导入,因此无需进行手动编码。现在创建一个比较函数,该函数的输入为两个图像,分别计算二者的MSE和SSIM,并展示计算结果。下面的三个步骤可以使用for循环一次完成,但是为了更容易地理解,这里不使用for循环编写代码,将其分解为三个部分:首先,加载保存在目录中的图像。其次,必须确保它们的大小相同,否则会出现尺寸不匹配的错误。问题是对其进行尺寸变换操作会导致图像失真,所以在找到比较合适的尺寸数字之前,可以尝试快速搜索方法,尺寸大小按照一定的规律设置,不断实验以找到最终比较合适的尺寸。接下来我们再实现一个功能,以便于看到测试图像是什么样子的。现在通过比较两个一样的图像来测试并查看MSE和SSIM是否正常工作。如果它有效,那么我们应该得到MSE值为0和SSIM值为1的结果。从中可以看到,代码正确,结果与猜想的一致!现在计算机就可以判断比较的两张图像是否相同了。为简单起见,我将三张狗的图像与自己以及三张猫的图像进行比较。下面看看两种算法的性能比较。正如所看到的那样,MSE的值变化很大,因此该值很难说明其表达的意思是什么。但从SSIM的结果看出,可以看到狗2和狗3相对于其他狗的图像最为相似。从视觉上来讲,我同意这个结果,因为两只狗的耳朵非常像。但我还会认为狗1和狗3会有更高的SSIM值,因为二者的姿势也很相似。实际上,在图像没有进行灰度处理之前,狗2和狗3在鼻子区域周围有类似的白色毛皮,而狗1没有。这很可能是狗2和3具有比狗1更高的SSIM值的原因。对于猫来说,这就有点困难。猫1和猫2具有相似的形状,并且图像是从相似的距离拍摄的,但猫2和猫3具有相似的皮毛颜色。这里我想进行的测试只有两个:一个是狗和猫的相似性,第二个是每个动物与原始源代码附带的门图的相似性。正如所预料的那样,狗和猫是相似的,这点与与无生命的物体相比呈鲜明的对比,如侏罗纪公园入口门。狗和猫对门的图像具有较高的SSIM值,唯一原因在于图像都经过了尺寸缩放和灰度处理。在调整图像大小和重新配置时,OpenCV并不是最好的。一般而言,TensorFlow是最好的,TensorFlow也最适合批量图像。之后,我也将使用TensorFlow处理kaggle Animal-10数据集,来实现一个完整的图像分类器。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

January 22, 2019 · 1 min · jiezi

一文带你学会使用YOLO及Opencv完成图像及视频流目标检测(上)|附源码

摘要: 本文介绍使用opencv和yolo完成图像目标检测,代码解释详细,附源码,上手快。计算机视觉领域中,目标检测一直是工业应用上比较热门且成熟的应用领域,比如人脸识别、行人检测等,国内的旷视科技、商汤科技等公司在该领域占据行业领先地位。相对于图像分类任务而言,目标检测会更加复杂一些,不仅需要知道这是哪一类图像,而且要知道图像中所包含的内容有什么及其在图像中的位置,因此,其工业应用比较广泛。那么,今天将向读者介绍该领域中表现优异的一种算算法——“你只需要看一次”(you only look once,yolo),提出该算法的作者风趣幽默可爱,其个人主页及论文风格显示了其性情,目前该算法已是第三个版本,简称YoLo V3。闲话少叙,下面进入教程的主要内容。在本教程中,将学习如何使用YOLO、OpenCV和Python检测图像和视频流中的对象。主要内容有:简要讨论YOLO算法;使用YOLO、OpenCV、Python进行图像检测;使用YOLO、OpenCV、Python进行视频流检测;讨论YOLO算法的优点和缺点;什么是YOLO?当涉及基于深度学习的对象检测时,常用的三类算法有:R-CNN家族系列算法:R-CNN、fast R-CNN以及faster R-CNN;单发检测器(SSD);YOLO算法;R-CNN算法是最早的基于深度学习的目标检测器之一,其结构是两级网络:首先需要诸如选择性搜索之类的算法来提出可能包含对象的候选边界框;然后将这些区域传递到CNN算法进行分类;R-CNN算法存在的问题在于其仿真很慢,并且不是完整的端到端的目标检测器。Fast R-CNN算法对原始R-CNN进行了相当大的改进,即提高准确度并减少执行正向传递所花费的时间,但是,该模型仍然依赖于外部区域搜索算法。直到2015年,faster R-CNN才成为真正的端到端深度学习目标检测器,删除了选择性搜索的要求,而是依赖于(1)完全卷积的区域提议网络(RPN)和(2)可以预测对象边界框和“对象”分数(量化它是一个区域的可能性的分数)。然后将RPN的输出传递到R-CNN组件以进行最终分类和标记。R-CNN系列算法的检测结果一般都非常准确,但R-CNN系列算法最大的问题在仿真速度——非常慢,即使是在GPU上也仅获得5 FPS。为了提高基于深度学习的目标检测器的速度,单次检测器(SSD)和YOLO都使用单级检测器策略(one stage)。这类算法将对象检测视为回归问题,获取给定的输入图像并同时学习边界框坐标和相应的类标签概率。通常,单级检测器往往不如两级检测器准确,但其速度明显更快。YOLO是单级检测器中一个很好的算法。YOLO算法于2015年提出,在GPU上获得了 45 FPS性能,此外,同时也提出了一个较小的变体称为“Fast YOLO”,在GPU上达到155 FPS的性能。YOLO经历了许多次的迭代,包括YOLOv2,能够检测超过9,000个目标。直到最近提出的YOLOv3算法,YOLOv3模型比之前的版本要复杂得多,但它是YOLO系列目标检测器中最好的一款。本文使用YOLOv3,并在COCO数据集上进行训练。COCO数据集由80个标签组成,可以使用此链接找到YOLO在COCO数据集上训练的内容的完整列表。项目结构在终端中使用tree命令,可以很方便快捷地生成目标树:$ tree.├── images│ ├── baggage_claim.jpg│ ├── dining_table.jpg│ ├── living_room.jpg│ └── soccer.jpg├── output│ ├── airport_output.avi│ ├── car_chase_01_output.avi│ ├── car_chase_02_output.avi│ └── overpass_output.avi├── videos│ ├── airport.mp4│ ├── car_chase_01.mp4│ ├── car_chase_02.mp4│ └── overpass.mp4├── yolo-coco│ ├── coco.names│ ├── yolov3.cfg│ └── yolov3.weights├── yolo.py└── yolo_video.py从上面可以看出,项目包括4个文件夹和2个Python脚本。目录(按重要性顺序)是:yolo - coco / :YOLOv3对象检测器预先(在COCO数据集上)训练得到最终的权重文件,可以在Darknet团队主页找到对应的文件;images / :此文件夹包含四个静态图像,之后将执行对象检测以进行测试和评估;videos/ :使用YOLO对图像进行目标检测器后,将实时处理视频。该文件夹中包含四个示例视频可供测试;输出/ :输出已由YOLO处理并带有边界框和类名称注释的视频可以放在此文件夹中;此外还有两个Python脚本——yolo .py和 yolo_video.py ,第一个脚本用于图像处理,第二个脚本用于视频处理。下面进入实战内容,你准备好了吗?将YOLO应用于图像对象检测首先将YOLO目标检测器应用于图像中,首先打开项目中的 yolo .py并插入以下代码:# import the necessary packagesimport numpy as npimport argparseimport timeimport cv2import os# construct the argument parse and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-i", “–image”, required=True, help=“path to input image”)ap.add_argument("-y", “–yolo”, required=True, help=“base path to YOLO directory”)ap.add_argument("-c", “–confidence”, type=float, default=0.5, help=“minimum probability to filter weak detections”)ap.add_argument("-t", “–threshold”, type=float, default=0.3, help=“threshold when applying non-maxima suppression”)args = vars(ap.parse_args())在使用之前,需要为此脚本安装 3.4.2+版本以上的OpenCV,可以直接使用pip install opencv-python==3.4.2安装,你也可以在这里找到OpenCV安装教程,这里注意一点,OpenCV 4目前处于测试阶段,这里建议去安装OpenCV 3.4.2+。首先,导入所需的数据包——OpenCV和NumPy。现在解析四个命令行参数,命令行参数在运行时处理,允许我们从终端更改脚本的输入。如果你对其不熟悉,建议阅读相关的内容。命令行参数包括:– image :输入图像的路径;– yolo :YOLO文件路径,脚本将加载所需的YOLO文件,以便在图像上执行对象检测;– confidence :过滤弱检测的最小概率,默认值设置为0.5,但该值也可以随意设置;– threshold :非最大值抑制阈值,默认值设置为 0.3,可以在此处阅读有关非最大值抑制的更多信息。解析之后,args变量是一个包含命令行参数的键值对的字典。下面为每个标签设置随机颜色:# load the COCO class labels our YOLO model was trained onlabelsPath = os.path.sep.join([args[“yolo”], “coco.names”])LABELS = open(labelsPath).read().strip().split("\n")# initialize a list of colors to represent each possible class labelnp.random.seed(42)COLORS = np.random.randint(0, 255, size=(len(LABELS), 3), dtype=“uint8”)上述加载所有类 LABELS,其类型是列表,保存的是类别名称,然后将随机颜色分配给每个标签 。下面设置YOLO权重和配置文件的路径,然后从磁盘加载YOLO文件:# derive the paths to the YOLO weights and model configurationweightsPath = os.path.sep.join([args[“yolo”], “yolov3.weights”])configPath = os.path.sep.join([args[“yolo”], “yolov3.cfg”])# load our YOLO object detector trained on COCO dataset (80 classes)print("[INFO] loading YOLO from disk…")net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)从磁盘加载YOLO文件后,并利用OpenCV中的cv2.dnn.readNetFromDarknet函数从中读取网络文件及权重参数,此函数需要两个参数configPath 和 weightsPath,这里再次强调,:OpenCV 的版本至少是3.4.2及以上才能运行此代码,因为它需要加载YOLO所需的更新的 dnn模块。下面加载图像并处理:# load our input image and grab its spatial dimensionsimage = cv2.imread(args[“image”])(H, W) = image.shape[:2]# determine only the output layer names that we need from YOLOln = net.getLayerNames()ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]# construct a blob from the input image and then perform a forward# pass of the YOLO object detector, giving us our bounding boxes and# associated probabilitiesblob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416), swapRB=True, crop=False)net.setInput(blob)start = time.time()layerOutputs = net.forward(ln)end = time.time()# show timing information on YOLOprint("[INFO] YOLO took {:.6f} seconds".format(end - start))在该代码中:加载输入 图像并获得其尺寸;确定YOLO模型中的输出图层名称;从图像构造一个 blob结构;如果你对blob和cv2.dnn.blobFromImage有疑问,可以看这篇博客进一步的了解。当blob准备好了后,我们就会通过YOLO网络进行前向传递;显示YOLO的推理时间;现在采取措施来过滤和可视化最终的结果。首先,让我们初步化一些处理过程中需要的列表:# initialize our lists of detected bounding boxes, confidences, and# class IDs, respectivelyboxes = []confidences = []classIDs = []这些列表包括:boxes :对象的边界框。confidences :YOLO分配给对象的置信度值,较低的置信度值表示该对象可能不是网络认为的对象。上面的命令行参数中将过滤掉不大于 0.5阈值的对象。classIDs :检测到的对象的类标签。下面用YOLO layerOutputs中的数据填充这些列表 :# loop over each of the layer outputsfor output in layerOutputs: # loop over each of the detections for detection in output: # extract the class ID and confidence (i.e., probability) of # the current object detection scores = detection[5:] classID = np.argmax(scores) confidence = scores[classID] # filter out weak predictions by ensuring the detected # probability is greater than the minimum probability if confidence > args[“confidence”]: # scale the bounding box coordinates back relative to the # size of the image, keeping in mind that YOLO actually # returns the center (x, y)-coordinates of the bounding # box followed by the boxes’ width and height box = detection[0:4] * np.array([W, H, W, H]) (centerX, centerY, width, height) = box.astype(“int”) # use the center (x, y)-coordinates to derive the top and # and left corner of the bounding box x = int(centerX - (width / 2)) y = int(centerY - (height / 2)) # update our list of bounding box coordinates, confidences, # and class IDs boxes.append([x, y, int(width), int(height)]) confidences.append(float(confidence)) classIDs.append(classID)在这个块中:循环遍历每个 layerOutputs;循环每个detection中 output;提取 classID和 confidence;使用 confidence滤除弱检测;过滤掉了不需要的检测结果后,我们将:缩放边界框坐标,以便我们可以在原始图像上正确显示它们;提取边界框的坐标和尺寸,YOLO返回边界框坐标形式: (centerX ,centerY ,width,height);使用此信息导出边界框的左上角(x,y)坐标;更新boxes, confidences ,classIDs列表。有了这些数据后,将应用“非最大值抑制”(non-maxima suppression,nms):# apply non-maxima suppression to suppress weak, overlapping bounding# boxesidxs = cv2.dnn.NMSBoxes(boxes, confidences, args[“confidence”], args[“threshold”])YOLO算法并没有应用非最大值抑制,这里需要说明一下。应用非最大值抑制可以抑制明显重叠的边界框,只保留最自信的边界框,NMS还确保我们没有任何冗余或无关的边界框。利用OpenCV内置的NMS DNN模块实现即可实现非最大值抑制 ,所需要的参数是边界 框、 置信度、以及置信度阈值和NMS阈值。最后在图像上绘制检测框和类文本:# ensure at least one detection existsif len(idxs) > 0: # loop over the indexes we are keeping for i in idxs.flatten(): # extract the bounding box coordinates (x, y) = (boxes[i][0], boxes[i][1]) (w, h) = (boxes[i][2], boxes[i][3]) # draw a bounding box rectangle and label on the image color = [int(c) for c in COLORS[classIDs[i]]] cv2.rectangle(image, (x, y), (x + w, y + h), color, 2) text = “{}: {:.4f}".format(LABELS[classIDs[i]], confidences[i]) cv2.putText(image, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)# show the output imagecv2.imshow(“Image”, image)cv2.waitKey(0)假设存在至少一个检测结果,就循环用非最大值抑制确定idx 。然后,我们使用随机类颜色在图像上绘制边界框和文本 。最后,显示结果图像,直到用户按下键盘上的任意键。下面进入测试环节,打开一个终端并执行以下命令:$ python yolo.py –image images/baggage_claim.jpg –yolo yolo-coco[INFO] loading YOLO from disk…[INFO] YOLO took 0.347815 seconds从上图可以看到,YOLO不仅检测了输入图像中的每个人,还检测了手提箱。此外,可以从图像的右上角看到,YOLO还检测到女士肩上的手提包。我们试试另一个例子:$ python yolo.py –image images/living_room.jpg –yolo yolo-coco[INFO] loading YOLO from disk…[INFO] YOLO took 0.340221 secondsYOLO还可以检测电视显示器和椅子,令我惊讶的是YOLO能够检测到椅子,因为它是手工制作的老式“婴儿高脚椅”。有趣的是,YOLO认为我手中有一个遥控器,它实际上不是遥控器——玻璃反射的VHS录,仔细盯着这个地方看,它实际上看起来非常像遥控器。以下示例图像演示了YOLO对象检测器的局限性和弱点:$ python yolo.py –image images/dining_table.jpg –yolo yolo-coco[INFO] loading YOLO from disk…[INFO] YOLO took 0.362369 seconds虽然YOLO正确检测到葡萄酒瓶、餐桌和花瓶,但只有两个酒杯中的一个被正确检测到。下面尝试最后一幅图像:$ python yolo.py –image images/soccer.jpg –yolo yolo-coco[INFO] loading YOLO from disk…[INFO] YOLO took 0.345656 secondsYOLO能够正确地检测球场上的每个球员,包括足球本身。请注意,尽管区域高度模糊且部分遮挡,但仍会检测到背景中的人。以上内容就是图像检测部分的全部内容,下一节将介绍视频流中对象检测以及YOLO算法的总结。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

November 21, 2018 · 4 min · jiezi

基于Opencv&Tensorflow实现实时查找停车位置

摘要: 一个小例子带你玩转Opencv+tensorflow~介绍你是不是经常在停车场周围转来转去寻找停车位。如果你的手机能准确地告诉你最近的停车位在哪里,那是不是很爽?事实证明,基于深度学习和OpenCV解决这个问题相对容易,只需获取停车场的实时视频即可。下面的GIF图片突出显示洛杉矶机场停车场上所有可用的停车位,并显示可用停车位的数量,关键是这一过程是实时的!你可以在Github repo找到我曾用过的代码。步骤概述构建这个停车检测模型主要有两个步骤:1.检测所有可用的停车位;2.确定停车位是空的还是被占用的;因为安装了摄像头视图,我们可以使用OpenCV对每个停车位进行一次映射。一旦你知道了每个停车位的位置,你就可以用深度学习来预测它是否空着。我已经在我的博客上分享了所涉及的一个高层次步骤的概述。如果你对详细代码感兴趣,请看看我的博客。检测所有可用停车位的位置检测停车位的基本思路是,所有的停车点的分隔线都是处于水平线,而一列中的停车点之间的间隔大致相等。首先使用Canny边缘检测来获得边缘图像。我还把没有停车的地方遮了起来。如下所示:然后我在边缘图像上做了霍夫变换,画出了它能识别的所有线。我只选择斜率接近于零的直线来隔离水平线。霍夫变换的输出如下:正如你所看到的那样,霍夫变换在识别停车线方面做得相当好,但是输出有噪声——几个停车线被多次检测到,而有些被遗漏了。那么我们如何解决这个问题呢?然后我用观察和直觉开始,通过使用霍夫变换返回的坐标,聚集x坐标来确定主要的停车道。利用聚类逻辑来识别车道线x坐标的间隔。这样就能识别出这里的12个车道。如下:如果所有这些看起来都很复杂,别担心5——我已经在github的jupyter notebook上一步一步地记录了代码。现在我已经知道了所有的停车道都在哪里,通过合理地假设所有的停车点大小都一样来识别每个单独的停车位。我仔细观察了结果,以确保尽可能准确地捕捉到点之间的边界。我终于能够标出每个停车位。如下:当完成了每个车位的定位之后,我们可以为每个点分配一个ID,并将其坐标保存在字典中并将它pickled了一下,以便以后能取回。这是可以实现的,因为安装了摄像头,我们不需要一次又一次地计算每个点在视图中的位置。更多详情请登录我的博客。识别该车位是否有标记现在我们有了每个停车位的映射,可以通过以下几种方式来确定这个停车位是否被占用:1.使用OpenCV检查视频图像中停车位的像素颜色是否与空停车位的颜色一致。这是一种简单的方法,但容易出错。例如,灯光的变化将会改变一个空停车位的颜色,在一天的光照变化中,这种方法将无法正确工作。如果有可能的话,这种逻辑会把灰色的汽车当成空停车位;2.使用目标检测来识别所有的汽车,然后检查汽车的位置是否与停车位重叠。我做了尝试,发现实时检测模型真的很难检测小尺寸的对象,检测到的车辆不超过30%;3.使用CNN检测每个停车位,并预测是否有人停车,这种方法最终效果最好。要构建一个CNN,我们需要停车位有车以及无车这两种情况的图像。我提取了每个停车位的图像,并将其保存在文件夹中,然后将这些图像分组。我还在Github上分享了这个训练文件夹。因为在1280x720像素的图像中有近550个车位,所以每个车位的大小只有15x60像素左右。下面是空车位和被占用车位的图像:然而,由于被占用车位和空车位看起来有很大的不同,这对CNN来说应该不是一个具有挑战性的问题。然而,我只有大约550张关于这两个类的图片,所以决定利用VGG的前10层,并在VGG模型的输出添加一个单一的softmax图层来进行迁移学习。你可以在这里找到这个迁移学习模型的代码,准确率达到94%。见下文:现在,我将停车位检测和CNN预测器结合起来,构建了一个停车位检测器,准确率非常高。我还在notebook记录了在视频流上运行这个的代码。结论对于联合不同的工具和使用深度学习来构建实际应用程序这么容易我感到很惊奇,我在两个下午完成了这项工作。准备进一步探索的其他几个想法:1.如果可以将车位检测逻辑扩展到任何可能使用深度学习的车位地图上,那就太好了,OpenCV对每个用例进行调优有限制;2.CNN使用的VGG模型是一个重量化模型,想要尝试更轻量化的模型。云服务器99元拼团购!拉新还可赢现金红包!300万等你瓜分!马上一键开团赢红包: http://click.aliyun.com/m/1000019899/本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

October 30, 2018 · 1 min · jiezi