【发布时间】:2014-05-14 07:00:21
【问题描述】:
我正在尝试通过计算从图像中提取的字符与我预先存储在数据库中的每个字符之间的系数相关性来构建 OCR。我的实现基于 Java,并且在应用程序开始时将预存储的字符加载到 ArrayList 中,即
ArrayList<byte []> storedCharacters, extractedCharacters;
storedCharacters = load_all_characters_from_database();
extractedCharacters = extract_characters_from_image();
// Calculate the coefficent between every extracted character
// and every character in database.
double maxCorr = -1;
for(byte [] extractedCharacter : extractedCharacters)
for(byte [] storedCharacter : storedCharactes)
{
corr = findCorrelation(extractedCharacter, storedCharacter)
if (corr > maxCorr)
maxCorr = corr;
}
...
...
public double findCorrelation(byte [] extractedCharacter, byte [] storedCharacter)
{
double mag1, mag2, corr = 0;
for(int i=0; i < extractedCharacter.length; i++)
{
mag1 += extractedCharacter[i] * extractedCharacter[i];
mag2 += storedCharacter[i] * storedCharacter[i];
corr += extractedCharacter[i] * storedCharacter[i];
} // for
corr /= Math.sqrt(mag1*mag2);
return corr;
}
每张图像提取的字符数约为 100-150 个,但数据库中有 15600 个存储的二进制字符。检查每个提取的字符和每个存储的字符之间的系数相关性会对性能产生影响,因为使用 Intel i5 CPU 大约需要 15-20 秒才能完成每个图像。 有没有办法提高这个程序的速度,或者提出另一种构建这个程序的方法,带来类似的结果。 (将每个字符与如此大的数据集进行比较产生的结果非常好)。
提前谢谢你
更新 1
public static void run() {
ArrayList<byte []> storedCharacters, extractedCharacters;
storedCharacters = load_all_characters_from_database();
extractedCharacters = extract_characters_from_image();
// Calculate the coefficent between every extracted character
// and every character in database.
computeNorms(charComps, extractedCharacters);
double maxCorr = -1;
for(byte [] extractedCharacter : extractedCharacters)
for(byte [] storedCharacter : storedCharactes)
{
corr = findCorrelation(extractedCharacter, storedCharacter)
if (corr > maxCorr)
maxCorr = corr;
}
}
}
private static double[] storedNorms;
private static double[] extractedNorms;
// Correlation between to binary images
public static double findCorrelation(byte[] arr1, byte[] arr2, int strCharIndex, int extCharNo){
final int dotProduct = dotProduct(arr1, arr2);
final double corr = dotProduct * storedNorms[strCharIndex] * extractedNorms[extCharNo];
return corr;
}
public static void computeNorms(ArrayList<byte[]> storedCharacters, ArrayList<byte[]> extractedCharacters) {
storedNorms = computeInvNorms(storedCharacters);
extractedNorms = computeInvNorms(extractedCharacters);
}
private static double[] computeInvNorms(List<byte []> a) {
final double[] result = new double[a.size()];
for (int i=0; i < result.length; ++i)
result[i] = 1 / Math.sqrt(dotProduct(a.get(i), a.get(i)));
return result;
}
private static int dotProduct(byte[] arr1, byte[] arr2) {
int dotProduct = 0;
for(int i = 0; i< arr1.length; i++)
dotProduct += arr1[i] * arr2[i];
return dotProduct;
}
【问题讨论】:
-
你的问题很模糊。无论如何,探索的方法不是先尝试与“原型”字母匹配,然后仅与与此类原型相关的字母进行比较。例如,如果一个字母与
X非常接近而与a非常不同,那么您只需将其与x、X、Y进行比较,而不是与s进行比较。当然,找到字母集及其最佳“原型”并非易事。 -
你的字节数组有多大?您可以像 SJuan76 建议的那样为初步测试准备一个“低分辨率”模型(较小的阵列)
-
你可以使用多个线程(我认为 i5 允许 4 个线程)。
-
如果我理解正确的话,瓶颈是
findCorrelation调用的循环。如果您提供此方法的代码,可以提供更集中的提示和建议。否则,只能给出一般性陈述,例如“高级”优化(如前所述的多线程),或引用方法本身的提示(即是否可以通过某种散列或启发式算法进行优化) - 但是只要您不更详细地描述该方法,后者就很困难。 -
您显示的 sn-p 是未优化的部分。 您隐藏的内容可能会有所改进(即
findCorrelation)。在这个级别,您只能并行化(这可能是值得的,但加速受到内核数量的限制)。
标签: java performance ocr correlation coefficients