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

     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.html
 
https://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 plt



plt.clf()
plt.figure(figsize=(10,8))



demo=Image.open('a.jpg')
h,w=demo.size

plt.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+=area
        lengths+=length
        left_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_box
        print('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的检测工作整体上来说偏简单化了,真正想要高精度的检测还是需要深度学习模型,比如:目标检测方法来实现的,后面有时间再做吧。

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

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 护眼 设计师:闪电赇 返回首页
实付 29.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值