Я пытаюсь создать 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 двоичных символов. Проверка коэффициента корреляции между каждым извлеченным символом и каждым сохраненным символом влияет на производительность, поскольку для завершения каждого изображения требуется около 15-20 секунд с процессором Intel i5. Есть ли способ улучшить скорость этой программы или предложить другой путь построения, дающий аналогичные результаты. (Результаты, полученные при сравнении каждого символа с таким большим набором данных, довольно хороши).
заранее спасибо
ОБНОВЛЕНИЕ 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
. Конечно, найти набор букв и его лучший прототип — задача нетривиальная. - person SJuan76   schedule 14.05.2014findCorrelation
. Можно было бы дать более целенаправленные советы и предложения, если бы вы предоставили код этого метода. В противном случае можно давать только общие утверждения, такие как оптимизация высокого уровня (многопоточность, как было упомянуто), или подсказки, относящиеся к самому подходу (т. сложно, если вы не описываете подход более подробно. - person Marco13   schedule 14.05.2014findCorrelation
). На этом уровне можно было только распараллелить (что может и стоит, но ускорение ограничено количеством ядер). - person maaartinus   schedule 14.05.2014i
) для двумерного массива, аj
не определен. Так что я не уверен, что происходит. В любом случае, он не может скомпилироваться. Если вы действительно обрабатываете двумерный массив, преобразуйте его в одномерный и наслаждайтесь ускорением. - person maaartinus   schedule 15.05.2014x
иy
? Нет, он просто проходит через все пиксели 3. Таким образом, для скорости одномерный массив лучше. 4. Даже для вычислений, требующих 2D-доступа, можно использовать 1D-макет. Умножение составляет всего 3 цикла, промах кэша L1 может быть 10. В цикле умножение оптимизируется. - person maaartinus   schedule 17.05.2014