从图像中提取奶牛编号
问题描述
我妈妈时不时地需要翻阅这些类型的照片以从图像中提取数字并将其重命名为数字.
every now and then my mom has to shift through these type of photos to extract the number from the image and rename it to the number.
我正在尝试使用 OpenCV、Python、Tesseract 来完成该过程.我真的很想用数字提取图像的一部分.我怎么能这样做?任何建议我都是 OpenCV 的新手.
I'm trying to use OpenCV, Python, Tesseract to get the process done. I'm really lost trying to extract the portion of the image with the numbers. How could I do this? Any suggestions i'm really new at OpenCV.
我尝试使用阈值和轮廓提取白色矩形板,但无济于事,因为我为阈值选择的 RGB 并不总是有效,我不知道如何选择轮廓.
I tried to extract the white rectangular board using thresholds and contours, but no avail because the RGB I choose for thresh doesn't always work and I don't know how to choose the contour.
看这篇论文http://yoni.wexlers.org/papers/2010TextDetection.pdf .看起来很有前途
Looking at this paper http://yoni.wexlers.org/papers/2010TextDetection.pdf . Looks prominisn
解决方案
我一直在看这个,一路上得到了一些灵感....
I have been having another look at this, and had a couple of inspirations along the way....
Tesseract 可以接受自定义字典,如果你再深入一点,似乎从 v3.0 开始,它接受命令行参数
digits
以使其仅识别数字 -似乎对您的需求有用.
Tesseract can accept custom dictionaries, and if you dig a little more, it appears that from v3.0, it accepts the command-line parameter
digits
to make it recognise digits only - seems a useful idea for your needs.
可能没有必要找到带有数字的板 - 使用不同的图像切片多次运行 Tesseract 并让它自己尝试可能会更容易,因为这是它应该做的做.
It may not be necessary to find the boards with the digits on - it may be easier to run Tesseract multiple times with various slices of the image and let it have a try itself as that is what it is supposed to do.
因此,我决定对图像进行预处理,将黑色 25% 以内的所有内容更改为纯黑色,并将其他所有内容更改为纯白色.这给出了这样的预处理图像:
So, I decided to preprocess the image by changing everything that is within 25% of black to pure black, and everything else to pure white. That gives pre-processed images like this:
接下来,我生成一系列图像并将它们传递给 Tesseract,一次一个.我决定假设数字可能在图像高度的 40% 到 10% 之间,所以我在图像高度的 40、30、20 和 10% 的条带上做了一个循环.然后,我以 20 步从上到下将条带从图像上向下滑动,将每个条带传递到 Tesseract,直到条带基本上穿过图像的底部.
Next, I generate a series of images and pass them, one at a time to Tesseract. I decided to assume that the digits are probably between 40% to 10% of the image height, so I made a loop over strips 40, 30, 20 and 10% of the image height. I then slide the strip down the image from top to bottom in 20 steps passing each strip to Tesseract, till the strip is essentially across the bottom of the image.
这是 40% 的片段 - 动画的每一帧都传递给 Tesseract:
Here are the 40% strips - each frame of the animation is passed to Tesseract:
这是 20% 的片段 - 动画的每一帧都传递给 Tesseract:
Here are the 20% strips - each frame of the animation is passed to Tesseract:
得到条带后,我很好地调整了它们的大小以适应 Tesseract 的最佳位置,并清除它们的噪音等.然后,我将它们传递到 Tesseract 并通过计算它找到的位数来粗略地评估识别的质量.最后,我按位数对输出进行排序 - 可能更多位数可能更好......
Having got the strips, I resize them nicely for Tesseract's sweet spot and clean them up from noise etc. Then, I pass them into Tesseract and assess the quality of the recognition, somewhat crudely, by counting the number of digits it found. Finally, I sort the output by number of digits - presumably more digits is maybe better...
有一些粗糙的边缘和细节,你可以用它来处理,但这是一个开始!
There are some rough edges and bits that you could dink around with, but it is a start!
#!/bin/bash
image=${1-c1.jpg}
# Make everything that is nearly black go fully black, everything else goes white. Median for noise
# convert -delay 500 c1.jpg c2.jpg c3.jpg -normalize -fuzz 25% -fill black -opaque black -fuzz 0 -fill white +opaque black -median 9 out.gif
convert "${image}" -normalize
-fuzz 25% -fill black -opaque black
-fuzz 0 -fill white +opaque black
-median 9 tmp_$$.png
# Get height of image - h
h=$(identify -format "%h" "${image}")
# Generate strips that are 40%, 30%, 20% and 10% of image height
for pc in 40 30 20 10; do
# Calculate height of this strip in pixels - sh
((sh=(h*pc)/100))
# Calculate offset from top of picture to top of bottom strip - omax
((omax=h-sh))
# Calculate step size, there will be 20 steps
((step=omax/20))
# Cut strips sh pixels high from the picture starting at top and working down in 20 steps
for (( off=0;off<$omax;off+=$step)) do
t=$(printf "%05d" $off)
# Extract strip and resize to 80 pixels tall for tesseract
convert tmp_$$.png -crop x${sh}+0+${off}
-resize x80 -median 3 -median 3 -median 3
-threshold 90% +repage slice_${pc}_${t}.png
# Run slice through tesseract, seeking only digits
tesseract slice_${pc}_${t}.png temp digits quiet
# Now try and assess quality of output :-) ... by counting number of digits
digits=$(tr -cd "[0-9]" < temp.txt)
ndigits=${#digits}
[ $ndigits -gt 0 ] && [ $ndigits -lt 6 ] && echo $ndigits:$digits
done
done | sort -n
Cow 618 的输出(第一个数字是找到的位数)
Output for Cow 618 (first number is the number of digits found)
2:11
2:11
3:573
5:33613 <--- not bad
Cow 2755 的输出(第一个数字是找到的位数)
Output for Cow 2755 (first number is the number of digits found)
2:51
3:071
3:191
3:517
4:2155 <--- pretty close
4:2755 <--- nailed that puppy :-)
4:2755 <--- nailed that puppy :-)
4:5212
5:12755 <--- pretty close
Cow 3174 的输出(第一个数字是找到的位数)
Output for Cow 3174 (first number is the number of digits found)
3:554
3:734
5:12732
5:31741 <--- pretty close
很酷的问题 - 谢谢!
Cool question - thank you!
相关文章