OpenCV是一款非常强大的图像处理工具,对于从事图像处理领域相关工作的人来说这个可以说是必不可少的一项工具,用起来也很方面,下吗是一段简单的介绍:

OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
OpenCV用C++语言编写,它具有C ++,Python,Java和MATLAB接口,并支持Windows,Linux,Android和Mac OS,OpenCV主要倾向于实时视觉应用,并在可用时利用MMX和SSE指令, 如今也提供对于C#、Ch、Ruby,GO的支持。

OpenCV官网在这里,首页截图如下所示:

下面给出来几个学习OpenCV的链接:

https://docs.opencv.org/master/d9/df8/tutorial_root.htmlhttps://docs.opencv.org/https://www.zhihu.com/question/26881367

我们今天的内容主要是想基于OpenCV来实现对电子扫描版的试卷中批改结果的检测,也就是老师给打的对号、错号的检测,还是挺有意思的。先看一张试卷样例:

接下来,看一下经过实际处理后的图像结果数据:

上面第三幅子图就是我们这里的掩膜图像,看的不是很真切,因为背景是黑色的加上对号和错号显示从横深蓝色就分不清楚了,为了方便观察,这里我对mask处理后的图像转为灰度图,也就是上面的第五幅图像,已经很清晰地看到了试卷中的批改结果都已经很清晰的筛选了出来了。最后一幅子图就是我们将计算出来的区域叠加到原图上面得到的最终的结果图像了。

接下来,我们进入正文,在实际去实践之前,我们很有必要来了解一下几种比较常用的颜色空间,简单总结汇总如下:

RGB颜色空间:
R:Red 红色
G:Green 绿色
B:Blue 蓝色HSV颜色空间:
H:Hue 色度
S:Saturation 饱和度
V:Value 亮度HSI颜色空间:
H:Hue 色度
S:Saturation 饱和度
I:Intensity 强度

如果想要深入了解学习的话这里推荐一篇不错的博客:

《RGB、HSV、HSI颜色空间》

感兴趣的话可以自行学习,这里就不再对其进行累述了。

本质上来讲,不同的物体不同的对象自身的像素范围是不同的,在实际操作的时候基于像素区间可以过滤得到你所关注的对象,通常这样的操作会在HSV空间中进行,个人的理解是将原始的BGR或者是RGB的图像转化到HSV空间里面来确定目标对象的像素区间更为容易,我实际测试过,在RGB和BGR空间里面也是可以进行计算的,只不过不如HSV空间,这里就不再多讨论了,可以尝试别的方式,本文用的是HSV空间进行计算的。

最开始的时候去确定目标对象所处的像素空间是很笨拙的,主要是借助OpenCV和matplotlib实现的【人眼探索】,比较麻烦,这一块可以借助编程来解决,参见前文:

《opencv实现图像目标对象区域挖掘》

启动后截图如下:

接下来尝试调节上方H、S、V三个维度的滚动条来观察图像的变化:

经过几次的调节,最终效果如下所示:

已经达到了我的预期目的了,记录下来这组数据即可:

到这里,我们已经获取到了所需要的各个维度的阈值数据了,就可以进行后面的处理了。

接下来我们基于上述阈值来进行区域挖掘计算,同样使用上述的图片,核心代码实现如下所示:

