/*---------------------------------------------------------------------------*
* IT++ *
*---------------------------------------------------------------------------*
* Copyright (c) 1995-2004 by Tony Ottosson, Thomas Eriksson, Pål Frenger, *
* Tobias Ringström, and Jonas Samuelsson. *
* *
* Permission to use, copy, modify, and distribute this software and its *
* documentation under the terms of the GNU General Public License is hereby *
* granted. No representations are made about the suitability of this *
* software for any purpose. It is provided "as is" without expressed or *
* implied warranty. See the GNU General Public License for more details. *
*---------------------------------------------------------------------------*/
/*!
\file
\brief Vector quantizer class (unconstrained)
\author Thomas Eriksson
1.14
2004/09/29 12:28:06
*/
#include "srccode/vq.h"
#include "base/matfunc.h"
#include <fstream>
#include <string>
using std::ifstream;
using std::ofstream;
using std::cout;
using std::endl;
namespace itpp {
//--------------------------------------------------------------------
// class VQ
//--------------------------------------------------------------------
VQ::VQ() : CodeBook()
{
LatestDist=0;
Size=0;
Dim=0;
}
VQ::VQ(const char *Name) : CodeBook()
{
LatestDist=0;
Size=0;
Dim=0;
load(Name);
}
int VQ::encode(const vec &x)
{
int i;
double S,MinS=1.0E30F;
int MinIndex=0;
int j,pos=0;
double a;
for (i=0;i<Size;i++) {
S=0;
for (j=0;j<Dim;j++) {
a=x._elem(j)-CodeBook._elem(pos+j);
S+=a*a;
if (S>=MinS) goto sune;
}
MinS=S;
MinIndex=i;
sune: pos+=Dim;
}
LatestDist=MinS;
return MinIndex;
}
ivec VQ::encode(const vec &x, int num)
{
double S,a;
vec MinS(num);
ivec MinIndex(num);
int i,j,index,pos=0;
MinS.clear();MinS+=1.0E30F;
MinIndex.clear();
for (i=0;i<Size;i++) {
S=0;
for (j=0;j<Dim;j++) {
a=x._elem(j)-CodeBook._elem(pos+j);
S+=a*a;
if (S>=MinS[num-1]) goto sune;
}
for (index=num-2;(index>=0) && (S<MinS[index]);index--);
for (j=MinS.length()-2;j>index;j--) {
MinS[j+1]=MinS[j];// memcpy, memmov
MinIndex[j+1]=MinIndex[j];
}
MinS[index+1]=S;
MinIndex[index+1]=i;
sune: pos+=Dim;
}
LatestDist=MinS[0];
return MinIndex;
}
Array<vec> VQ::decode(const ivec &Index) const
{
Array<vec> Temp(Index.length());
for (int i=0;i<Temp.length();i++) {
Temp(i)=get_codevector(Index(i));
}
return Temp;
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
ifstream &operator>>( ifstream &ifs, vec &v)
{
int i;
char str[2000];
char *ptr,*ptr_old;
bool flag;
if (length(v)!=0) {
for (i=0;i<length(v);i++) {
ifs.operator>>(v[i]) ;
}
} else {
v.set_length(50);
ifs.getline(str,2000);
if (strlen(str)==0) ifs.getline(str,2000);
i=0;
v[i++]=atof(str);
ptr=str;
ptr_old=ptr;
ptr=strchr(ptr,' ');
while (ptr==ptr_old) {
ptr++;
ptr_old=ptr;
ptr=strchr(ptr,' ');
}
while (ptr) {
if (i>=v.length()) v.set_length(2*v.length(),true);
v[i++]=atof(ptr);
ptr_old=ptr;
ptr=strchr(ptr,' ');
while (ptr==ptr_old) {
ptr++;
ptr_old=ptr;
ptr=strchr(ptr,' ');
}
}
flag=true;
flag=false;
v.set_length(i,true);
}
return ifs;
}
#endif //DOXYGEN_SHOULD_SKIP_THIS
void VQ::load(const char *Name)
{
mat Temp;
ifstream CodeBookFile(Name);
vec v;
int n;
it_error_if(!CodeBookFile,std::string("VQ::load : cannot open file ")+Name);
cout << "Reading the codebook " << Name ; cout.flush() ;
CodeBookFile >> v ;
Temp.set_size(16,length(v));
n=0;
while (!CodeBookFile.eof()) {
if (n>=Temp.rows()) Temp.set_size(2*Temp.rows(),Temp.cols(),true);
Temp.set_row(n++,v);
CodeBookFile >> v ;
}
Temp.set_size(n,Temp.cols(),true);
set_codebook(Temp);
cout << " size:" << size() << " dim:" << dim() << endl ;
}
void VQ::save(const char *Name) const
{
ofstream CodeBookFile(Name);
cout << "Saving the codebook " << Name << endl ;
for (int i=0;i<Size;i++) {
vec v=CodeBook.mid(i*Dim,Dim);
for (int j=0;j<v.length();j++) {
CodeBookFile.operator<<(v[j]);
if (j<v.length()-1) CodeBookFile.put(' ') ;
}
CodeBookFile << endl ;
}
CodeBookFile.close();
}
void VQ::modify_codevector(int no, double mul, const vec &add)
{
int pos=Dim*no;
for (int i=0;i<Dim;i++) {
CodeBook._elem(pos+i)*=mul;
CodeBook._elem(pos+i)+=add[i];
}
}
vec VQ::get_codevector(int Index) const
{
return CodeBook.mid(Index*Dim,Dim);
}
void VQ::set_codevector(int Index, const vec &v)
{
it_error_if(Dim!=length(v),"VQ::set_codevector : Wrong dimension");
for (int i=0;i<length(v);i++) {
CodeBook._elem(Index*Dim+i)=v._elem(i);
}
}
void VQ::set_codebook(const mat &CB)
{
Size=CB.cols();
Dim=CB.rows();
CodeBook.set_length(Size*Dim);
for (int i=0;i<Size;i++) {
for (int j=0;j<Dim;j++) {
CodeBook(i*Dim+j)=CB(j,i);
}
}
}
mat VQ::get_codebook() const
{
mat CB(Dim,Size);
for (int i=0;i<Size;i++) {
for (int j=0;i<Dim;i++) {
CB(j,i)=CodeBook(i*Dim+j);
}
}
return CB;
}
} //namespace itpp
syntax highlighted by Code2HTML, v. 0.9.1