Java 大型二值图像数据集上的系数相关性-性能较慢

Java 大型二值图像数据集上的系数相关性-性能较慢,java,performance,ocr,correlation,coefficients,Java,Performance,Ocr,Correlation,Coefficients,我试图通过计算从图像中提取的字符与我预先存储在数据库中的每个字符之间的相关系数来构建OCR。我的实现基于Java,预存储的字符在应用程序开始时加载到ArrayList中,即 ArrayList<byte []> storedCharacters, extractedCharacters; storedCharacters = load_all_characters_from_database(); extractedCharacters = extract_characters_fr

我试图通过计算从图像中提取的字符与我预先存储在数据库中的每个字符之间的相关系数来构建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;
}
ArrayList存储的字符、提取的字符;
storedCharacters=从数据库()加载所有字符;
extractedCharacters=从图像()中提取字符;
//计算每个提取字符之间的系数
//以及数据库中的每个字符。
双maxCorr=-1;
for(字节[]extractedCharacter:extractedCharacters)
for(字节[]存储字符:存储字符)
{
corr=查找相关(提取字符、存储字符)
如果(corr>maxCorr)
maxCorr=corr;
}
...
...
公共双查找相关(字节[]提取字符,字节[]存储字符)
{
双磁极1,磁极2,corr=0;
for(int i=0;i
每个图像提取的字符数约为100-150个,但数据库中存储了15600个二进制字符。使用Intel i5 CPU,检查每个提取字符和每个存储字符之间的系数相关性会对性能产生影响,因为每个图像需要大约15-20秒才能完成。 有没有办法提高这个程序的速度,或者建议另一种方法来构建这个程序,从而带来类似的结果。(将每个字符与如此大的数据集进行比较得到的结果非常好)

先谢谢你

更新1
publicstaticvoidrun(){
ArrayList存储的字符、提取的字符;
storedCharacters=从数据库()加载所有字符;
extractedCharacters=从图像()中提取字符;
//计算每个提取字符之间的系数
//以及数据库中的每个字符。
计算格式(字符组、提取字符);
双maxCorr=-1;
for(字节[]extractedCharacter:extractedCharacters)
for(字节[]存储字符:存储字符)
{
corr=查找相关(提取字符、存储字符)
如果(corr>maxCorr)
maxCorr=corr;
}
}
}
私有静态双[]存储格式;
私有静态双[]抽取规范;
//二值图像间的相关性
公共静态双查找相关(字节[]arr1,字节[]arr2,int-strCharIndex,int-extCharNo){
最终整数点积=点积(arr1,arr2);
最终双精度corr=dotProduct*storedNorms[strCharIndex]*extractedNorms[extCharNo];
返回corr;
}
公共静态void计算格式(ArrayList storedCharacters、ArrayList extractedCharacters){
StoredForms=计算规范(storedCharacters);
ExtractedNormals=计算范数(extractedCharacters);
}
私有静态双[]计算规范(列表a){
最终双精度[]结果=新双精度[a.尺寸()];
对于(int i=0;i
如今,很难找到单核CPU(即使是在手机中)。由于任务很好地分开,所以只需几行就可以完成。所以我会努力的,尽管收获有限

如果你真的是说,那么像或这样的变换可能会有所帮助。它们当然适用于大图像,但对于您的12x16,我不确定

也许你的意思只是一个?也许你应该告诉我们

请注意,实际上您不需要计算相关性,大部分时间您只需要找出相关性是否大于阈值:

corr = findCorrelation(extractedCharacter, storedCharacter)
..... more code to check if this is the best match ......
这可能会导致一些优化或不优化,这取决于图像的外观

还请注意,一个简单的低级优化可以为您提供接近4的因子,如下所示。也许你真的应该告诉我们你在做什么

更新1 我猜由于循环中有三个乘积的计算,有足够的指令级并行性,因此不需要像中那样手动展开循环

但是,我看到这三个产品被计算了大约100*15600次,而其中只有一个依赖于
extractedCharacter
storedCharacter
。所以你可以计算

100 + 15600 + 100 * 15600
点积代替

 3 * 100 * 15600
这样你可以很容易地得到三的因子

或者不是。在这一步之后,在相关的步骤中会计算出一个和,上面链接的问题适用。它的解决方案也是如此(手动展开)

系数5.2

虽然
byte[]
非常紧凑,但计算需要将它们扩展到int,这需要花费一些时间,如我的演示所示。在计算所有相关性之前,将
字节[]
s转换为
int[]
s可以节省时间。更好的方法是利用这样一个事实,即
storedCharacters
的这种转换可以事先完成


手动循环展开两次有帮助,但展开更多则没有帮助。

您的问题相当模糊。无论如何,一种探索的方法是不尝试首先与“原型”字母匹配,然后只与与此类原型相关的字母进行比较。例如,如果一个字母非常接近
X
,并且与
a
非常不同,那么您只能将其与
X
X
Y
进行比较,而不与
s
进行比较。当然,找到l的集合
 3 * 100 * 15600