Windows
Windows 编程

OpenCv 训练自己的分类器

工具(64位)

opencv_createsamples

opencv_traincascade

使用64位你可以使用更多的内存,因为32位可以使用的地址很少,很容易造成训练过程中的内存不足。上述两个工具在编译源代码的时候会自动生成,如果你没有编译源代码,那么你可以直接下载:https://opencv.org/releases 在bin目录下就可以找到这两个工具。

训练样本:正负样本

正样本:仅包含被检测物体的样本,并且距离边界尽量要小,图片尺寸大小一致。

负样本:不包含被检测物体的样本,图片尺寸大小无要求。

建议:正样本图片尺寸尽量小一些,并且进行归一化然后灰度处理,检测物体距离边界近一些,背景尽量是纯色,少夹杂一些颜色,突出被检测物体。

数量:正样本 : 负样本=1 : 3 这个比例在OpenCv官网有一个更精准的说法,最大是1 : 3,负样本大于正样本,这样可以保证训练过程中负样本不会因为太少而终止训练。

实验

这里我已识别二维码为例,首先编写代码生成随机的正样本二维码,这里我生成的二维码是50x50像素,根据你要识别的物体,尽量尺寸小一些。

111.png

这里并没有进行归一化灰度化,进行了更好,那样时间上会大大缩短。

负样本数据是直接爬取的网上的图片,内容随机。
微信截图_20190710150000.png

负样本这里我进行了转换,主要是抓取的图片太大,所以进行了一下转换。

结构目录

33.png

neg和pos是存放训练图片的,按说明把正负样本放进去就可以了,编号最好从0开始顺序编号,因为后续的描述文件有用到,有一点图片的格式最好是jpg和png其他的格式需要自己编译支持才行。网络抓取的图片可能保存的后缀是jpg但是真实的文件格式可能是其他的,这点需要注意。

neg.txt 描述文件内容如下

neg/1.jpg

neg/2.jpg

...

...

...

neg/599.jpg

neg/600.jpg

这里我准备了600张负样本

pos.txt描述文件内容如下

pos/1.jpg 1 0 0 50 50

pos/2.jpg 1 0 0 50 50

...

...

...

pos/199.jpg 1 0 0 50 50

pos/200.jpg 1 0 0 50 50

这里我准备了200张正样本比例正好是1 : 3(正 : 负),

格式【图片路径】【图片内包含的被检测物体的数量】【被检测物体的左上角坐标】【被检测物体的右下角坐标】

这里没有去量二维码在图片内的坐标,所以认为是整张图都是,那就是x:0-y:0-x:50-y:50。

生成vec文件

命令:opencv_createsamples.exe -vec pos.vec -info pos.txt -num 200 -w 50 -h 50

格式:opencv_createsamples.exe -vec 【vec文件存储名字】 -info 【正样本描述文件】 -num 【正样本数量】 -w 【正样本图片宽度】 -h 【正样本图片高度】

开始训练

命令:opencv_traincascade.exe -data xml -vec pos.vec -bg neg.txt -numPos 200 -numNeg 600 -numStages 15 -w 50 -h 50 -minHitRate 0.999 -maxFalseAlarmRate 0.2 -weightTrimRate 0.95 -featureType LBP

格式:opencv_traincascade.exe -data xml -vec 【vec文件存储名字】 -bg 【负样本描述文件】 -numPos 【正样本数量】 -numNeg 【负样本数量】 -numStages 【训练层级数】 -w 【正样本图片宽度】 -h 【正样本图片高度】 -minHitRate 【接近1的数】 -maxFalseAlarmRate 【接近0的数】 -weightTrimRate 0.95 -featureType 【算法类型】

具体的参数可以参考OpenCv的说明,注意你的正样本数填写的时候如果你觉得样本不是很规范,那么本来你训练的是200张,这里你就可以填写150,尽量填写的小于真实的数字,不容易出错,由于这里是用工具生成的正样本,比较规范,所以还是填写的200。

训练过程

微信截图_20190710152027.png

N:层数  %

HR:当前层数 对正样本识别正确的概率

FA:当前层数 对负样本识别错误的概率

训练完成后会在XML文件夹下生成一个cascade.xml文件,这个文件就是分类器。XML文件夹下还会有每层的结果,训练的过程中完全可以Ctrl+C进行打断,下次继续训练。

识别结果

微信截图_20190710143918.jpg

代码

