private void OCR()
        {
            //tessnet2.Tesseract ocr = new tessnet2.Tesseract();//声明一个OCR类
            tessnet2.Tesseract ocr = null;
            string defaultCharList = "0123456789";
            ocr = new tessnet2.Tesseract();
            ocr.SetVariable("tessedit_char_whitelist", defaultCharList);//设置识别变量,当前只能识别数字及英文字符。
            ocr.Init(Application.StartupPath + @"\tessdata", "eng", false); //应用当前语言包。注,Tessnet2是支持多国语的。语言包下载链接:http://code.google.com/p/tesseract-ocr/downloads/list            WebClient wc = new WebClient();
            byte[] oimg = wc.DownloadData(txtImageUrl.Text); // 自己修改成要识别的地址吧
            Bitmap bp = new Bitmap(new MemoryStream(oimg), true);//识别图像
            Bitmap bp2 = new Bitmap(new MemoryStream(oimg), true);
            picBox1.Image = bp2;
            //bp = ImageProcess.RemoveGreen(bp);
            //bp = ImageProcess.ToBW(bp);            picBox2.Image = bp;            List<tessnet2.Word> result = new List<tessnet2.Word>();
            string txt = "";            try
            {
                result = ocr.DoOCR(bp, Rectangle.Empty);//执行识别操作
                foreach (tessnet2.Word word in result)//遍历识别结果。
                {
                    txt += word.Text;
                }
            }
            catch (Exception ex)
            {            }
            
            textBox1.Text = txt;
        }
    }网上下的源码。每调用一次内存就增加2m。直到内存超限,应用程序自动关闭。求大神怎么解决