#!usr/bin/env python
#encoding:utf-8
from __future__ import division'''
__Author__:沂水寒城
功能: 基于 OpenCV 实现对号错号检测
'''import io
import os
import sys
import cv2
import time
import json
import base64
import random
import numpy
import datetime
import requests
from PIL import Image
from flask import *
from scipy import  misc
import numpy as np
from matplotlib import pyplot as pltplt.clf()
plt.figure(figsize=(10,8))demo=Image.open('a.jpg')
h,w=demo.sizeplt.subplot(2,3,1)
plt.imshow(demo)
plt.title("original")img=cv2.imread('a.jpg')
print(img.shape)
area=h*w
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)plt.subplot(2,3,2)
plt.imshow(hsv)
plt.title("HSV")h,w,way=img.shape
total=h*w
print('h: ', h, 'w: ', w, 'area: ', total)
#对号、错号
lower = [0, 40, 0]
upper = [179, 255, 255]
lower = np.array(lower, dtype="uint8")
upper = np.array(upper, dtype="uint8")
mask = cv2.inRange(hsv, lower, upper)
output = cv2.bitwise_and(hsv, img, mask=mask)count = cv2.countNonZero(mask)
print('count: ', count)
now_ratio=round(int(count)/total,3)
print('now_ratio: ', now_ratio)plt.subplot(2,3,3)
plt.imshow(output)
plt.title("mask,ratio: "+str(now_ratio))result={}
result['count'],result['ratio']=count,now_ratio
print('output: ', output)plt.subplot(2,3,4)
plt.imshow(output)
plt.title('HSV2BGR')gray=cv2.cvtColor(output,cv2.COLOR_BGR2GRAY)
print('gray: ', gray)plt.subplot(2,3,5)
plt.imshow(gray)
plt.title("gray")ret,output=cv2.threshold(gray, 10, 255, cv2.THRESH_BINARY)contours,hierarchy=cv2.findContours(output,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
print('contours_num: ', len(contours))
count_dict={}
areas,lengths=0,0
for i in range(len(contours)):one=contours[i]one_lk=one.tolist()if len(one_lk)>=2:area=cv2.contourArea(one)length=cv2.arcLength(one, True)areas+=arealengths+=lengthleft_list,right_list=[O[0][0] for O in one_lk],[O[0][1] for O in one_lk]minX,maxX,minY,maxY=min(left_list),max(left_list),min(right_list),max(right_list)A=abs(maxY-minY)*abs(maxX-minX)print('area: ', area, 'A: ', A, 'length: ', length)count_dict[i]=[A,area,length,[minX,maxX,minY,maxY]]
sorted_list=sorted(count_dict.items(), key=lambda e:e[1][0], reverse=True)
print(sorted_list[:10])
result['value']=count_dict
cv2.drawContours(img,contours,-1,(0,0,255),3)print('==========================================================================')
if sorted_list:filter_list=filterBox(sorted_list)for one_box in filter_list:print('one_box: ', one_box)A,area,length,[minX,maxX,minY,maxY]=one_boxprint('sorted_area: ', A,area)cv2.rectangle(img,(minX,maxY),(maxX,minY),(0,255,0),10)plt.subplot(2,3,6)
plt.imshow(img)
Sratio=round(areas/total,3)
try:Lratio=round((2*h+2*w)/lengths,3)
except:Lratio=0
plt.title("areas:"+str(round(areas,1))+',len:'+str(round(lengths,1))+'\nSratio:'+str(Sratio)+',Lratio:'+str(Lratio))
plt.show()

后面为了简单对比,绘制了四张子图对比示意图,如下所示:

基于OpenCV的检测工作整体上来说偏简单化了,真正想要高精度的检测还是需要深度学习模型,比如:目标检测方法来实现的,后面有时间再做吧。

到这里本文的内容就结束了,学习依旧在路上,欢迎交流,互相学习!

opencv实现电子试卷图片中对号、错误的检测相关推荐

  1. 标准化计算机考试软件,考易标准化电子试卷制作系统

    考易标准化电子试卷制作系统是一款简单实用的电子试卷制作设计工具,软件可以设置试题文件.试卷答案.音频文件.提示或讲解文件.试卷评语.试卷信息等,无需数据库支持,轻轻松松设计电子考卷,支持将试卷制作为E ...

  2. OpenCV模板匹配识别图片中的数字

    OpenCV模板匹配识别图片中的数字 前言 本博客主要实现利用OpenCV的模板匹配识别图像中的数字,然后把识别出来的数字输出到txt文件中,如果识别失败则输出"读取失败". 操作 ...

  3. 怎么样才能使计算机题库打开不是wps,wps表格巧制电子试卷实现无纸化考试让电脑自动批改...

    电子试卷的出现实现了实现无纸化的考试充分利用这个现代科学技术为教学和办公服务.电子试卷,一般仅支持选择.判断.填空等客观性试题,如果没有专业的考试系统的话,我们可以考虑使用WPS2009电子表格提供的 ...

  4. 怎么用计算机批改试卷,WPS表格如何制作电脑自动批改电子试卷

    启动WPS表格,新建一空白文档,按照传统试卷的格式和要求,制作好一张试卷头.下面学习啦小编给大家分享WPS表格制作电脑自动批改电子试卷的技巧,欢迎阅读: WPS表格制作电脑自动批改电子试卷的教程: 一 ...

  5. 关于opencv调用onnx模型的一个错误 Can’t infer a dim denoted by -1 in function ‘cv::dnn::computeShapeByReshapeMas

    关于opencv调用onnx模型的一个错误 Can't infer a dim denoted by -1 in function 'cv::dnn::computeShapeByReshapeMas ...

  6. 【OpenCV学习】(十)特征点检测与匹配

    [OpenCV学习](十)特征点检测与匹配 背景 提取图像的特征点是图像领域中的关键任务,不管在传统还是在深度学习的领域中,特征代表着图像的信息,对于分类.检测任务都是至关重要的: 特征点应用的一些场 ...

  7. OpenCV for Ios 学习笔记(4)-标记检测1

    本文原始地址:OpenCV for Ios 学习笔记(4)-标记检测1 简单的标记经常是以白色块和黑色块构成的规则图形.因为我们预先知道这些因素,所以我们可以很容易检测标记. 如图: 首先,我们需要找 ...

  8. 【OpenCV入门指南】第五篇轮廓检测 下

    上一篇<[OpenCV入门指南]第五篇轮廓检测上>介绍了cvFindContours函数和cvDrawContours函数,并作了一个简单的使用示范.本篇将展示一个实例,让大家对轮廓检测有 ...

  9. 【OpenCV入门指南】第五篇 轮廓检测 上

    <[OpenCV入门指南]第三篇Canny边缘检测>中介绍了边缘检测,本篇介绍轮廓检测,轮廓检测的原理通俗的说就是掏空内部点,比如原图中有3*3的矩形点.那么就可以将中间的那一点去掉. 在 ...

  10. Python+opencv 机器视觉 - 基于霍夫圈变换算法检测图像中的圆形实例演示

    Python+opencv 机器视觉 - 基于霍夫圈变换算法检测图像中的圆形实例演示 第一章:霍夫变换检测圆 ① 实例演示1 ② 实例演示2 ③ 霍夫变换函数解析 第二章:Python + openc ...

最新文章

  1. 09.20类类型random
  2. BLE 安全之虫洞攻击
  3. Creator-配置MSVC调试器
  4. 关于本次课堂代码的练习
  5. java网络编程_Java基础 网络编程
  6. puzzles —— 111、222、333、444、555、666、777、888、999
  7. LeetCode Repeated DNA Sequences
  8. linux 解决Linux上解压jdk报错gzip: stdin: not in gzip format
  9. 25.211 -- 物理层信道
  10. 深圳安全研讨会圆满结束,PPT共享下载
  11. 51单片机实现电子时钟代码
  12. 机器学习与模式识别期末试题回忆
  13. HDFS的设计目标是什么?
  14. 空气净化器哪个品牌口碑好 空气净化器除甲醛排行榜前十名
  15. 解字谜:黑白皆算,对我等众猿而言中央C所在位置数优剃爱肤杠吧爱慕帝贰亿次的值是?...
  16. 自定义圆环形进度条实现
  17. 关于家庭收纳:请好好运用二维码!
  18. 【图解】PCB快速制板,热转印机+腐蚀槽
  19. 【Kotlin 协程】Flow 异步流 ② ( 使用 Flow 异步流持续获取不同返回值 | Flow 异步流获取返回值方式与其它方式对比 | 在 Android 中使用 Flow 异步流下载文件 )
  20. 一起Oracle回收站过大引发的insert逻辑读过高故障

热门文章

  1. 《凤凰项目-一个IT运维从传奇故事》读后感+个人职业思考
  2. android蓝牙 助手源码,蓝牙串口助手(Android Studio源码)
  3. 网络安全—社会工程学
  4. 根据Excel记录生成Mysql和Hive建表语句
  5. 根据MySQL表结构批量自动生成HIVE建表语句
  6. UGUI适配问题 1.UI坐标与屏幕坐标转换
  7. sklearn 决策树例子_sklearn CART决策树分类
  8. CentOS7设置镜像源
  9. 拖机教程之ASTER v7超越BETWIN WIN7 VISTA教程(含ASTER v7和注册机下载)
  10. Vivado里程序固化详细教程