/** 定义一个级联分类器 */
cv::CascadeClassifier Detector;
/** 加载分类器 */
Detector.load("C:\\Users\\iwonmo\\Desktop\\cascade.xml")
/** 加载进来图片 */
cv::Mat image = cv::imread("C:\\Users\\iwonmo\\Desktop\\55.jpg");
/** 定义检测结果变量 */
std::vector<cv::Rect> qrcode;
/** 进行识别并会把结果存储到qrcode里 */
Detector.detectMultiScale(image , qrcode, 1.3, 1, 0, cv::Size(50, 50));
/** 标记位置 */
for (size_t t = 0; t < qrcode.size(); t++) {
    cv::rectangle(image, qrcode[t], cv::Scalar(0, 108, 255), 3);
}
/** 显示图片 */
cv::imshow("qrcode", image);

注意训练什么分类器,就定义对应的分类器变量。如果你是HOG分类器,则需要定义HOGDescriptor类型的Detector。

opencv 实现人脸对比

基础

VS2013

CMake 3.7.2

OpenCV:(版本:3.3.0):https://github.com/opencv/opencv

opencv_contrib:(版本:3.3.0) :https://github.com/opencv/opencv_contrib

下载

OpenCV和opencv_contrib下载的时候一定要选择对应版本

微信截图_20190703171018.png

生成工程文件

用CMake编译的时候,第一次点击Configure会出现很多红色,这个红色的出现,是让你进行编译确认。正确的编译顺序。

阅读全文»

codeblock dlib gcc

Code::Blocks gcc 编译 dlib 方法

注意:gcc需要是支持C++11 并且 thread model是posix不能是win32。

打包文件,回复后下载

阅读全文»

微擎:小程序上传图片重定向问题

调用wx.uploadFile总是返回如下代码

<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
    </head>
    <body>
        <script type="text/javascript">
            var ua = navigator.userAgent.toLowerCase();
            var isWeixin = ua.indexOf('micromessenger') != -1;
            var isAndroid = ua.indexOf('android') != -1;
            var isIos = (ua.indexOf('iphone') != -1) || (ua.indexOf('ipad') != -1);
            if (!isWeixin) {
                document.head.innerHTML = '<title>抱歉,出错了</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0"><link rel="stylesheet" type="text/css" href="https://res.wx.qq.com/open/libs/weui/0.4.1/weui.css">';
                document.body.innerHTML = '<div class="weui_msg"><div class="weui_icon_area"><i class="weui_icon_info weui_icon_msg"></i></div><div class="weui_text_area"><h4 class="weui_msg_title">请在微信客户端打开链接</h4></div></div>';
            }
        </script>
    </body>
</html>

百思不得其解,上网查询也是无果,没有办法只能看下HTTP请求包。

微信截图_20190523173447.png可以看到被302重定向了,后端上传代码里并没有重定向操作,所以查看了下标识,发现MicroMessenger。猜测应该是被微擎重定向了。

微擎源代码里有这么一段:

// 检查是否在微信中打开
public static function isMicroMessage($agent = '')
{
    $agent = self::getAgent($agent);
    if (stripos($agent, 'MicroMessenger') !== false) {
        return self::MICRO_MESSAGE_YES;
    } else {
    return self::MICRO_MESSAGE_NOT;
    }
}

会检查你的agent,如果包含MicroMessenger则会当成是在微信中打开。然后调用getOauthCodeUrl|getOauthCodeUrl去获取你的微信信息。所以会造成重定向。

修改微信开发者工具,将请求头改掉

333.png然后上传成功

微信截图_20190523173600.png

真实的环境下,一般会存在第三方存储服务商,所以不会发生这种情况。如果你要在微擎里改掉授权操作,那么很有可能出现一系列问题,所以还是建议在微擎外写一个上传接口。

HBuilder 免安装调试方法探究

关于HBuilder基座的分析可以看:https://www.iwonmo.com/archives/1414.html

本质上是一个webview,而每次保存adb都会push到私有目录下的www目录,然后进行重运行。

命令行如下:

parent_pid:612
cmdline:'c:\users\wonmo\desktop\hbuilderx.1.8.1.20190330.full\hbuilderx\plugins\launcher\tools\adbs\adb.exe -s 022TDM1481004885 push C:\Users\wonmo\Documents\HBuilderProjects\d\unpackage\dist\dev\app-plus/. /sdcard/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/'
image_base:0x0000000000400000
image_size:0x00113000

这种方式每次都要把vue编译后的文件上传到www。在想有没有更简便的方式,结合前段时间分析微信的开发者工具https://www.iwonmo.com/archives/1539.html尝试了一种方法。

流程:

屏幕快照 2019-03-31 上午11.43.44.png


编辑器搭建http环境,手机收到广播,判断广播类型,webview重新加载http地址。

实现:

发送

屏幕快照 2019-03-31 上午11.26.03.png

接收

屏幕快照 2019-03-31 上午11.26.20.png