解决方案 »

  1.   

    WebClient wc = new WebClient();wc貌似没释放吧 close一下试试
      

  2.   

    切换 bitmap 的时候,记着把之前的 bitmap dispose 掉!
      

  3.   

    ocr = new tessnet2.Tesseract();应该包含有非托管资源,最好用using括起来,using(ocr = new tessnet2.Tesseract())
    {
    ...
    }然后WebClient也应该释放,最好也用using括起来,            picBox1.Image = bp2;
                picBox2.Image = bp;赋值之前也应该释放原来的bitmap,if (picBox1.Image!=null)
    {
    Bitmap toRemove=picBox1.Image;
    picBox1.Image=null;
    toRemove.Dispose();
    }
    if (picBox2.Image!=null)
    {
    Bitmap toRemove=picBox2.Image;
    picBox2.Image=null;
    toRemove.Dispose();
    }
    picBox1.Image = bp2;
    picBox2.Image = bp;
      

  4.   

    问题出在这段代码:
       try
                    {
                        result = ocr.DoOCR(bp, Rectangle.Empty);//执行识别操作
                        foreach (tessnet2.Word word in result)//遍历识别结果。
                        {
                            txt += word.Text;
                        }
                    }
                    catch (Exception ex)
                    {                }我去掉这段代码执行程序是每问题的。
      

  5.   

    拼接字符串的时候请不要用+=
    要用StringBuilder,去网上查查。
    ocr是什么东西我不懂,你自己看看是不是什么东西开启了为释放理论上将如果你的result如果不是很大应该到不了2M,如果你的result里面的对象tessnet2.Word 非常多就会达到2M甚至更多,所需要注意啊。
      

  6.   

    ocr  这个变量你找找有没资源释放的之类的函数。
      

  7.   

    ocr是个非托管的函数。里面可能有需要手动释放的地方或函数。
      

  8.   

     ocr.Dispose();这个是释放的方法,但是没有效果
      

  9.   

    不一定是这里的问题,也可能是 ocr.DoOCR内部才分配了非托管资源,解决方法还是要Dispose,要么你干完之后调用ocr.Dispose,要么用using,如果ocr没有Dispose方法那就没法解决问题了,不过你可以要求厂家把Dispose方法加上去,
    Quote: 引用 4 楼 sphinx1685 的回复:
    问题出在这段代码:
        try
                     {
                         result = ocr.DoOCR(bp, Rectangle.Empty);//执行识别操作
                         foreach (tessnet2.Word word in result)//遍历识别结果。
                         {
                             txt += word.Text;
                         }
                     }
                     catch (Exception ex)
                     {
     
                    }
     
    我去掉这段代码执行程序是每问题的。 
    Quote:
      

  10.   


    ocr有Dispose方法。但是我调用了没有作用。还是耗内存。最大的疑点就是这句了:ocr.DoOCR(bp, Rectangle.Empty);
    其他的应该都是没有问题的。
      

  11.   

    再不行你就每次调用完之后用GC.Collect(); 回收一个内存
      

  12.   

    用这个 GC.Collect(); 
    每次执行完,就强制回收下,
      

  13.   

    你再for循环上打一个断点,看看有没有运行到for循环,如果没有的话就是这一行代码ocr.DoOCR(bp, Rectangle.Empty);的问题咯。先定位问题再找解决方案!·
      

  14.   

    循环调用这个方法OCR()?没调用一次内存增加2M?那你没调用完一次的时候回收一下垃圾试试!
      

  15.   

    对于非托管资源,强制执行GC.Collect()也是没用的。
    如果确实像楼主说的那样,问题出在ocr的话,可尝试下面
       try
                    {
                        result = ocr.DoOCR(bp, Rectangle.Empty);//执行识别操作
                        foreach (tessnet2.Word word in result)//遍历识别结果。
                        {
                            txt += word.Text;
                        }
                    }
                    catch (Exception ex)
                    {                }
    finally
    {
        ocr.Dispose();
    }如果还没有效果,那就是ocr本事的问题:它内部使用的资源没有在Dispose()方法里释放掉
      

  16.   

    用 using()不用担心忘记回收的问题。
      

  17.   

    GC的定义:
          GC如其名,就是垃圾收集,当然这里仅就内存而言。Garbage Collector(垃圾收集器,在不至于混淆的情况下也成为GC)以应用程序的root为基础.
    GC实现原理:
          通过识别它们是否被引用来确定哪些对象是已经死亡的、哪些仍需要被使用。已经不再被应用程序的root或者别的对象所引用的对象就是已经死亡的对象,即所谓的垃圾,需要被回收。这就是GC工作的原理
    为了实现这个原理,GC有多种算法。比较常见的算法有Reference Counting,Mark Sweep,Copy Collection等等。目前主流的虚拟系统.NET CLR,Java VM和Rotor都是采用的Mark Sweep算法
    具体算法,我也不太了解.这里就不说了!
    先上代码:.NET的GC机制有这样两个问题:
    第一,GC只能回收内存中的托管对象资源,对于非托管对象例如:数据库连接,文件句柄关于很多直接和硬件打交道的资源,GC是不能涉及的。
    第二,GC并不是实时性的,这将会造成系统性能上的瓶颈和不确定性,因此.Net中GC会在某一个时间点去回收垃圾.class Program
         {
             static string name = "张三";
             static void Main(string[] args)
             {
                 //判断静态对象是否被回收
                 GC.Collect();//强制对所有代进行即时垃圾回收。 
                 WeakReference weakstatic = new WeakReference(name);//引用指定的对象初始化 WeakReference 类的新实例。 
                 Console.WriteLine("静态变量是否存活:" + weakstatic.IsAlive);
                 
                 //被引用的对象是否被回收
                 List<Person> persons = new List<Person>();
                 for (int i = 0; i < 9000; i++ ){
                     Person p = new Person();
                 }
                 GC.Collect();
                 WeakReference weakReference = new WeakReference(persons);
                 Console.WriteLine("被引用的对象是否存活:" + weakReference.IsAlive);
                 
                 //没有被引用的对象是否被回收
                 Person p1 = new Person();
                 WeakReference weakNo = new WeakReference(p1);
                 GC.Collect();
                 Console.WriteLine("没有被引用的对象是否存活:" + weakNo.IsAlive);
                 
                 /*
                  总结:
                  * 托管内存中的对象,只要有被引用到的地方,GC不会回收,
                  * 只要没有被任何地方引用的对象GC会回收,但是不是立即回收,GC会找个时间段统一回收
     */
                 Console.WriteLine("");
                 Console.WriteLine("解析:为什么没有被引用的对象是否被回收?是因为GC并不是实时性的,\n这将会造成系统性能上的瓶颈和不确定性,因此.Net中GC会在某一个时间点去回收垃圾。");
     
                 Console.ReadKey();
             }
         }
     
         class Person { }
    第三,关于非托管对象,如文件句柄,数据库连接等等,如何回收呢?
     
     上面都说到GC只能回收内存中的托管对象资源,对于非托管对象例如:数据库连接,文件句柄关于很多直接和硬件打交道的资源,GC是不能涉及的
     所以.Net有了IDisposable接口,IDisposable接口定义了Dispose方法,这个方法用来供程序员显式调用以释放非托管资源。使用using语句可以简化资源管理。
     using(){}自动帮我们调用Dispose 方法,和try{}catch(){}finally{file.Dispose()}差不多class Program
         {
             static void Main(string[] args)
             {
                 using (MyFile file = new MyFile()) {
                     file.OpenFile();
                 }
                 Console.ReadKey();
                 /*
                  总结:
                  * 非托管内存中的资源类,一般需要实现IDesposable接口
                  * 使用using(){},相当于try{}catch(){}finally{file.Dispose();}
                  * 使用了using 作用域,会自动去调用IDisposable的实现方法
                  * IDisposable的实现方法可以帮助调用Close的关闭方法。
     */
             }
         }
     
         class MyFile : IDisposable
         {
             public void OpenFile(){
                 Console.WriteLine("打开文件!");
             }
     
             public void Dispose(){
                 Close();
                 Console.WriteLine("释放文件句柄资源!");
             }
     
             public void Close(){
                 Console.WriteLine("关闭文件流");
             }
         }
      

  18.   

    上面写反了。
    不是Dispose调用Close,而是
    Close可以调用 Dispose
      

  19.   

    上面的没有搞懂楼主要的啥。
    一般的非托管的代码。都是不是dispose来释放的。
    一般有close,delete开头之类的函数用来释放的。楼主找找。
      

  20.   

        result = ocr.DoOCR(bp, Rectangle.Empty);//执行识别操作
    这行下面加
    bp.dispose();
    bp2.dispose();
    GC.Collect();如果还有问题那就只能去找ocr里面有没有Dispose,close,delete神马的了。
      

  21.   

    尽.net事, 听ocr.DoOCR的命.............
      

  22.   

    受教了。。其实 textbox 显示的值是不是也有限制哦?  一直往里面读入内容显示会不会导致错误呢。