Converting CSV and Vector Data to Native HTK Format Using C#

The output of my Principal Component Analysis in Matlab to reduce the dimensionality of gesture data is in the comma separated variable format. 57 dimension data goes in, X dimension data comes out in standard csv format. It is better to remove unnecessary information from the gesture data as it only makes the recognition of gesture (and intent, in my case) more difficult.

The problem is that the HTK, which I am going to use to perform recognition, doesn’t natively accept csv data so you have to convert to the HTK binary format parameter files. I chose to do this in c# as I’m familiar with it, but I stumbled across a few problems relating to the conversion between big-endian and little-endian binary data. HTK reads data in the opposite way to my PC (although I’m sure I read on their website somewhere that there is automatic detection for this).

The following code is pretty rough around the edges as it includes a lot of stuff to help me debug it. The program reads a directory and converts all *.csv files into HTK format binary files by reading in the data as floats, converting to bytes, writing a header and then writing the data to a binary file *.csv.bin.

static void Main(string[] args)
{
string dir = @”G:PHD Nov 09# programsmatlab worktest”;
DirectoryInfo di = new DirectoryInfo(dir);

FileInfo[] rgFiles = di.GetFiles(“*.csv”);
foreach (FileInfo fi in rgFiles)
{
using (TextReader tr = new StreamReader(fi.FullName))
{
string data = tr.ReadToEnd();
System.Text.ASCIIEncoding encoding=new System.Text.ASCIIEncoding();
byte[] byteArray = encoding.GetBytes(data);

string newdata = data.Replace(‘n’,’ ‘);
string[] plit = newdata.Trim().Split(‘ ‘);

int samples = plit.Length;
int itemspersample = plit[0].Split(‘,’).Length;

// now create binary data, each sample (part of a line in the file)
// has to be converted from a float to a 4 byte array and then joined to make one
// large binary file

byte[] bytedata = new byte[samples * itemspersample * 4];

for (int i = 0; i < samples; i++)
{
for (int j = 0; j < itemspersample; j++)
{
string dd = plit[i].Split(‘,’)[j];
float f = (float)Convert.ToDouble(plit[i].Split(‘,’)[j]);

byte[] temp = new byte[4];
temp = BitConverter.GetBytes(f);

bytedata[(i * itemspersample * 4) + (j * 4)] = temp[3];
bytedata[(i * itemspersample * 4) + (j * 4) + 1] = temp[2];
bytedata[(i * itemspersample * 4) + (j * 4) + 2] = temp[1];
bytedata[(i * itemspersample * 4) + (j * 4) + 3] = temp[0];
}
}

// now create HTK header 12 bytes long
byte[] nSamples = BitConverter.GetBytes(samples);
byte[] sampPeriod = BitConverter.GetBytes(100000);
byte[] sampSize = BitConverter.GetBytes(Convert.ToInt16(itemspersample * 4));
byte[] parmKind = BitConverter.GetBytes(Convert.ToInt16(9));

using (BinaryWriter bw = new BinaryWriter(File.Open(fi.FullName + “.bin”, FileMode.Create)))
{
Array.Reverse(nSamples);
Array.Reverse(sampPeriod);
Array.Reverse(sampSize);
Array.Reverse(parmKind);
bw.Write(nSamples);
bw.Write(sampPeriod);
bw.Write(sampSize);
bw.Write(parmKind);
bw.Write(bytedata);
}
}
}

To check it works you run HList, with no config file required as the header explains to HTK everything it needs to know about the data:

G:PHD Nov 09# programsmatlab worktest>hlist -h EO412_10PCs.csv.bin
————————- Source: EO412_10PCs.csv.bin ————————
Sample Bytes:  40       Sample Kind:   USER
Num Comps:     10       Sample Period: 10000.0 us
Num Samples:   5        File Format:   HTK
—————————— Samples: 0->-1 ——————————
0:    1838.200 308.910-262.970 401.920 -66.737-499.370 305.260-260.250 -91.974  28.171
1:    1837.700 308.630-263.340 400.810 -67.144-499.920 305.280-260.060 -92.174  27.584
2:    1837.000 308.360-263.750 399.940 -67.870-500.510 305.540-259.960 -91.964  26.922
3:    1836.500 308.160-264.000 398.500 -68.003-501.230 305.790-259.980 -92.138  26.342
4:    1837.000 308.360-263.750 399.940 -67.870-500.510 305.540-259.960 -91.964  26.922
———————————– END ———————————–

5 thoughts on “Converting CSV and Vector Data to Native HTK Format Using C#

  1. Dear Sir or Madam,

    I study maths and informatics at the University in Erlangen, Germany.

    We work on a project to analyse learning processes of pupils.
    The pupils had to solve different tasks with a learning software called “Eval Kara”. In “Eval KAra” they have a ladybeetle which can be controlled over view commands like “go ahead”, “go left”, “go right”, to lay or to put something. The individual techniques they used to solve these tasks are recorded into log-files in form of text-files with separators between the single actions they have executed. Our intention now is to analyse these log-files with Hidden Markov Models, which implies that we have to feed the collected data into the HTK.

    Here is an excerpt of one log-file:

    —————————————————————————————————————————-
    11:45:38 Bild “invertieren” (mittel) 1 5 STATE_ADDED Start 1 0 “”
    11:45:42 Bild “invertieren” (mittel) 1 8 TRANSITION_ADDED Start Start “” “”
    11:45:43 Bild “invertieren” (mittel) 1 12 TRANSITION_INPUT_CHANGED Start onLeaf 1 “”
    11:45:44 Bild “invertieren” (mittel) 1 12 TRANSITION_INPUT_CHANGED Start onLeaf 2 “”
    11:45:45 Bild “invertieren” (mittel) 1 12 TRANSITION_INPUT_CHANGED Start onLeaf 0 “”
    11:45:48 Bild “invertieren” (mittel) 1 12 TRANSITION_INPUT_CHANGED Start onLeaf 1 “”
    11:45:52 Bild “invertieren” (mittel) 1 9 TRANSITION_COMMAND_ADDED Start Start 0 removeLeaf
    11:45:54 Bild “invertieren” (mittel) 1 9 TRANSITION_COMMAND_ADDED Start Start 1 move
    11:46:07 Bild “invertieren” (mittel) 1 8 TRANSITION_ADDED Start Start “” “”
    11:46:07 Bild “invertieren” (mittel) 1 12 TRANSITION_INPUT_CHANGED Start onLeaf 1 “”
    11:46:08 Bild “invertieren” (mittel) 1 12 TRANSITION_INPUT_CHANGED Start onLeaf 2 “”
    11:46:10 Bild “invertieren” (mittel) 1 9 TRANSITION_COMMAND_ADDED Start Start 0 putLeaf
    11:46:12 Bild “invertieren” (mittel) 1 9 TRANSITION_COMMAND_ADDED Start Start 1 move
    11:46:18 Bild “invertieren” (mittel) 3 2 NO_START_STATE_EXCEPTION “” “” “” “”
    11:46:18 Bild “invertieren” (mittel) 0 3 ERROR_STOP “” “” “” “”
    11:46:27 Bild “invertieren” (mittel) 1 4 START_STATE_SET Start “” “” “”
    11:46:30 Bild “invertieren” (mittel) 0 4 GOT_READY “” “” “” “”
    11:46:30 Bild “invertieren” (mittel) 0 6 PLAYING “” “” “” “”
    11:46:30 Bild “invertieren” (mittel) 2 6 WORLD_OBJECT_REMOVED L0 1 1 “”
    11:46:30 Bild “invertieren” (mittel) 0 7 STEPPED “” “” “” “”
    11:46:31 Bild “invertieren” (mittel) 0 7 STEPPED “” “” “” “”
    11:46:32 Bild “invertieren” (mittel) 2 6 WORLD_OBJECT_REMOVED L0 2 1 “”

    The strukture is:

    Timestamp | Taskname | action-id | action-name they executed | different other parameters…

    In a nutshell:
    We don’t need to analyse Speech-data. We already have simple recorded textfiles from recorded behaviour of every pupil.
    Now we want to design Hidden Markov Modells to find spezial sequences ( similar to DNA-Sequencing).
    Is this possible with HTK? And how should we do this?

    Is it possible to use CSVfiles like you to convert the Data into HTK?

    It would be really very very nice hearing from you soon.

    kind regards,

    dreaduriel

    University Erlangen

  2. Dear James,

    I’m also currently working with HTK and have my own defined feature vectors (spatio-temporal float arrays).
    Basically, my feature extractor algorithm extracts a 500 element float vector. For each video sequence, I have on average 20 spatio-temporal windows (each of 8 frames with overlap of 4 frames), over which I extract the feature vector.
    Therefore, the dimensionality for a given video sequence is: 500×20.
    I did a small script in python, but was not sure how to set up the header values. Do you mind if I ask you a question related to that? In my case, the values would be:
    nSamples = 20
    sampPeriod = 8/25 * 10 000 000 (Each spatio-temporal window has 8 frames and the video has 25 fps)
    sampSize = 500
    parmKind = 9
    Do you think those values are set up correctly? When I run “HList -h” an error number 1113 is shown which and from the book it represents that the file might be not correctly formatted. Therefore, I was thinking my parameters might not be set properly.
    Best wishes

  3. it works

    but when i use HErest function it learns the data in the first colum only and discard all the other coloums …

    do u have any idea about what cause this problem?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>