小白啃骨头系列是通过案例的分享,描述7是怎么入门某类技术的。下面就请进入正题吧~

相信大家对于有一些名词耳熟能详,可以谈天说地,但是真正想要用起来,却觉得门槛太高,望而却步。如今AI大火,凡是沾点边就感觉高级炸了。什么图像识别,语音识别,自动驾驶等等,今天7,就不怕死的去尝试了这么难啃的骨头,究竟结论怎样呢?我们先看样本骨头。

本次案例的目的是用python3的OpenCV库实现答题卡识别,这里可能要补充一点知识,毕竟对于真小白来说,我们需要名词解释环节。

OpenCV:分为OPEN + CV, open好理解open source即开源,CV指的是计算机视觉(computer version)。OpenCV最早由英特尔公司于1999年启动,后来以BSD许可证授权发行,可以在商业和研究领域中免费使用。简而言之,你做图像识别,或者计算机视觉或者模式识别,那很有可能和它打交道了。OpenCV最早支持C语言,因为就是C写的,而先前很火的OpenCV的例子是用MATLAB开发的,如今Java,Python等都有相关的库可以使用了。

关于各个平台python和OpenCV怎么安装,大家自行Google解决啦。

附上本地示例的原图:

解决一个问题,第一步是要有思路。但我相信很多新手对于要识别图像,识别答题卡是没有思路的,没错,要是你有思路那就不是小白了。7对于这艰难的第一步那就是去找文档和开源项目看,总结他们的相同点,整理核心算法思路,梳理整个识别的步骤。然后在debug自己的代码,一边被虐一边进步。

思路有了,下面就要开始敲一敲了。7会给出每一步对应的代码片段帮助大家理解过程。

  • 进行图像灰度,使图像黑白(二值化)

为什么要进行二值化,我认为有两点,一是硬性要求,很多算法要求输入是一个二值化后的图像,俗称黑白图像;二是为了更好地区分主题和背景。比如你需要识别pdf里的文字,如果用彩色图像,那你就要先区分颜色,在处理文字,而实际上对于整个识别目的来说,只需要识别字,并不在意字本身什么颜色,也就是忽略颜色对识别的干扰。那为什么二值化之前要灰度,灰度图像像素介于0-255之间,在二值化的时候我们只需要设定某一个值,高于这个值就是黑,低于这个值则是白。这整个过程过程分为两小步:

  1. 对原图像进行灰度,然后应用高斯模糊使图像模糊一点,去除随机点

通俗的来说就是去噪,为了去除噪点对图像的影响,也就是平时大家P照片时美颜。

# 灰度gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)# 高斯模糊,3 * 3的核,此处核越大就越模糊,即美颜效果越好。blur = cv.GaussianBlur(gray, (3, 3), 0)

2. 使用自适应阈值设置每个像素为黑色或白色

这一步就是图像二值化,把像素分为0和255两个度,非黑即白。

# 图像二值化binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, 5, 4)
  • 使用霍夫变换找到图中的直线, 找到直线的交点,形成四边形

对于答题卡来说,因为每个答题卡设计会影响我们的算法,这一步是核心算法,需要定位答题卡的答题范围。在7的示例中,我们采用的答题卡有一个很重要的特点,那就是答题卡区域整个答题卡最大的区域,也就是说,我们通过找出答题卡中的轮廓,找到最大的就是答题的区域了。

# 找到二值化图像所有的轮廓conts = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)[0]# 对轮廓进行反向排序,第一个就是最大的轮廓即示例中答题区域conts = sorted(conts, key=cv.contourArea, reverse=True)
  • 找到四边形轮廓,并对四边形应用透视变换

为什么要进行透视变换?这里的透视变换是四点透视,透视变化是一种投影。大家可以思考一个例子,如果我们因为角度问题是不是在扫描矩形图片的时候并不是一个矩形,可能是个梯形,这与实际不符,算法需要规避这种角度问题,所以有了变化操作,而四点透视就是为了把一个梯形拉成一个矩形(可能比较抽象,如果不能理解,大家可以尝试用手机从非物体正上方的位置拍一张照感受下)

