I am trying to learn BOW object categorization. I have tried to implement the example given in the book "Practical OpenCV, Samarth Brahmbhatt" Chapter 8 (page 148)
When I save the SVM's to file on the training stage and read them on the categorization stage, the result is comletely different. (If the line
svm = notFromFile[category]; is removed, the results are wrong; if not, it is successful with the dataset provided by the book.)
When I try this code with some larger datasets, I sometimes get this exception: System.AccessViolationException' in Emgu.CV.World.dll for the line bowDescriptorExtractor.Compute(frame_g, kp, img); and the application closes. It cannot be handled.
I have tried many things but could not figure them out. Any suggestions why these are happening, and how to solve, is very appreciated.
I am using emgucv-windesktop 3.1.0.2504
My implementation:
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;
}
}
}
Related
I built a winform project. This project open a mhtml file, then, he display the datagrid and remove the empty column.
i used much time "invoke" in my code. I would like to know how can i put this data into a DataTable or List and then binded the grid to it.
Here is the code :
{
public partial class Form1 : Form
{
private readonly string ConvertedFileName = "page.html";
private readonly List<string> ColumnsToSeparate = new List<string>() { "life limit", "interval" }; // Delete these columns
private readonly List<string> ExtraColumnsToAdd = new List<string>() { "Calendar", "Flight Hours", "Landing" }; // Add these columns
public Form1()
{
InitializeComponent();
this.Text = $"MhtmlTablesHunter v{Application.ProductVersion}";
}
//browse for specific file type , in this case its .mhtml
private void btnBrowse_Click(object sender, EventArgs e)
{
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.Title = "Please choose the MHTML file";
openFileDialog.Filter = "MHTML files (*.mhtml)|*.mhtml;"; //the file type specified here
openFileDialog.RestoreDirectory = false;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
textBoxSourceFile.Text = openFileDialog.FileName;
checkAndExtractTable();
}
}
}
private void checkAndExtractTable()
{
string sourcePath = textBoxSourceFile.Text;
if (!string.IsNullOrEmpty(sourcePath)) //check if the input file path is not empty
{
if (File.Exists(sourcePath)) //check if the input file path is exists
{
Task.Run(async () => await ExtractTable(sourcePath)); //run the extraction process in a thread for the UI to be more responsive
}
else
{
MessageBox.Show("Source file doesn't exist.");
}
}
else
{
MessageBox.Show("Please select the source file.");
}
}
//This part concern the headers, rows and columns
public async Task<string> ExtractTable(string sourcePath)
{
try
{
var doc = new HtmlAgilityPack.HtmlDocument();
var converter = new MimeConverter(); //converter used to convert mhtml file to html
if (File.Exists(ConvertedFileName)) //check if previously converted file is exist
{
File.Delete(ConvertedFileName); //delete the file
}
using (FileStream sourceStream = File.OpenRead(sourcePath))
{
using (FileStream destinationStream = File.Open("page.html", FileMode.Create))
{
await converter.Convert(sourceStream, destinationStream); //convert the file to html, it will be stored in the application folder
}
}
doc.Load(ConvertedFileName); //load the html
var tables = doc.DocumentNode.SelectNodes("//table"); //get all the tables
HtmlAgilityPack.HtmlNode table = null;
if (tables.Count > 0)
{
table = tables[tables.Count - 1]; //take the last table
}
if (table != null) //if the table exists
{
dataGridView1.Invoke((Action)delegate //we use delegate because we accessing the datagridview from a different thread
{
this.dataGridView1.Rows.Clear();
this.dataGridView1.Columns.Clear();
});
var rows = table.SelectNodes(".//tr"); //get all the rows
var nodes = rows[0].SelectNodes("th|td"); //get the header row values, first item will be the header row always
string LifeLimitColumnName = ColumnsToSeparate.Where(c => nodes.Any(n => n.InnerText.ToLower().Contains(c))).FirstOrDefault();
if (string.IsNullOrWhiteSpace(LifeLimitColumnName))
{
LifeLimitColumnName = "Someunknowncolumn";
}
List<string> headers = new List<string>();
for (int i = 0; i < nodes.Count; i++) // LOOP
{
headers.Add(nodes[i].InnerText);
if (!nodes[i].InnerText.ToLower().Contains(LifeLimitColumnName))
{
dataGridView1.Invoke((Action)delegate
{
dataGridView1.Columns.Add("", nodes[i].InnerText);
});
}
}
int indexOfLifeLimitColumn = headers.FindIndex(h => h.ToLower().Contains(LifeLimitColumnName));
if (indexOfLifeLimitColumn > -1)
{
foreach (var eh in ExtraColumnsToAdd)
{
dataGridView1.Invoke((Action)delegate
{
dataGridView1.Columns.Add("", eh); //add extra header to the datagridview
});
}
}
for (int i = 1; i < rows.Count; i++) ///loop through rest of the rows
{
var row = rows[i];
var nodes2 = row.SelectNodes("th|td"); //get all columns in the current row
List<string> values = new List<string>(); //list to store row values
for (int x = 0; x < nodes2.Count; x++)
{
//rowes.Cells[x].Value = nodes2[x].InnerText;
string cellText = nodes2[x].InnerText.Replace(" ", " ");
values.Add(cellText); //add the cell value in the list
}
// Factory for -> Calendar, Flight Hours, Landings
if (indexOfLifeLimitColumn > -1)
{
values.RemoveAt(indexOfLifeLimitColumn);
string lifeLimitValue = nodes2[indexOfLifeLimitColumn].InnerText.Replace(" ", " ");
string[] splittedValues = lifeLimitValue.Split(' ');
for (int y = 0; y < ExtraColumnsToAdd.Count; y++)
{
if (ExtraColumnsToAdd[y] == "Calendar")
{
string valueToAdd = string.Empty;
string[] times = new string[] { "Years", "Year", "Months", "Month", "Day", "Days" };
if (splittedValues.Any(s => times.Any(t => t == s)))
{
var timeFound = times.Where(t => splittedValues.Any(s => s == t)).FirstOrDefault();
int index = splittedValues.ToList().FindIndex(s => s.Equals(timeFound));
valueToAdd = $"{splittedValues[index - 1]} {timeFound}";
}
values.Add(valueToAdd);
}
else if (ExtraColumnsToAdd[y] == "Flight Hours")
{
string valueToAdd = string.Empty;
if (splittedValues.Any(s => s == "FH"))
{
int index = splittedValues.ToList().FindIndex(s => s.Equals("FH"));
valueToAdd = $"{splittedValues[index - 1]} FH";
}
values.Add(valueToAdd);
}
else
{
string valueToAdd = string.Empty;
if (splittedValues.Any(s => s == "LDG"))
{
int index = splittedValues.ToList().FindIndex(s => s.Equals("LDG"));
valueToAdd = $"{splittedValues[index - 1]} LDG";
}
values.Add(valueToAdd);
}
}
}
dataGridView1.Invoke((Action)delegate
{
this.dataGridView1.Rows.Add(values.ToArray()); //add the list as a row
});
}
//This code remove the empty row
dataGridView1.Invoke((Action)delegate
{
int[] rowDataCount = new int[dataGridView1.Columns.Count];
Array.Clear(rowDataCount, 0, rowDataCount.Length);
for (int row_i = 0; row_i < this.dataGridView1.RowCount; row_i++)
{
for (int col_i = 0; col_i < this.dataGridView1.ColumnCount; col_i++)
{
var cell = this.dataGridView1.Rows[row_i].Cells[col_i];
string cellText = cell.Value.ToString();
if (!String.IsNullOrWhiteSpace(cellText))
{
rowDataCount[col_i] += 1;
}
}
}
int removedCount = 0;
for (int index = 0; index < rowDataCount.Length; index++)
{
if (rowDataCount[index] == 0)
{
this.dataGridView1.Columns.RemoveAt(index - removedCount);
removedCount++;
}
}
});
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return string.Empty;
}
private void textBoxSourceFile_TextChanged(object sender, EventArgs e)
{
}
}
}
Somebody can help me please? thanks a lot !
I am new on this subject. What I try to do is train many SVM's for the same dataset with different parameters (different kind of signature of images in the future I hope) then predict each SVM and accept the mostly found class.
I tried to read many peoples' code about SVM image training, but couldn't figure out what I am doing wrong im my code. What ever I try, svm.Predict always return 0.
Any help or hint is very appreciated.
internal class SVMClassifier
{
Dictionary<int, string> classIndex_name;
List<SVM> svms;
internal void Train(string trainFolder)
{
this.classIndex_name = new Dictionary<int, string>();
Dictionary<int, List<Mat>> class_mats = getMats(trainFolder, this.classIndex_name);
this.svms = new List<SVM>();
Mat samples; Mat responses;
getTrainingData(class_mats, out samples, out responses);
svms.Add(trainSVM(samples, responses));
svms.Add(trainSVM(samples, responses, SVM.SvmType.CSvc, SVM.SvmKernelType.Linear, 0d, 0d, 10d, TermCritType.Iter | TermCritType.Eps, 1000, 0.000001d, 0d, 0d));
svms.Add(trainSVM(samples, responses, SVM.SvmType.CSvc, SVM.SvmKernelType.Rbf, 100d, 100d, 1d, TermCritType.Iter | TermCritType.Eps, 1000, 0.000001d, 0.1d, 0.5d));
samples.Dispose(); responses.Dispose();
foreach (Mat mat in class_mats.Values.SelectMany((a) => a))
mat.Dispose();
}
private static Dictionary<int, List<Mat>> getMats(string trainFolder, Dictionary<int, string> classIndex_name)
{
Dictionary<int, List<Mat>> class_mats = new Dictionary<int, List<Mat>>();
DirectoryInfo diTrain = new DirectoryInfo(trainFolder);
int i = 0;
foreach (var di in diTrain.GetDirectories())//classes are according to the directories
{
var dirName = di.Name;
classIndex_name[i] = dirName;
var fileNames = di.GetFiles().Select((a) => a.FullName).ToList();
fileNames.Sort(new Dece.Misc.NumericSuffixFileFullNameComparer());
class_mats[i] = fileNames.Select((a) => getMat(a, true)).ToList();
i++;
}
return class_mats;
}
private static SVM trainSVM(Mat samples, Mat responses,
SVM.SvmType? svm_Type = null, SVM.SvmKernelType? svm_KernelType = null, double? gamma = null, double? degree = null, double? c = null,
TermCritType? criteriaType = null, int? criteriaMaxCount = null, double? criteriaEps = null, double? p = null, double? nu=null)
{
SVM svm = new SVM();
if (svm_Type != null) svm.Type = (SVM.SvmType)svm_Type;
if (svm_KernelType != null) svm.SetKernel((SVM.SvmKernelType)svm_KernelType);
if (gamma != null) svm.Gamma = (double)gamma;
if (degree != null) svm.Degree = (double)degree;
if (c != null) svm.C = (double)c;
if ((criteriaType != null) || (criteriaMaxCount != null) || (criteriaEps != null))
{
var t = new MCvTermCriteria((int)criteriaMaxCount, (double)criteriaEps);
if (criteriaType != null) t.Type = (TermCritType)criteriaType;
svm.TermCriteria = t;
}
if (p != null) svm.P = (double)p;
if (nu != null) svm.Nu = (double)nu;
if (!svm.Train(samples, DataLayoutType.RowSample, responses))
throw new Exception();
return svm;
}
private static void getTrainingData(Dictionary<int, List<Mat>> class_mats, out Mat samples, out Mat responses)
{
samples = null;
List<int> lstResp = new List<int>();
foreach (int cls in class_mats.Keys)
{
int count = 0;
foreach (Mat mat in class_mats[cls])
using (var desc = mat.Reshape(0, 1))
{
if (samples == null)
samples = new Mat(desc.Cols, 0, desc.Depth, 1);
samples.PushBack(desc);
count += desc.Rows;
}
for (int i = 0; i < count; i++)
lstResp.Add(cls);
}
//responses = new Mat(new Size(lstResp.Count, 1), DepthType.Cv32S, 1);
//for (int i = 0; i < lstResp.Count; i++)
// responses.SetValue(0, i, lstResp[i]);
responses = new Mat(new Size(1, lstResp.Count), DepthType.Cv32S, 1);
for (int i = 0; i < lstResp.Count; i++)
responses.SetValue(i, 0, lstResp[i]);
if (samples.Depth != DepthType.Cv32F)
samples.ConvertTo(samples, DepthType.Cv32F);
CvInvoke.Normalize(samples, samples, -1, 1, NormType.MinMax);
}
internal void Detect(IEnumerable<string> fileNames, Action<ShapeInfo> detected)
{
foreach (var fn in fileNames)
using (Mat mat = getMat(fn, false))
{
{
using (var samples = mat.Reshape(0, 1))
{
if (samples.Depth != DepthType.Cv32F)
samples.ConvertTo(samples, DepthType.Cv32F);
CvInvoke.Normalize(samples, samples, -1, 1, NormType.MinMax);
foreach (var svm in this.svms)
{
Mat res = new Mat();
float p0 = svm.Predict(samples, res, 0);
float p1 = svm.Predict(samples, res, 1);
float p2 = svm.Predict(samples, res, 2);
float p3 = svm.Predict(samples, res, 3);
float p4 = svm.Predict(samples, res, 4);
float p = svm.Predict(samples, res);
foreach (var val in toIEnumerable(p0, p1, p2, p3, p4, p))
if (val != 0f)
{
System.Windows.Forms.MessageBox.Show("never enters here :(");
}
}
}
}
}
}
private static Mat getMat(string fn, bool train)
{
var mat = new Mat(fn, ImreadModes.Grayscale);
mat.Resize(new Size(128, 128));
return mat;
}
private static IEnumerable<T> toIEnumerable<T>(params T[] items)
{
if (items != null)
foreach (var item in items)
yield return item;
}
}
Mat.SetValue extension is taken from here.
I hope asking like that is propriate for this site's format. If not this question can be closed-erased, no problem. I am trying to understand how should we train an svm with images.
Yes I am stupid. The problem was sending an empty Mat to Predict function. When I tried null instead, I started to get the class predictions. (I still dont get why.)
Classification problem makes me feel like a dumb. Any comments about how I am using svm, what could-should be done is wellcome.
internal void Detect(IEnumerable<string> fileNames, Action<ShapeInfo> detected)
{
foreach (var fn in fileNames)
using (Mat mat = getMat(fn, false))
{
{
using (var samples = mat.Reshape(0, 1))
{
if (samples.Depth != DepthType.Cv32F)
samples.ConvertTo(samples, DepthType.Cv32F);
CvInvoke.Normalize(samples, samples, -1, 1, NormType.MinMax);
foreach (var svm in this.svms)
{
float p = svm.Predict(samples, null);
}
}
}
}
}
This is my project so far:
private void test()
{
var rows = GetDataGridRows(dgVarConfig);
Dictionary<TextBlock, String> dic = new Dictionary<TextBlock, string>();
foreach (DataGridRow r in rows)
{
TextBlock tb = cMatchEx.GetCellContent(r) as TextBlock;
dic.Add(tb, tb.Text);
}
if (!syntaxWorker.IsBusy)
syntaxWorker.RunWorkerAsync(dic);
}
private void syntaxWorker_DoWork(object sender, DoWorkEventArgs e)
{
if (e.Argument == null)
Thread.Sleep(100);
else
{
Dictionary<TextBlock, String> dic = (Dictionary<TextBlock, String>)e.Argument;
foreach (KeyValuePair<TextBlock, String> kvp in dic)
{
kvp.Key.Dispatcher.BeginInvoke(new Action(() =>
{
kvp.Key.Inlines.Clear();
Syntax.Highlight(kvp.Value).ForEach(x => kvp.Key.Inlines.Add(x));
}));
}
}
}
Syntax.Highlight:
public static class Syntax
{
static Regex subFormula = new Regex(#"\w+\(\)");
static Regex sapFormula = new Regex(#"\w+\(([^)]+)\)");
static Regex strings = new Regex(#"\'[^']+\'");
static Regex numerals = new Regex(#"\b[0-9\.]+\b");
static Regex characteristic = new Regex(#"(?:)?\w+(?:)?");
static Regex andOr = new Regex(#"( and )|( AND )|( or )|( OR )");
static Regex not = new Regex(#"(not )|(NOT )");
private static Brush[] colorArray;
public static List<Run> Highlight(String input)
{
colorArray = new Brush[input.Length];
for (int i = 0; i < input.Length; i++)
colorArray[i] = Brushes.Black;
//Reihenfolge beibehalten!!
assignColor(Brushes.Blue, characteristic.Matches(input));
assignColor(Brushes.Black, andOr.Matches(input));
assignColor(Brushes.Black, numerals.Matches(input));
assignColor(Brushes.Orange, strings.Matches(input));
assignColor(Brushes.DeepPink, subFormula.Matches(input));
assignColor(Brushes.Green, sapFormula.Matches(input));
assignColor(Brushes.Green, not.Matches(input));
int index = 0;
List<Run> runList = new List<Run>();
foreach (Char character in input)
{
runList.Add(new Run(character.ToString()) { Foreground = colorArray[index] });
index++;
}
colorArray = null;
return runList;
}
public static void Check(TextBlock textBlock)
{
}
private static void assignColor(Brush brush, MatchCollection matchCollection)
{
foreach (Match match in matchCollection)
{
int start = match.Index;
int end = start + match.Length;
for (int i = start; i < end; i++)
{
colorArray[i] = brush;
}
}
}
}
With this code, the gui freezes for about 2 seconds. Is there any way to build up the gui step by step and avoid any freezing?
Its no problem to see how its building up, just the freezing is a problem.
Hope anybody knows how to resolve this.
You could move a good portion of the work outside of the invoke like this :
One small caveat : i'm not entirely sure how you retreive the text of the textboxes. you might have to do a separate invoke for that (see comment in the code)
public class RunInfo
{
public string Content { get; set;}
public Color foreground { get; set; }
public RunInfo(string content)
{
Content = content;
}
public Run AsRun()
{
return new Run(Content){ Foreground = foreground };
}
}
public static class Syntax
{
static Regex subFormula = new Regex(#"\w+\(\)");
static Regex sapFormula = new Regex(#"\w+\(([^)]+)\)");
static Regex strings = new Regex(#"\'[^']+\'");
static Regex numerals = new Regex(#"\b[0-9\.]+\b");
static Regex characteristic = new Regex(#"(?:)?\w+(?:)?");
static Regex andOr = new Regex(#"( and )|( AND )|( or )|( OR )");
static Regex not = new Regex(#"(not )|(NOT )");
private static Brush[] colorArray;
public static List<RunInfo> Highlight(String input)
{
colorArray = new Brush[input.Length];
for (int i = 0; i < input.Length; i++)
colorArray[i] = Brushes.Black;
//Reihenfolge beibehalten!!
assignColor(Brushes.Blue, characteristic.Matches(input));
assignColor(Brushes.Black, andOr.Matches(input));
assignColor(Brushes.Black, numerals.Matches(input));
assignColor(Brushes.Orange, strings.Matches(input));
assignColor(Brushes.DeepPink, subFormula.Matches(input));
assignColor(Brushes.Green, sapFormula.Matches(input));
assignColor(Brushes.Green, not.Matches(input));
int index = 0;
List<Run> runList = new List<Run>();
foreach (Char character in input)
{
runList.Add(new RunInfo(character.ToString()) { Foreground = colorArray[index] });
index++;
}
colorArray = null;
return runList;
}
public static void Check(TextBlock textBlock)
{
}
private static void assignColor(Brush brush, MatchCollection matchCollection)
{
foreach (Match match in matchCollection)
{
int start = match.Index;
int end = start + match.Length;
for (int i = start; i < end; i++)
{
colorArray[i] = brush;
}
}
}
}
private void syntaxWorker_DoWork(object sender, DoWorkEventArgs e)
{
if (e.Argument == null)
Thread.Sleep(100);
else
{
Dictionary<TextBlock, String> dic = (Dictionary<TextBlock, String>)e.Argument;
foreach (KeyValuePair<TextBlock, String> kvp in dic)
{
//i am unsure if this line will work. if it does not, you might need to do a separate dispatcher invoke in order to retreive the text from the textbox.
List<RunInfo> runinfoObjects = Syntax.Highlight(kvp.Value);
kvp.Key.Dispatcher.BeginInvoke(new Action(() =>
{
kvp.Key.Inlines.Clear();
//we'd run into problems here, since wpf won't allow us to add elements created in a background thread. since we now make the Run object inside the invoke, we should be fine.
runinfoObjects.ForEach(x => kvp.Key.Inlines.Add(x.AsRun()));
}));
}
}
}
Before i asked my question, I read the previous posts.When I run the script, it shows Invalid rank specifier:expected ',' or ']' error at following code. BTW, I tried with new float[8939, 100]; but it still shows the error.
And also how can use hashtable to save the result where i wrote the hashtable comments.
namespace function
{
public partial class Form1 : Form
{
float userscore,itemscore,result;
string lineitem, lineuser;
float[][] a = new float[89395][100]; //<----the error is here
float[][] b = new float[1143600][100]; //<----the error is here
//float[,] c = new float[89395, 100];
StreamReader fileitem = new StreamReader("c:\\1.txt");
StreamReader fileuser = new StreamReader("c:\\2.txt");
public Form1()
{
InitializeComponent();
for (int x = 0; x <= 8939500; x++)
{
lineuser = fileuser.ReadLine();
string[] values = lineuser.Split(' ');
int userid, factoriduser;
foreach (string value in values)
{
userid = Convert.ToInt32(values[0]);
factoriduser = Convert.ToInt32(values[1]);
userscore = Convert.ToSingle(values[2]);
a[userid][factoriduser] = userscore;
}
}
for (int y = 0; y <= 114360000; y++)
{
lineitem = fileitem.ReadLine();
string[] valuesi = lineitem.Split(' ');
int itemid, factoriditem;
foreach (string value in valuesi)
{
itemid = Convert.ToInt32(valuesi[0]);
factoriditem = Convert.ToInt32(valuesi[1]);
itemscore = Convert.ToSingle(valuesi[2]);
b[itemid][factoriditem] = itemscore;
}
}
}
public float dotproduct(int userid,int itemid)
{
//get the score of 100 from user and item to dotproduct
float[] u_f = a[userid];
float[] i_f = b[itemid];
for (int i = 0; i <u_f.GetLength(1); i++)
{
result += u_f[userid] * i_f[itemid];
}
return result;
}
private void btn_recomm_Click(object sender, EventArgs e)
{
if(txtbx_id.Text==null)
{
MessageBox.Show("please insert user id");
}
if (txtbx_id.Text != null)
{
int sc = Convert.ToInt32(txtbx_id.Text);
if (sc>=0 &&sc<=89395)
{
for (int z=0;z<=1143600;z++)
{
dotproduct(sc,z);
}
//Hashtable hashtable = new Hashtable();
//put the result in hashtable
//foreach (DictionaryEntry entry in hashtable)
//{
//Console.WriteLine("{0}, {1}", entry.Key, entry.Value);
// }
}
}
if (txtbx_id==null &&txtbx_itemid==null)
{
int uid = Convert.ToInt32(txtbx_id.Text);
int iid = Convert.ToInt32(txtbx_itemid.Text);
{
if (uid>=0 && uid<=89395 && iid>=0 && iid<=1143600)
{
dotproduct(uid,iid);
MessageBox.Show("The Score of user id "+uid+" is "+result);
}
}
}
}
You cannot declare jagged array like that. You have to declare outer array first, and then declare all inner arrays:
float[][] a = new float[89395][];
for(int i = 0; i < 89395; i++)
a[i] = new float[100];
or you should change your array to multidimensional float[,] array:
float[,] a = new float[89395,100];
float[,] a = new float[89395,100];
float[,] b = new float[1143600,100];
Reference: http://msdn.microsoft.com/en-us/library/2yd9wwz4.aspx
You cannot make a new 2D array like that - you do it one dimension at a time. You can useva loop to initialize the second dimensiuon, or use LINQ:
float[][] a = Enumerable.Range(0, 89395).Select(i=>new float[100]).ToArray();
What C# template engine
that uses 'pure' HTML having only text and markers
sans any control flow like if, while, loop or expressions,
separating html from control code ?
Below is the example phone book list code,
expressing how this should be done:
string html=#"
<html><head><title>#title</title></head>
<body>
<table>
<tr>
<td> id</td> <td> name</td> <td> sex</td> <td>phones</td>
</tr><!--#contacts:-->
<tr>
<td>#id</td> <td>#name</td> <td>#sex</td>
<td>
<!--#phones:-->#phone <br/>
<!--:#phones-->
</td>
</tr><!--:#contacts-->
</table>
</body>
</html>";
var contacts = from c in db.contacts select c;
Marker m = new Marker(html);
Filler t = m.Mark("title");
t.Set("Phone book");
Filler c = m.Mark("contacts", "id,name,sex");
// **foreach** expressed in code, not in html
foreach(var contact in contacts) {
int id = contact.id;
c.Add(id, contact.name, contact.sex);
Filler p = c.Mark("phones", "phone");
var phones = from ph in db.phones
where ph.id == id
select new {ph.phone};
if (phones.Any()) {
foreach(var ph in phones) {
p.Add(ph);
}
} else {
fp.Clear();
}
}
Console.Out.WriteLine(m.Get());
Use this code:
Templet.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace templaten.com.Templaten
{
public class tRange
{
public int head, toe;
public tRange(int _head, int _toe)
{
head = _head;
toe = _toe;
}
}
public enum AType
{
VALUE = 0,
NAME = 1,
OPEN = 2,
CLOSE = 3,
GROUP = 4
}
public class Atom
{
private AType kin;
private string tag;
private object data;
private List<Atom> bag;
public Atom(string _tag = "",
AType _kin = AType.VALUE,
object _data = null)
{
tag = _tag;
if (String.IsNullOrEmpty(_tag))
_kin = AType.GROUP;
kin = _kin;
if (_kin == AType.GROUP)
bag = new List<Atom>();
else
bag = null;
data = _data;
}
public AType Kin
{
get { return kin; }
}
public string Tag
{
get { return tag; }
set { tag = value; }
}
public List<Atom> Bag
{
get { return bag; }
}
public object Data
{
get { return data; }
set { data = value; }
}
public int Add(string _tag = "",
AType _kin = AType.VALUE,
object _data = null)
{
if (bag != null)
{
bag.Add(new Atom(_tag, _kin, _data));
return bag.Count - 1;
}
else
{
return -1;
}
}
}
public class Templet
{
private string content;
string namepat = "\\w+";
string justName = "(\\w+)";
string namePre = "#";
string namePost = "";
string comment0 = "\\<!--\\s*";
string comment1 = "\\s*--\\>";
private Atom tokens; // parsed contents
private Dictionary<string, int> iNames; // name index
private Dictionary<string, tRange> iGroups; // groups index
private Atom buffer; // output buffer
private Dictionary<string, int> _iname; // output name index
private Dictionary<string, tRange> _igroup; // output index
public Templet(string Content = null)
{
Init(Content);
}
private int[] mark(string[] names, string group)
{
if (names == null || names.Length < 1) return null;
tRange t = new tRange(0, buffer.Bag.Count - 1);
if (group != null)
{
if (!_igroup.ContainsKey(group)) return null;
t = _igroup[group];
}
int[] marks = new int[names.Length];
for (int i = 0; i < marks.Length; i++)
marks[i] = -1;
for (int i = t.head; i <= t.toe; i++)
{
if (buffer.Bag[i].Kin == AType.NAME)
{
for (int j = 0; j < names.Length; j++)
{
if (String.Compare(
names[j],
buffer.Bag[i].Tag,
true) == 0)
{
marks[j] = i;
break;
}
}
}
}
return marks;
}
public Filler Mark(string group, string names)
{
Filler f = new Filler(this, names);
f.di = mark(f.names, group);
f.Group = group;
tRange t = null;
if (_igroup.ContainsKey(group)) t = _igroup[group];
f.Range = t;
return f;
}
public Filler Mark(string names)
{
Filler f = new Filler(this, names);
f.di = mark(f.names, null);
f.Group = "";
f.Range = null;
return f;
}
public void Set(int[] locations, object[] x)
{
int j = Math.Min(x.Length, locations.Length);
for (int i = 0; i < j; i++)
{
int l = locations[i];
if ((l >= 0) && (buffer.Bag[l] != null))
buffer.Bag[l].Data = x[i];
}
}
public void New(string group, int seq = 0)
{
// place new group copied from old group just below it
if (!( iGroups.ContainsKey(group)
&& _igroup.ContainsKey(group)
&& seq > 0)) return;
tRange newT = null;
tRange t = iGroups[group];
int beginRange = _igroup[group].toe + 1;
for (int i = t.head; i <= t.toe; i++)
{
buffer.Bag.Insert(beginRange,
new Atom(tokens.Bag[i].Tag,
tokens.Bag[i].Kin,
tokens.Bag[i].Data));
beginRange++;
}
newT = new tRange(t.toe + 1, t.toe + (t.toe - t.head + 1));
// rename past group
string pastGroup = group + "_" + seq;
t = _igroup[group];
buffer.Bag[t.head].Tag = pastGroup;
buffer.Bag[t.toe].Tag = pastGroup;
_igroup[pastGroup] = t;
// change group indexes
_igroup[group] = newT;
}
public void ReMark(Filler f, string group)
{
if (!_igroup.ContainsKey(group)) return;
Map(buffer, _iname, _igroup);
f.di = mark(f.names, group);
f.Range = _igroup[group];
}
private static void Indexing(string aname,
AType kin,
int i,
Dictionary<string, int> dd,
Dictionary<string, tRange> gg)
{
switch (kin)
{
case AType.NAME: // index all names
dd[aname] = i;
break;
case AType.OPEN: // index all groups
if (!gg.ContainsKey(aname))
gg[aname] = new tRange(i, -1);
else
gg[aname].head = i;
break;
case AType.CLOSE:
if (!gg.ContainsKey(aname))
gg[aname] = new tRange(-1, i);
else
gg[aname].toe = i;
break;
default:
break;
}
}
private static void Map(Atom oo,
Dictionary<string, int> dd,
Dictionary<string, tRange> gg)
{
for (int i = 0; i < oo.Bag.Count; i++)
{
string aname = oo.Bag[i].Tag;
Indexing(oo.Bag[i].Tag, oo.Bag[i].Kin, i, dd, gg);
}
}
public void Init(string Content = null)
{
content = Content;
tokens = new Atom("", AType.GROUP);
iNames = new Dictionary<string, int>();
iGroups = new Dictionary<string, tRange>();
// parse content into tokens
string namePattern = namePre + namepat + namePost;
string patterns =
"(?<var>" + namePattern + ")|" +
"(?<head>" + comment0 + namePattern + ":" + comment1 + ")|" +
"(?<toe>" + comment0 + ":" + namePattern + comment1 + ")";
Regex jn = new Regex(justName, RegexOptions.Compiled);
Regex r = new Regex(patterns, RegexOptions.Compiled);
MatchCollection ms = r.Matches(content);
int pre = 0;
foreach (Match m in ms)
{
tokens.Add(content.Substring(pre, m.Index - pre));
int idx = -1;
if (m.Groups.Count >= 3)
{
string aname = "";
MatchCollection x = jn.Matches(m.Value);
if (x.Count > 0 && x[0].Groups.Count > 1)
aname = x[0].Groups[1].ToString();
AType t = AType.VALUE;
if (m.Groups[1].Length > 0) t = AType.NAME;
if (m.Groups[2].Length > 0) t = AType.OPEN;
if (m.Groups[3].Length > 0) t = AType.CLOSE;
if (aname.Length > 0)
{
tokens.Add(aname, t);
idx = tokens.Bag.Count - 1;
}
Indexing(aname, t, idx, iNames, iGroups);
}
pre = m.Index + m.Length;
}
if (pre < content.Length)
tokens.Add(content.Substring(pre, content.Length - pre));
// copy tokens into buffer
buffer = new Atom("", AType.GROUP);
for (int i = 0; i < tokens.Bag.Count; i++)
buffer.Add(tokens.Bag[i].Tag, tokens.Bag[i].Kin);
// initialize index of output names
_iname = new Dictionary<string, int>();
foreach (string k in iNames.Keys)
_iname[k] = iNames[k];
// initialize index of output groups
_igroup = new Dictionary<string, tRange>();
foreach (string k in iGroups.Keys)
{
tRange t = iGroups[k];
_igroup[k] = new tRange(t.head, t.toe);
}
}
public string Get()
{
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < buffer.Bag.Count; i++)
{
switch (buffer.Bag[i].Kin)
{
case AType.VALUE:
sb.Append(buffer.Bag[i].Tag);
break;
case AType.NAME:
sb.Append(buffer.Bag[i].Data);
break;
case AType.OPEN:
case AType.CLOSE:
break;
default: break;
}
}
return sb.ToString();
}
}
public class Filler
{
private Templet t = null;
public int[] di;
public string[] names;
public string Group { get; set; }
public tRange Range { get; set; }
private int seq = 0;
public Filler(Templet tl, string markers = null)
{
t = tl;
if (markers != null)
names = markers.Split(new char[] { ',' },
StringSplitOptions.RemoveEmptyEntries);
else
names = null;
}
public void init(int length)
{
di = new int[length];
for (int i = 0; i < length; i++)
di[i] = -1;
seq = 0;
Group = "";
Range = null;
}
// clear contents inside marked object or group
public void Clear()
{
object[] x = new object[di.Length];
for (int i = 0; i < di.Length; i++)
x[i] = null;
t.Set(di, x);
}
// set value for marked object,
// or add row to group and set value to columns
public void Set(params object[] x)
{
t.Set(di, x);
}
public void Add(params object[] x)
{
if (Group.Length > 0)
{
t.New(Group, seq);
++seq;
t.ReMark(this, Group);
}
t.Set(di, x);
}
}
}
Testing program
Program.cs
Templet m = new Templet(html);
Filler f= m.Mark("title");
f.Set("Phone book");
Filler fcontacts = m.Mark("contacts", "id,name,sex,phone");
fcontacts.Add(1, "Akhmad", "M", "123456");
fcontacts.Add(2, "Barry", "M", "234567");
fcontacts.Add(1, "Charles", "M", "345678");
Console.Out.WriteLine(m.Get());
Still can't do nested loop- yet.
Just use ASP.NET. Whether you use webforms or MVC, it's super easy to have C# in your .cs files, and HTML in your .aspx files.
As with anything in programming, it's 99% up to you to do things right. Flexible UI engines aren't going to enforce that you follow good coding practices.
In principle most any template engine you choose can separate HTML from control logic with the proper architecture. using an MVC (Or MVVM) pattern, if you construct your model in such a way that the controller contains the if/then logic instead of the view you can eliminate it from the view.
That said, the syntax you use is very close to Razor syntax which is easily available for ASP.NET MVC through NuGet packages.
I totally hear you. I built SharpFusion, which has some other stuff in it but if you look for the template.cs file you will see the handler that parses a HTML file and simply replaces out tokens with values that you've made in c#.
Because no XML parsing is done like ASP.NET the framework loads much faster than even an MVC site.
Another alternative is ServiceStack.