- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我试图从数百个包含死刑记录信息的 JPG 中提取文本; JPG 由德克萨斯州刑事司法部 (TDCJ) 主持。以下是删除了个人身份信息的示例代码段。
我已经确定下划线是正确 OCR 的障碍--如果我进入,截取一个子片段并手动涂白线,通过 pytesseract 生成 OCR非常好。但是有下划线,它非常糟糕。
如何才能最好地去除这些水平线?我尝试过的:
用 c++ 标记这个问题希望有人能帮忙翻译docs walkthrough的第5步到 Python。我已经尝试了一批转换,例如 Hugh Line Transform,但我在图书馆和我之前经验为零的区域中感到黑暗。
import cv2
# Inverted grayscale
img = cv2.imread('rsnippet.jpg', cv2.IMREAD_GRAYSCALE)
img = cv2.bitwise_not(img)
# Transform inverted grayscale to binary
th = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY, 15, -2)
# An alternative; Not sure if `th` or `th2` is optimal here
th2 = cv2.threshold(img, 170, 255, cv2.THRESH_BINARY)[1]
# Create corresponding structure element for horizontal lines.
# Start by cloning th/th2.
horiz = th.copy()
r, c = horiz.shape
# Lost after here - not understanding intuition behind sizing/partitioning
最佳答案
到目前为止,所有答案似乎都在使用形态学运算。这里有点不同。如果线条是水平的,这应该会产生相当好的结果。
为此,我使用了您的示例图片的一部分,如下所示。
加载图像,将其转换为灰度并反转。
import cv2
import numpy as np
import matplotlib.pyplot as plt
im = cv2.imread('sample.jpg')
gray = 255 - cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
反转灰度图:
如果您扫描此倒置图像中的一行,您会发现其轮廓看起来不同,具体取决于是否存在线条。
plt.figure(1)
plt.plot(gray[18, :] > 16, 'g-')
plt.axis([0, gray.shape[1], 0, 1.1])
plt.figure(2)
plt.plot(gray[36, :] > 16, 'r-')
plt.axis([0, gray.shape[1], 0, 1.1])
绿色是没有下划线的行,红色是有下划线的行。如果您对每个配置文件取平均值,您会发现红色配置文件的平均值更高。
因此,使用这种方法,您可以检测下划线并将其删除。
for row in range(gray.shape[0]):
avg = np.average(gray[row, :] > 16)
if avg > 0.9:
cv2.line(im, (0, row), (gray.shape[1]-1, row), (0, 0, 255))
cv2.line(gray, (0, row), (gray.shape[1]-1, row), (0, 0, 0), 1)
cv2.imshow("gray", 255 - gray)
cv2.imshow("im", im)
以下是检测到的红色下划线和清理后的图像。
清理后图像的tesseract输出:
Convthed as th(
shot once in the
she stepped fr<
brother-in-lawii
collect on life in
applied for man
to the scheme i|
使用部分图片的原因现在应该很清楚了。由于原始图像中的个人身份信息已被删除,因此阈值将不起作用。但是当你应用它进行处理时,这应该不是问题。有时您可能需要调整阈值 (16, 0.9)。
删除了部分字母并且仍然保留了一些微弱的线条,结果看起来不太好。如果我能改进它会更新。
更新:
Dis 一些改进;清理并链接字母的缺失部分。我已经评论了代码,所以我相信这个过程很清楚。您还可以检查生成的中间图像以了解它是如何工作的。结果稍微好一点。
清理后图像的tesseract输出:
Convicted as th(
shot once in the
she stepped fr<
brother-in-law. ‘
collect on life ix
applied for man
to the scheme i|
清理后图像的tesseract输出:
)r-hire of 29-year-old .
revolver in the garage ‘
red that the victim‘s h
{2000 to kill her. mum
250.000. Before the kil
If$| 50.000 each on bin
to police.
python 代码:
import cv2
import numpy as np
import matplotlib.pyplot as plt
im = cv2.imread('sample2.jpg')
gray = 255 - cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
# prepare a mask using Otsu threshold, then copy from original. this removes some noise
__, bw = cv2.threshold(cv2.dilate(gray, None), 128, 255, cv2.THRESH_BINARY or cv2.THRESH_OTSU)
gray = cv2.bitwise_and(gray, bw)
# make copy of the low-noise underlined image
grayu = gray.copy()
imcpy = im.copy()
# scan each row and remove lines
for row in range(gray.shape[0]):
avg = np.average(gray[row, :] > 16)
if avg > 0.9:
cv2.line(im, (0, row), (gray.shape[1]-1, row), (0, 0, 255))
cv2.line(gray, (0, row), (gray.shape[1]-1, row), (0, 0, 0), 1)
cont = gray.copy()
graycpy = gray.copy()
# after contour processing, the residual will contain small contours
residual = gray.copy()
# find contours
contours, hierarchy = cv2.findContours(cont, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):
# find the boundingbox of the contour
x, y, w, h = cv2.boundingRect(contours[i])
if 10 < h:
cv2.drawContours(im, contours, i, (0, 255, 0), -1)
# if boundingbox height is higher than threshold, remove the contour from residual image
cv2.drawContours(residual, contours, i, (0, 0, 0), -1)
else:
cv2.drawContours(im, contours, i, (255, 0, 0), -1)
# if boundingbox height is less than or equal to threshold, remove the contour gray image
cv2.drawContours(gray, contours, i, (0, 0, 0), -1)
# now the residual only contains small contours. open it to remove thin lines
st = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
residual = cv2.morphologyEx(residual, cv2.MORPH_OPEN, st, iterations=1)
# prepare a mask for residual components
__, residual = cv2.threshold(residual, 0, 255, cv2.THRESH_BINARY)
cv2.imshow("gray", gray)
cv2.imshow("residual", residual)
# combine the residuals. we still need to link the residuals
combined = cv2.bitwise_or(cv2.bitwise_and(graycpy, residual), gray)
# link the residuals
st = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (1, 7))
linked = cv2.morphologyEx(combined, cv2.MORPH_CLOSE, st, iterations=1)
cv2.imshow("linked", linked)
# prepare a msak from linked image
__, mask = cv2.threshold(linked, 0, 255, cv2.THRESH_BINARY)
# copy region from low-noise underlined image
clean = 255 - cv2.bitwise_and(grayu, mask)
cv2.imshow("clean", clean)
cv2.imshow("im", im)
关于python - 删除水平下划线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48327567/
执行此查询 INSERT INTO classes( '_fkUserID', 'date', 'time' ) VALUES ( '1', '2017-07-04', '8:15' ) 给
不知道它是否重复(无法找到要搜索的词,例如 “允许使用 java 字符”)。我在测试面试中遇到了这个问题: 考虑以下类: class _ {_ f; _(){}_(_ f){_ t = f; f =
我需要验证用户的屏幕名称以确保它不能有 多个连字符或下划线 我不希望人们的网名全是标点符号。 这是我到目前为止的验证: public boolean validateScreenName(String
我正在尝试检查我收到的新数据是否针对我持有的对象,我想知道的是,我正在发送的对象的键是否与我当前拥有的对象中的任何键匹配。 所以我捕获了一个像 myObj = [{"one": 1}, {"two":
这是我第一次使用下划线...我有这个简单的 json... "categories" : [ { "tag" : "cat1", "active" : true
一个很简单的问题: 为什么在WPF内容中看不到_(下划线)? 例如内容 显示为"testt"(未显示下划线)。 最佳答案 标签支持助记符(即您可以使用ctrl +(key)赋予它们焦点)。您可以使用
下面是我正在处理的简化逻辑,我想在数组中查找具有匹配位置(文件夹)的文件。 我能够使用普通的 JS 循环来实现此功能,您能建议更好/更简单/类似下划线的方法来实现此类功能吗? // source va
我正在尝试在对象的函数中查找和替换值 我的对象看起来像这样: var testStates = [{ "module": "module1", "customUrl": [
尝试让 _.uniq() 在以下结构上工作: [ {'x' : 1, 'y': 2}, {'x' : 1, 'y': 2}, {'x' : 2, 'y': 3}, {'
明白了: [{ "title": "qq", "dateValuePair": { "date": "2016-04-29T22:00:00.000Z", "va
我不知道这是否可能,但我试图做的是“清理”一个对象。基本想法是我有一个对象的表格(以 Angular ),然后单击我想添加一个新行(控制对象中的一个新项目,但我希望它没有值。我有下划线尝试一下。一些考
所以我有一大堆对象需要将其变成一个小对象。 它有 50-60 个对象,我需要过滤到一个新的对象数组中,其中只有 3 个。 所以看起来像 myOb = {{"ob1": 1},{"ob2": 1},{"
我有一个像这样的对象 - {"house" : red, "car" : green, "apple" : blue}; 并且正在发送另一个带有单个键/值的对象,如下所示 {"apple" : gre
我有一个包含多个对象的数组,例如 var val = [ _id: ["5412fc1bd123cf7016674a92", "5412cf270e9ca9b517b43ca3"],
所以我有一个对象列表,例如 var options = [{"car" : "red"},{"house": "green"},{"dog":"bark"}] 我正在尝试将其转换为一个值数组,
我正在尝试将此数组转换为对象。使用下划线,我想转换这个数组: [ { "id": "parentA", "children": [ { "nam
我正在尝试使用这样的链检索嵌套项目值。我正在遍历的对象如下所示: var testStates = [{ "module": "module1", "customUrl
我有一些内容可编辑的段落,我希望能够在双击时使某些单词加粗下划线。当我双击一个单词时,它会被选中,并显示一个包含 3 个选项的工具提示。但是,单击工具提示选项后,选择就会消失,并且文本不会发生任何更改
要在 CSS 中给文本加下划线,我们可以这样做: h3 {text-decoration:underline;} 然而,这只会强调包含在 h3 标签中的文本。如果想让下划线穿过页面怎么办? 谢谢 最佳
我正在尝试解决我的最后一个问题,但我仍然不知道如何解决它。我的任务是编写一个对数字进行排序的程序,但是:我们的导师给了我们一些处理数字的程序的额外要点,例如:000054667(实际上是 54667)
我是一名优秀的程序员,十分优秀!