# 多边形拟合,我们找到的轮廓都是有像素点构成的,计算机只能处理像素,# 在计算机眼里并没有直线曲线之分。peri = 0.01 * cv.arcLength(cont, True)approx = cv.approxPolyDP(cont, peri, True# 判断是否为四边形if len(approx) == 4:    # 四点透视变换    ox = four_point_transform(image, approx.reshape(4, -1))
  • 使用霍夫变换找到图中的答案轮廓

有了轮廓的概念,其实答案框也是一个一个的轮廓,通过答案框长宽比例来过滤掉非答题框的轮廓。

for c in cnts:  # 对每一个轮廓进行长宽比过滤,找到所有答案框的位置  x, y, w, h = cv.boundingRect(c)  ar = w / float(h)  if 80 >= w >= 46 and h >= 30 and 1.2 <= ar <= 1.9:      cv.rectangle(question, (x, y), (x + w, y + h), (0, 0, 255), 2)      question_choices.append(c)
  • 区分答题框是否填充

这里我们采用在答题框轮廓中像素点进行反向排序,像素最多的即为填涂的选项(这里只适用于单选题)

for (i, q) in enumerate(np.arange(0, len(question_choices), 12)):    if i <= 10:         line_cnts = question_choices[q:q + 12]        line_cnts = contours.sort_contours(line_cnts, method="left-to-right")[0]        # 取出i行,第k题        for (k, m) in enumerate(np.arange(0, len(line_cnts), 4)):            ticket_num = i + k * 17 + 1            bubble_rows = []            m_cnts = line_cnts[m:m + 4]            # print("{}: {}".format(i, len(m_cnts)))            # 取出k题 j选项            for j, c in enumerate(m_cnts):                mask = np.zeros(tx.shape, dtype=tx.dtype)                cv.drawContours(mask, [c], -1, 255, -1)                mask = cv.bitwise_and(binary, binary, mask=mask)                total = cv.countNonZero(mask)                bubble_rows.append((total, j))            bubble_rows = sorted(bubble_rows, key=lambda x: x[0], reverse=True)            choice_num = bubble_rows[0][1]            student_answer.append((ticket_num, answer_format.get(choice_num)))

上面的算法写的比较初学者,大神们看看就行了

  • 最后我们打印出题号和答案

    # 比较简单就不赘述了    for item in student_answer:        print("题号: {} 答案:{}".format(item[0], item[1]))    return {"答题卡答案": [{'题号': x[0], '答案': x[1]} for x in student_answer]}

以上就是小白啃骨头的过程,完整代码会重新整理后放到GitHub上。由于本文涉及的内容比较专业,如果有说错的还请各路大神不吝赐教,早日指正!

推荐阅读

(点击标题可跳转阅读)

最详细、最完整的相机标定讲解

深度学习+机器视觉=下一代检测

视觉检测系统最经典的结构你了解吗?

机器视觉技术的十大应用领域

工业相机和普通相机究竟有什么不同?

基于机器视觉和深度学习的智能缺陷检测

波士顿等移动机器人的视觉算法解析

2020年37个人工智能技术发展趋势

机器视觉的光源选型及打光方案分析

光学三维测量技术及应用

国内80%搞机器视觉的工程师,走的路子是错的!

视觉+机器人,如何实现连接器的自动装配?

机器视觉技术发展的五大趋势

搞懂机器视觉基本内容,这份PPT就够了

机器视觉:PC式视觉系统与嵌入式视觉系统区别

基于HALCON的机器视觉开发,C++或C#如何选择?

3D视觉技术在机器人抓取作业中的应用实例

基于机器视觉的粗糙度检测方案

机器视觉常用图像软件对比及分析

工业相机编程流程及SDK接口使用汇总

 End 

声明:部分内容来源于网络,仅供读者学习、交流之目的。文章版权归原作者所有。如有不妥,请联系删除。

