C# 无法使EmguCV OpenCV正常工作

C# 无法使EmguCV OpenCV正常工作,c#,opencv,classification,svm,emgucv,C#,Opencv,Classification,Svm,Emgucv,我正在努力学习弓对象分类。我已尝试实施《第8章》(第148页)一书中给出的示例 当我在训练阶段将SVM保存到文件中,并在分类阶段读取它们时,结果完全不同。(如果该行 svm=notFromFile[category];被删除,结果是错误的;如果没有,则使用本书提供的数据集成功。) 当我用一些较大的数据集尝试这段代码时,我有时会在Emgu.CV.World.dll中为行bowDescriptorExtractor.Compute(frame_g,kp,img)得到以下异常:System.Acce

我正在努力学习弓对象分类。我已尝试实施《第8章》(第148页)一书中给出的示例

  • 当我在训练阶段将SVM保存到文件中,并在分类阶段读取它们时,结果完全不同。(如果该行
    svm=notFromFile[category];
    被删除,结果是错误的;如果没有,则使用本书提供的数据集成功。)
  • 当我用一些较大的数据集尝试这段代码时,我有时会在Emgu.CV.World.dll中为行
    bowDescriptorExtractor.Compute(frame_g,kp,img)得到以下异常:System.AccessViolationException'和应用程序关闭。这是无法处理的
我试过很多东西,但都想不出来。我们非常感谢您提出任何建议,说明为什么会发生这些情况,以及如何解决这些问题

我使用的是emgucv windesktop 3.1.0.2504

我的实施:

internal class Categorizer3 : ICategorizer
    {
        public string Name
        {
            get
            {
                return "Categorizer3";
            }
        }

        public bool Train()
        {
            try
            {
                initDir();
                Feature2D descriptorExtractor;
                Feature2D featureDetector;
                List<Mat> templates;
                BOWKMeansTrainer bowtrainer;
                BOWImgDescriptorExtractor bowDescriptorExtractor;
                init(out descriptorExtractor, out featureDetector, out templates, out bowtrainer, out bowDescriptorExtractor);

                List<Tuple<string, Mat>> train_set;
                List<string> category_names;
                make_train_set(out train_set, out category_names);

                Mat vocab;
                build_vocab(descriptorExtractor, featureDetector, templates, bowtrainer, out vocab);

                bowDescriptorExtractor.SetVocabulary(vocab);

                Dictionary<string, Mat> positive_data;
                Dictionary<string, Mat> negative_data;
                make_pos_neg(train_set, bowDescriptorExtractor, featureDetector, category_names, out positive_data, out negative_data);

                this.train_classifiers(category_names, positive_data, negative_data);

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        public event TrainedEventHandler Trained;
        protected void OnTrained(string fn)
        {
            if (this.Trained != null)
                this.Trained(fn);
        }
        public Categorizer3()
        {
        }
        private Feature2D create_FeatureDetector()
        {
            return new SURF(500);
            //return new KAZE();
            //return new SIFT();
            //return new Freak();
        }
        private BOWImgDescriptorExtractor create_bowDescriptorExtractor(Feature2D descriptorExtractor)
        {
            LinearIndexParams ip = new LinearIndexParams();
            SearchParams sp = new SearchParams();
            var descriptorMatcher = new FlannBasedMatcher(ip, sp);

            return new BOWImgDescriptorExtractor(descriptorExtractor, descriptorMatcher);
        }
        private void init(out Feature2D descriptorExtractor, out Feature2D featureDetector, out List<Mat> templates, out BOWKMeansTrainer bowtrainer, out BOWImgDescriptorExtractor bowDescriptorExtractor)
        {
            int clusters = 1000;
            featureDetector = create_FeatureDetector();

            MCvTermCriteria term = new MCvTermCriteria(10000, 0.0001d);
            term.Type = TermCritType.Iter | TermCritType.Eps;
            bowtrainer = new BOWKMeansTrainer(clusters, term, 5, Emgu.CV.CvEnum.KMeansInitType.PPCenters);//****


            BFMatcher matcher = new BFMatcher(DistanceType.L1);//****
            descriptorExtractor = featureDetector;//******

            bowDescriptorExtractor = create_bowDescriptorExtractor(descriptorExtractor);


            templates = new List<Mat>();
            string TEMPLATE_FOLDER = "C:\\Emgu\\book\\practical-opencv\\code\\src\\chapter8\\code8-5\\data\\templates";
            //string TEMPLATE_FOLDER = "C:\\Emgu\\book\\practical-opencv\\code\\src\\chapter8\\code8-5\\data\\train_images";
            foreach (var filename in Directory.GetFiles(TEMPLATE_FOLDER, "*", SearchOption.AllDirectories))
            {
                templates.Add(GetMat(filename, true));
                this.OnTrained(filename);
            }
        }


        void make_train_set(out List<Tuple<string, Mat>> train_set, out List<string> category_names)
        {
            string TRAIN_FOLDER = "C:\\Emgu\\book\\practical-opencv\\code\\src\\chapter8\\code8-5\\data\\train_images";

            category_names = new List<string>();
            train_set = new List<Tuple<string, Mat>>();
            foreach (var dir in Directory.GetDirectories(TRAIN_FOLDER))
            {
                // Get category name from name of the folder
                string category = new DirectoryInfo(dir).Name;
                category_names.Add(category);
                foreach (var filename in Directory.GetFiles(dir))
                {     
                    train_set.Add(new Tuple<string, Mat>(category, GetMat(filename, true)));
                    this.OnTrained(filename);
                }
            }
        }

        void build_vocab(Feature2D descriptorExtractor, Feature2D featureDetector, List<Mat> templates, BOWKMeansTrainer bowtrainer, out Mat vocab)
        {
            Mat vocab_descriptors = new Mat();
            foreach (Mat templ in templates)
            {
                Mat desc = new Mat();
                VectorOfKeyPoint kp = new VectorOfKeyPoint(featureDetector.Detect(templ));
                descriptorExtractor.Compute(templ, kp, desc);
                vocab_descriptors.PushBack(desc);
            }

            bowtrainer.Add(vocab_descriptors);
            vocab = new Mat();
            bowtrainer.Cluster(vocab);

            string fn = getVocabularyFileName();
            using (FileStorage fs = new FileStorage(fn, FileStorage.Mode.Write))
            {
                fs.Write(vocab, "vocab");
                fs.ReleaseAndGetString();
            }
        }

        void make_pos_neg(List<Tuple<string, Mat>> train_set, BOWImgDescriptorExtractor bowDescriptorExtractor, Feature2D featureDetector, List<string> category_names,
            out Dictionary<string, Mat> positive_data, out Dictionary<string, Mat> negative_data)
        {
            positive_data = new Dictionary<string, Mat>();
            negative_data = new Dictionary<string, Mat>();

            foreach (var tu in train_set)
            {
                string category = tu.Item1;
                Mat im = tu.Item2;
                Mat feat = new Mat();

                VectorOfKeyPoint kp = new VectorOfKeyPoint(featureDetector.Detect(im));
                bowDescriptorExtractor.Compute(im, kp, feat);

                for (int cat_index = 0; cat_index < category_names.Count; cat_index++)
                {
                    string check_category = category_names[cat_index];
                    if (check_category.CompareTo(category) == 0)
                    {
                        if (!positive_data.ContainsKey(check_category))
                            positive_data[check_category] = new Mat();
                        positive_data[check_category].PushBack(feat);
                    }
                    else
                    {
                        if (!negative_data.ContainsKey(check_category))
                            negative_data[check_category] = new Mat();
                        negative_data[check_category].PushBack(feat);
                    }
                }
            }
        }
        void train_classifiers(List<string> category_names, Dictionary<string, Mat> positive_data, Dictionary<string, Mat> negative_data)
        { 
            for (int i = 0; i < category_names.Count; i++)
            {
                string category = category_names[i];

                // Postive training data has labels 1
                Mat train_data = positive_data[category];
                Mat train_labels = new Mat(train_data.Rows, 1, DepthType.Cv32S, 1);
                {
                    for (int col = 0; col < train_labels.Cols; col++)
                        for (int row = 0; row < train_labels.Rows; row++)
                            train_labels.SetValue(row, col, (int)1);
                    train_labels.SetTo(new MCvScalar(1));


                    // Negative training data has labels 0
                    train_data.PushBack(negative_data[category]);
                    Mat m = new Mat(negative_data[category].Rows, 1, DepthType.Cv32S, 1);
                    {
                        for (int col = 0; col < m.Cols; col++)
                            for (int row = 0; row < m.Rows; row++)
                                m.SetValue(row, col, (int)0);
                        m.SetTo(new MCvScalar(0));

                        train_labels.PushBack(m);
                    }

                    SVM svm = new SVM();
                    svm.C = 312.5;
                    svm.Gamma = 0.50625000000000009;
                    svm.SetKernel(SVM.SvmKernelType.Rbf);
                    svm.Type = SVM.SvmType.CSvc;

                    svm.Train(train_data, Emgu.CV.ML.MlEnum.DataLayoutType.RowSample, train_labels);

                    var fn = getSVMFileName(category);
                    svm.SaveSVMToFile(fn);

                    notFromFile[category] = svm;
                }
            }
        }
        Dictionary<string, SVM> notFromFile = new Dictionary<string, SVM>();//****


        private void initDir()
        {
            var dir = getSaveDir();
            if (Directory.Exists(dir))
                foreach (var fn in Directory.GetFiles(dir))
                    File.Delete(fn);
        }
        private string getSaveDir()
        {
            string dir = Path.Combine(Path.GetTempPath(), "Dece", "SVMS");
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);
            return dir;
        }
        private string getSVMFileName(string category)
        {
            return Path.Combine(getSaveDir(), category + ".svm");
        }
        private string getVocabularyFileName()
        {
            return Path.Combine(getSaveDir(), "vocabulary.voc");
        }


        //[HandleProcessCorruptedStateExceptions]
        public IEnumerable<ImageInfo> Categorize(IEnumerable<string> imageFileNames)
        {   
            var featureDetector = create_FeatureDetector();
            var bowDescriptorExtractor = create_bowDescriptorExtractor(featureDetector);

            Mat vocab = new Mat();
            using (var fs = new FileStorage(getVocabularyFileName(), FileStorage.Mode.Read))
                fs["vocab"].ReadMat(vocab);


            bowDescriptorExtractor.SetVocabulary(vocab);

            Dictionary<string, string> svms = new Dictionary<string, string>();
            foreach (var xml in Directory.GetFiles(getSaveDir(), "*.svm"))
                svms.Add(Path.GetFileNameWithoutExtension(xml), xml);


            Dictionary<string, SVM> dic = new Dictionary<string, SVM>();

            foreach (var fn in imageFileNames)
            {
                string scoreTxt = Environment.NewLine;
                float score = float.MaxValue;
                //float score = float.MinValue;
                string cat = "";

                try
                {
                    using (Mat frame_g = GetMat(fn, false))
                    {
                        using (Mat img = new Mat())
                        {
                            VectorOfKeyPoint kp = new VectorOfKeyPoint(featureDetector.Detect(frame_g));

                            bowDescriptorExtractor.Compute(frame_g, kp, img);

                            foreach (var category in svms.Keys)
                            {
                                SVM svm = null;
                                if (!dic.ContainsKey(category))
                                {
                                    string svmFn = svms[category];
                                    svm = new SVM();
                                    svm.LoadSVMFromFile(svmFn);
                                    dic[category] = svm;
                                }
                                else
                                    svm = dic[category];
                                svm = notFromFile[category];//*************

                                float classVal = svm.Predict(img, null);
                                float scoreVal = svm.Predict(img, null, 1);
                                //float signMul = (classVal < 0) == (scoreVal < 0) ? 1f : -1f;
                                //float score1 = signMul * scoreVal;

                                scoreTxt += string.Format("{0}-{1}: {2}{3}", category, classVal.ToString(), scoreVal.ToString("N3"), Environment.NewLine);

                                if (scoreVal < score)
                                {
                                    score = scoreVal;
                                    cat = category;
                                }
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    score = 0f;
                    cat = "hata";
                }
                if (string.IsNullOrEmpty(cat))
                    score = 0f;
                yield return new ImageInfo(fn, cat, scoreTxt);
            }
        }


        private static object matLocker = new object();
        public Mat GetMat(string fn, bool train)
        {
            lock (matLocker)
            {
                var mat = new Mat(fn, ImreadModes.Color);
                var mat2 = new Mat();
                mat.ConvertTo(mat2, DepthType.Cv8U);
                return mat2;
            }
        }
    }
内部类分类程序3:ICategorizer
{
公共字符串名
{
得到
{
返回“分类程序3”;
}
}
公共列车
{
尝试
{
initDir();
特征2D描述符;
特征二维特征检测器;
列出模板;
弓箭教练;
BOWIMGDESCRIPTOREXTRATOR BOWIMGDESCRIPTOREXTRATOR;
初始(输出描述符牵引器、输出特征检测器、输出模板、输出弓箭训练器、输出弓箭描述符牵引器);
列出列车组;
列出类别名称;
制作列车组(列车组、类别名称);
Mat vocab;
构建vocab(描述符、特征检测器、模板、弓箭训练器、输出vocab);
bowDescriptorExtractor.集合词汇表(vocab);
字典正相关数据;
字典否定数据;
使位置为负(列车组、船首描述符牵引车、特征检测器、类别名称、输出正数据、输出负数据);
训练分类器(类别名称、正数据、负数据);
返回true;
}
捕获(例外)
{
返回false;
}
}
接受公共活动培训的志愿者;
受保护的未约束的空(字符串fn)
{
如果(this.Trained!=null)
这是经过训练的(fn);
}
公共分类程序3()
{
}
专用功能2D创建_功能检测器()
{
返回新的SURF(500);
//返回新的KAZE();
//返回新的SIFT();
//返回新怪物();
}
专用BOWImgDescriptorExtractor创建_bowDescriptorExtractor(功能2D descriptorExtractor)
{
LinearIndexParams ip=新的LinearIndexParams();
SearchParams sp=新的SearchParams();
var descriptorMatcher=新法兰基匹配器(ip,sp);
返回新的BOWImgDescriptorExtractor(描述符Extractor,描述符Formatcher);
}
私有void init(out Feature2D descriptor、out Feature2D featureDetector、out List模板、out bowkmeanfilter bowtrainer、out bowimgdescriptor extractor bowdescriptor rextractor)
{
int集群=1000;
featureDetector=创建_featureDetector();
MCvTermCriteria术语=新的MCvTermCriteria(10000,0.0001d);
term.Type=TermCritType.Iter | TermCritType.Eps;
bowtrainer=新的BowKMeanFilter(集群,术语,5,Emgu.CvEnum.KMeansInitType.PPCenters)//****
BFMatcher matcher=新的BFMatcher(DistanceType.L1)//****
描述符X=特征检测器//******
bowDescriptorExtractor=创建_bowDescriptorExtractor(descriptorExtractor);
模板=新列表();
字符串模板\u FOLDER=“C:\\Emgu\\book\\practical opencv\\code\\src\\chapter8\\code 8-5\\data\\templates”;
//字符串模板\u FOLDER=“C:\\Emgu\\book\\practical opencv\\code\\src\\chapter8\\code 8-5\\data\\train\u images”;
foreach(Directory.GetFiles(TEMPLATE_文件夹,“*”,SearchOption.AllDirectories)中的var文件名)
{
添加(GetMat(filename,true));
此.OnTrained(文件名);
}
}
作废制造列车组(列示列车组,列示类别名称)
{
字符串TRAIN\u FOLDER=“C:\\Emgu\\book\\practical opencv\\code\\src\\chapter8\\code 8-5\\data\\TRAIN\u images”;
类别名称=新列表();
列车组=新列表();
foreach(目录中的var dir.GetDirectories(TRAIN_文件夹))
{
//从文件夹的名称中获取类别名称
字符串category=newdirectoryinfo(dir).Name;
类别名称。添加(类别);
foreach(Directory.GetFiles(dir)中的var文件名)
{     
train_set.Add(新元组(category,GetMat(filename,true));
此.OnTrained(文件名);
}
}
}
void build_vocab(Feature2D描述符牵引器、Feature2D featureDetector、列表模板、bowKMeanFilter bowtrainer、out Mat vocab)
{
Mat vocab_描述符=新Mat();
foreach(模板中的Mat templ)
{
Mat desc=新Mat();
VectorOfKeyPoint kp=新的KeyPoint矢量(featureDetector.Detect(templ));
descriptor.Compute(模板、kp、描述);
语音描述符。后推(描述);
}
bowtrainer.添加(语音描述符);
vocab=新的Mat();
弓箭教练机集群(vocab);
字符串fn=getVocabularyFileN