2015-11-30 3 views
-2

У меня есть управляемая C++ DLL, которую я использую в своем приложении C#. DLL обрабатывает множество изображений (тысячи) и использует OCR для извлечения текста из него; Несмотря на то, что я знаю, что OCR Processing потребляет много CPU, мне было интересно, можно ли оптимизировать код для повышения производительности.Оптимизация управляемого кода на C#

В настоящее время требуется разобрать минуту. 15 страниц PNG-страниц. Я бы спустился примерно до 30-40 секунд.

C++ Код:

 char* OCRWrapper::GetUTF8Text(char* path, char* lang, char* imgPath) 
     { 
      char* imageText; 
      tesseract::TessBaseAPI *api = new tesseract::TessBaseAPI(); 

      if (api->Init(path, lang)) { 
       fprintf(stderr, "Could not initialize tesseract. Incorrect datapath or incorrect lanauge\n"); /*This should throw an error to the caller*/ 
       exit(1); 
      } 

      /*Open a reference to the imagepath*/ 
      Pix *image = pixRead(imgPath); 

      /*Read the image object;*/ 
      api->SetImage(image); 

      // Get OCR result 
      imageText = api->GetUTF8Text(); 

      /*writeToFile(outText);*/ 
      /*printf("OCR output:\n%s", imageText);*/ 

      /*Destroy the text*/ 
      api->End(); 

      pixDestroy(&image); 
      /*std::string x = std::string(imageText);*/ 

      return imageText; 
     } 

: C# метод, который создает экземпляр класса OCROBject. OCRObject - это класс, фактически вызывающий DLL, см. Ниже этот метод.

private void GetTextFromSavedImages(List<string> imagesPath) 
    { 
     try 
     { 
      StringBuilder allPagesText = new StringBuilder(); 
      OCRObject ocr = new OCRObject(this.dbHandler.GetApplicationSetting(this.m_ProfileName, "TesseractLanguage").ApplicationSettingValue, this.dbHandler.GetApplicationSetting(this.m_ProfileName, "TesseractConfigurationDataPath").ApplicationSettingValue); //Settings.Default.TesseractConfigurationDataPath 
      for (int i = 0; i < imagesPath.Count; i++) 
      { 

       string pageText = ocr.GetOCRText(imagesPath[i]); 
       this.m_pdfDictionary.Add(i + 1, pageText); 
       allPagesText.Append(pageText); 
      } 
      this.AllPageText = allPagesText.ToString(); 
     } 
     catch (Exception ex) 
     { 
      Logger.Log(ex.ToString(), LogInformationType.Error); 
     } 
    } 

И, наконец, OcrObject Класс:

public class OCRObject 
     { 
      private string m_tessLanguage; 
      private string m_tessConfPath; 
      [DllImport(@"\OCR\OCR.dll", EntryPoint = "GetUTF8Text", CallingConvention = CallingConvention.Cdecl)] 
      private static extern IntPtr GetUTF8Text(string path, string lang, string imgPath); 

      public OCRObject(string language, string tessConfPath) 
      { 
       if (string.IsNullOrEmpty(language)) 
       { 
        throw new ArgumentException("Tesseract language is null or empty."); 
       } 
       if (!System.IO.Directory.Exists(tessConfPath)) 
       { 
        throw new DirectoryNotFoundException("Could not find directory => " + tessConfPath); 
       }  
       this.m_tessLanguage = language; 
       this.m_tessConfPath = tessConfPath; 
      }  
      public string GetOCRText(string imagePath) 
      { 
       return this.StringFromNativeUtf8(GetUTF8Text(this.m_tessConfPath, this.m_tessLanguage, imagePath)); 
      } 

      private string StringFromNativeUtf8(IntPtr nativeUtf8) 
      { 
       try 
       { 
        int len = 0; 
        if (nativeUtf8 == IntPtr.Zero) 
        { 
         return string.Empty; 
        } 
        while (Marshal.ReadByte(nativeUtf8, len) != 0) ++len; 
        byte[] buffer = new byte[len]; 
        Marshal.Copy(nativeUtf8, buffer, 0, buffer.Length); 
        //GC.Collect(GC.MaxGeneration, GCCollectionMode.Optimized); /*If this help???*/ 
        string text = Encoding.UTF8.GetString(buffer); 
        return text; 
       } 
       catch 
       { 
        return string.Empty; 
       } 
      } 
     } 

Пожалуйста, дайте мне знать, если вам нужно больше информации.

+1

Профилировали ли вы код, чтобы определить, где находится ваше узкое место? Если да, то где вы тратите большую часть времени? –

+0

Да, возможно, это возможно. Нет, я не собираюсь делать это за вас. У вас даже нет никаких требований здесь. Как быстро «достаточно быстро»? –

+0

@DanBryant: Как мне это сделать? Я действительно не знаю. – JohnJackson

ответ

0

Tesseract FAQ предложил, чтобы люди выполняли его исполняемый файл параллельно (т. Е. Подразумевая, что он однопоточный).

Возможно, вы можете попробовать использовать Parallel.For, чтобы заменить петлю for, и посмотреть, сможете ли вы получить от нее быстрый и грязный выигрыш.

Edit: Они переехали в GitHub, и новый FAQ предложил

Вы получите лучшие результаты, имеющим Тессеракт производить один страницу PDF файлов параллельно, а затем сращивания их вместе в конце

+0

Спасибо, что улучшили производительность. – JohnJackson

+0

Какой? Параллель или трюк PDF? – NPras

+0

Я добавил Parallel.ForEach вместо цикла, чтобы извлечь текст намного быстрее. Я не пробовал часть PDF, так как я не хочу, чтобы Tesseract создавал PDF-страницы, поскольку у меня уже есть PDF. – JohnJackson

Смежные вопросы