matlab二值化图像_小白啃骨头之图像识别相关推荐

  1. 基于MATLAB二值化图像的形态学处理

    在Matlab中将一幅图像阈值分割二值化非常简单,若需要通过阈值th2二值化保留一些大面积的.且有灰度值含有大于th1的点的前景区域,而不需要小面积的区域(th1大于th2),这时会遇到这样的问题:当 ...

  2. matlab 二值化图像反色,图像处理——灰度化、二值化、反色、饱和度、对比度...

    RGB RGB色彩模式使用RGB模型为图像中每个像素的RGB分量分配一个0~255范围内的强度值.RGB图像仅仅使用三种颜色,R(red).G(green).B(blue),就能够使它们依照不同的比例 ...

  3. MATLAB二值化图像

    直接上代码: RGB = imread('cat.jpg');   %读入图像 tu=im2gray(RGB);   %将图像转化为灰度图像 BW = imbinarize(tu);   %将灰度转化 ...

  4. python opencv二值化图像_python opencv,读取彩色图像,提取三通道,图像二值化,提取图像的边缘...

    python opencv,读取彩色图像,提取三通道,图像二值化,提取图像的边缘 python opencv 1,读取图像 2,图像变矩阵 3,图像转灰度图像 4,彩色图像是3D数组 5,灰度图像是2 ...

  5. ZYNQ图像处理(4)——灰度图像转二值化图像

    1.二值化图像简介 前面已经完成了摄像头图像的采集和显示,以及RGB图像转灰度图.二值化图像在图像处理领域同样有广泛的应用,本节介绍如何用FPGA实现灰度转二值化图形.灰度实现二值化的原理很简单,只需 ...

  6. java 图像二值化阀值,阈值 二值化图像程序

    在Matlab中将一幅图像阈值分割二值化非常简单,若需要通过阈值th2二值化保留一些大面积的.且有灰度值含有大于th1的点的前景区域,而不需要小面积的区域(th1大于th2),这时会遇到这样的问题:当 ...

  7. 二值化图像的欧拉数_Android OpenCV(八):图像二值化

    图像二值化 简介 图像二值化( Image Binarization)就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程.在数字图像处理中,二值图像占有非常重要的 ...

  8. 二值化图像去除小黑点_python与图像工程(2020.10.11)

    一.think python--字符串str.列表list.字典dict.元组tuple的比较 在think python的学习中,第八.十.十一.十二章介绍了四种相似的数据类型:字符串.列表.字典. ...

  9. python对图像二值化_python如何二值化图像

    在python中二值化图像的方法:首先将图片转化为灰色图像:然后自定义灰度界限:最后输入"photo=Img.point(table,'1')"命令(table为自己创建的数组名) ...

最新文章

  1. jquery初始化的三种方式
  2. WPF: RenderTransform特效
  3. java cancel_Java RunnableFuture.cancel方法代码示例
  4. 【Linux】一步一步学Linux——Centos7.5安装图解(08)
  5. 200819C阶段一C++面向对象的编程思想
  6. kali下生成web端后门
  7. RUNOOB python练习题8 numpy矩阵的索引及遍历
  8. 原创|面试官:线上服务器CPU占用率高如何排查定位问题?
  9. 解决虚拟机VMware运行Ubuntu时无法和主机之间复制粘贴的问题
  10. “vmware tools 只能虚拟机中安装”的解决方法
  11. 手机同步专家--基于SyncML协议同步通讯录的应用软件
  12. android之仿朋友圈程序,Android仿微信朋友圈添加图片的实例代码
  13. 剪辑过的视频md5会改变
  14. 蓝桥杯 平方和(JAVA)
  15. 什么是域名解析,A记录
  16. nvidia xavier平台无PD控制器USB接口调试
  17. 生物信息学算法之Python实现|Rosalind刷题笔记:001 碱基统计
  18. html的css怎么设置深度,vue css 深度选择器
  19. css超链接中的下划线设置
  20. OSChina 周一乱弹 ——第一天上班,命都搭上了!

热门文章

  1. Pytorch常见的坑汇总
  2. 美多商城之用户注册(展示用户注册页面)
  3. python多线程的使用(导入线程模块、创建子线程任务、启动子线程任务、获取当前执行的线程号)
  4. Linux之文本搜索命令 grep
  5. 关系型数据库管理系统和SQL介绍
  6. python 时间time()及日期date()函数
  7. servlet里面的context,定义属性值的事情!
  8. 亲测可以使用的:Maven将中央仓库修改为阿里云的maven仓库
  9. 技术16期:如何更好的保证数据质量【大数据篇】
  10. 如何识别出轮廓准确的长和宽