javascript - 如何检查文本覆盖的图像百分比?
问题描述
有没有办法以编程方式计算文本覆盖图像的百分比?我正在尝试在 node.js 或 python 中执行此操作,但似乎找不到任何执行此操作的内容 - 我找到了很多库,可让您分析文本和/或更改图像属性本身(tesseract最初看起来很有希望),但没有什么能给我一个区域或数量 - 通常只是文本本身。任何想法都将不胜感激,对我尝试过的代码缺乏感到抱歉,但在任何地方都找不到任何关于此的内容。
解决方案
这是使用 OpenCV 的阈值 + 轮廓过滤的潜在方法:
- 将图像转换为灰度和自适应阈值
- 使用定义的阈值查找轮廓并过滤以删除所有非文本轮廓
- 将非文本轮廓绘制到掩码上并按位异或仅获得文本
- 计算文本像素的百分比
由于您没有提供输入图像,因此我将使用教科书中的此示例图像。注意一些文字是彩色的,并且有一张图片来模拟带有文字的普通图像。
我们首先将图像转换为灰度和自适应阈值cv2.adaptiveThreshold()
以获得二值图像。
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,11,3)
接下来我们使用轮廓区域找到轮廓cv2.findContours()
并使用轮廓区域过滤cv2.contourArea()
。我们定义了一个picture_threshold
值,该值定义了非文本轮廓的阈值。本质上,这个值决定了如果轮廓太大,它一定是图片,所以我们想从图像中过滤掉这些轮廓。在这种情况下,我们将非文本轮廓定义为大于5%
图像大小的任何轮廓。这是一个不错的假设,因为单个单词不会大于1%
整个图像区域(除非它是徽标,但假设只是普通文本)。
阈值二值图像(左)和蒙版上过滤的非文本轮廓(右)
mask = thresh.copy()
mask = cv2.merge([mask,mask,mask])
picture_threshold = image.shape[0] * image.shape[1] * .05
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
if area < picture_threshold:
cv2.drawContours(mask, [c], -1, (0,0,0), -1)
为了去除不想要的轮廓,我们执行按位异或运算来获得我们过滤后的图像,其中只有文本。这是我们将计算文本像素百分比的图像。
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
result = cv2.bitwise_xor(thresh, mask)
由于我们只隔离了图像上的文本轮廓,因此我们只需计算图像上白色像素的数量cv2.countNonZero()
。我们可以通过除以图像的面积来获得文本像素的百分比。结果如下:
百分比:13.15%
text_pixels = cv2.countNonZero(result)
percentage = (text_pixels / (image.shape[0] * image.shape[1])) * 100
print('Percentage: {:.2f}%'.format(percentage))
完整的完整代码
import cv2
import numpy as np
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,11,3)
mask = thresh.copy()
mask = cv2.merge([mask,mask,mask])
picture_threshold = image.shape[0] * image.shape[1] * .05
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
if area < picture_threshold:
cv2.drawContours(mask, [c], -1, (0,0,0), -1)
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
result = cv2.bitwise_xor(thresh, mask)
text_pixels = cv2.countNonZero(result)
percentage = (text_pixels / (image.shape[0] * image.shape[1])) * 100
print('Percentage: {:.2f}%'.format(percentage))
cv2.imshow('thresh', thresh)
cv2.imshow('result', result)
cv2.imshow('mask', mask)
cv2.waitKey()
推荐阅读
- jquery - jQuery getElementByClassName 有效但并非总是如此
- php - 使用自定义 php mysql 查询从 wp 元值中获取值
- javascript - 不带表单标签的输入类型
- php - 当我单击主页中的链接时,如何从另一个 php 文件中调用模式
- jquery - CSS 在 Bootstrap 之前加载,导致元素混乱
- c - 当我处于无限while循环时如何使用malloc
- java - DAO 单元测试的日期转换
- javascript - 删除和添加类到模态内容元素
- c++ - 我应该如何构建 C++ 应用程序以分发到不同版本的 OS X/macOS?
- r - R将文件夹识别为文件