需求描述

多张判过分的试卷,通过demo来识别出每道题目扣分多少,将结果汇总到excel文件中。

个人想法

将图片按照题目划分矩形区域,识别出哪道题扣分,将结果统计出来。

步骤概述

图片处理

图片按照边框裁剪校正

保证初始输入的图片处理之后有基本相同的像素大小,按照试卷的边框进行裁剪,然后图片进行校正。

可参考链接

基于python+opencv的图像目标区域自动提取

图片增强

对校正好的图片进行处理,对比度增强、亮度增强、色度增强、锐度增强等。

# -*- coding: UTF-8 -*-
from PIL import Image
from PIL import ImageEnhance

# 原始图像
image = Image.open('fix.jpg')
image.show()
# 对比度增强
enh_con = ImageEnhance.Contrast(image)
contrast = 1.2
image_contrasted = enh_con.enhance(contrast)
image_contrasted.show()
# 亮度增强
enh_bri = ImageEnhance.Brightness(image)
brightness = 1.3
image_brightened = enh_bri.enhance(brightness)
image_brightened.show()
# 色度增强
enh_col = ImageEnhance.Color(image)
color = 1.5
image_colored = enh_col.enhance(color)
image_colored.show()
# 锐度增强
enh_sha = ImageEnhance.Sharpness(image)
sharpness = 3.0
image_sharped = enh_sha.enhance(sharpness)
image_sharped.show()
todo

图片增强的效果不是太好,考虑参考其它图片处理方法。 高斯模糊(todo)

图片分割

分割是比较简单,此图的难点在于如何确定哥哥题目区域,即各个题目的坐标。

此处我先均分,然后手动计算坐标给一张图片划分了矩形。(此处的基准模板图片可以考虑借助用户的帮助来生成,包括划分后区域题号的对应)

图片识别

识别切割出的题目区域中有没有扣分

选择题可以考虑只要是识别出了红色即算此题错误(todo)

客观题需要识别出所扣分数,初步打算是将扣分区域再分割出来,然后用手写体识别模型来识别扣分(准确率会高一些)。

目的是为了将扣分显示出来,所以题目信息不重要,图像处理,使得题目信息变模糊,红色加深。

提取目标图像参考下 投影法字符分割,或者是识别特定颜色并提取图像相关文章。

提取目标图像(扣分区域)

python 用opencv完成图像分割,并且完成每一个目标物的提取

使用Python和OpenCV检测图像中的物体并将物体裁剪下来

基于tensorflow、opencv的入门案例_发票识别三:发票数据集制作和cnn网络训练

百度OCR开源API

腾讯OCR ??

结果统计

题号和切割出的图片的对应关系,导出到excel不是难点。

重难点

  1. 图像的处理和高质量图片(测试图片)的获取
  2. 题目区域的划分(若扣分跨两个题目区域??)
  3. 题目和切割后图片对应关系
  4. 分割后的图片中是否包含扣分识别(选择题)
  5. 图片中扣分切割出并识别
  6. 识别的准确率问题

关键词参考

透视变换 图像二值化 图片膨胀腐蚀 高斯模糊 HSV openCV 图像切割投影法字符分割 特定区域ROI提取

可能用到的参考链接

Python+OpenCV识别颜色方块并提取轮廓

Python识别图片指定区域文字内容

Python+Opencv实现自动化阅卷

票据图片复杂表格框识别(票据单元格切割)

OpenCV图像分割python版

可能会用到的demo

  1. 识别图片中的红色

    import cv2
    import numpy as np

    src = cv2.imread("fix.jpg")
    cv2.namedWindow("input", cv2.WINDOW_AUTOSIZE)
    cv2.imshow("input", src)
    """
    提取图中的红色部分
    """
    hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
    low_hsv = np.array([0, 36, 10])
    high_hsv = np.array([10, 255, 255])
    mask = cv2.inRange(hsv, lowerb=low_hsv, upperb=high_hsv)
    cv2.imshow("pic", mask)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
  2. 手动给试卷题目划分区域

    # encoding:utf-8
    import cv2

    image = cv2.imread("origin.jpg")
    GrayImage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    print(GrayImage.shape)
    h, w = image.shape[:2]
    h, w = map(int, [h, w])
    print("高-宽", h, w)
    # # no flip
    draw_0 = cv2.rectangle(image, (10, 10), (500, 770), (0, 0, 255))
    cv2.rectangle(image, (510, 10), (1000, 770), (0, 0, 255))

    a = 0
    while a < h:
    a += 50
    # cv2.rectangle(image, (10, int(a)), (500, 770), (255, 0, 0), 1)
    # cv2.rectangle(image, (510, int(a)), (1000, 770), (255, 0, 0), 1)

    cv2.rectangle(image, (10, 270), (500, 770), (0, 0, 255))
    cv2.rectangle(image, (10, 313), (500, 770), (0, 0, 255))
    cv2.rectangle(image, (10, 365), (500, 770), (0, 0, 255))
    cv2.rectangle(image, (10, 415), (500, 770), (0, 0, 255))
    cv2.rectangle(image, (10, 470), (500, 770), (0, 0, 255))
    cv2.rectangle(image, (10, 505), (500, 770), (0, 0, 255))
    cv2.rectangle(image, (10, 615), (500, 770), (0, 0, 255))
    cv2.rectangle(image, (10, 670), (500, 770), (0, 0, 255))
    cv2.rectangle(image, (10, 725), (500, 770), (0, 0, 255))

    cv2.rectangle(image, (510, 10), (1000, 70), (0, 0, 255))
    cv2.rectangle(image, (510, 10), (1000, 370), (0, 0, 255))

    x, y, w, h = cv2.boundingRect(GrayImage)
    print(x, y, w, h)
    draw_1 = cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)

    # 参数:pt1,对角坐标1, pt2:对角坐标2
    # 注意这里根据两个点pt1,pt2,确定了对角线的位置,进而确定了矩形的位置
    # draw_0 = cv2.rectangle(image, (2 * w, 2 * h), (3 * w, 3 * h),(255, 255, 0), 2)

    # 将画过矩形框的图片保存到当前文件夹
    cv2.imwrite("changed.jpg", draw_0)

    # 显示画过矩形框的图片
    cv2.imshow("draw", draw_1)
    cv2.waitKey(0)
    cv2.destroyWindow("draw")
  1. 已知区域坐标,切割图片

    import cv2
    """
    特定区域图片裁切
    方法1:利用OpenCV对其进行裁剪
    方法2:使用Pillow对图片进行裁剪
    https://blog.csdn.net/hfutdog/article/details/82351549
    动态获取裁切点坐标
    (10, 270), (500, 770)
    (10, 313), (500, 770)
    (10, 365), (500, 770)
    (10, 415), (500, 770)
    (10, 470), (500, 770)
    (10, 505), (500, 770)
    """
    x0 = 10
    x1 = 500
    n = 770
    # 裁切点坐标 动态的坐标 图片以题号等命名
    y = [270, 313, 365, 415, 470, 505]
    img = cv2.imread("origin.jpg")
    print(img.shape)
    # 裁剪坐标为[y0:y1, x0:x1]
    for i in range(len(y)-1):
    cropped = img[y[i]:y[i + 1], x0:x1]
    cv2.imwrite("pic/" + str(i) + ".jpg", cropped)

    原始图片(测试用)

    origin.jpg

    DQc7z4.jpg