C#托管代码优化 我有一个C++ C++ DLL,我在C语言应用中使用。DLL正在处理大量图像(数千个),并使用OCR从中提取文本;尽管我知道OCR处理会消耗大量CPU,但我想知道是否有可能优化代码以获得更好的性能

C#托管代码优化 我有一个C++ C++ DLL,我在C语言应用中使用。DLL正在处理大量图像(数千个),并使用OCR从中提取文本;尽管我知道OCR处理会消耗大量CPU,但我想知道是否有可能优化代码以获得更好的性能,c#,c++,pinvoke,C#,C++,Pinvoke,目前,解析大约15页PNG页面需要一分钟。我想把时间缩短到30-40秒左右 C++代码:< /强> char* OCRWrapper::GetUTF8Text(char* path, char* lang, char* imgPath) { char* imageText; tesseract::TessBaseAPI *api = new tesseract::TessBaseAPI();

目前,解析大约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#方法。OCR对象是实际调用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);
        }
    }
如果你需要更多的细节,请告诉我

建议人们并行运行它的可执行文件(即,暗示它是单线程的)

您可以尝试使用
Parallel.For
替换
For
循环,看看是否能从中快速获得胜利

编辑:他们已经迁移到GitHub,新的FAQ建议

让Tesseract生成一页PDF,您将获得更好的结果 文件并行,然后在末尾将它们拼接在一起


您是否分析了代码以确定瓶颈在哪里?如果是这样的话,你的大部分时间都花在哪里了?是的,这是可能的。不,我不会为你做的。你甚至没有任何要求。“足够快”有多快?@丹布莱恩特:我该怎么做?我真的不知道。@EdS:我已经更新了这个问题。希望这能有所帮助。知道总时间并不能说明什么,您应该衡量流程执行的不同阶段。只有通过粒度测量,您才能知道瓶颈在哪里,从而提高性能。输入代码中分布的测量点,并定位第一次处理成本较高的点。谢谢,这大大提高了性能。哪一个?parallel for,还是PDF技巧?我添加了parallel.ForEach而不是循环,以更快地提取文本。我没有尝试过PDF部分,因为我不希望Tesseract生成PDF页面,因为我已经有了PDF。
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;
                }
            }
        }