⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 labels.cpp

📁 face recognition test source code
💻 CPP
字号:
/************************************************************************
 *                                                                      *
 *  Program packages 'lvq_pak' and 'som_pak' :                          *
 *                                                                      *
 *  labels.c                                                            *
 *   - routines for manipulating labels                                 *
 *                                                                      *
 *  Version 3.0                                                         *
 *  Date: 1 Mar 1995                                                    *
 *                                                                      *
 *  NOTE: This program package is copyrighted in the sense that it      *
 *  may be used for scientific purposes. The package as a whole, or     *
 *  parts thereof, cannot be included or used in any commercial         *
 *  application without written permission granted by its producents.   *
 *  No programs contained in this package may be copied for commercial  *
 *  distribution.                                                       *
 *                                                                      *
 *  All comments  concerning this program package may be sent to the    *
 *  e-mail address 'lvq@cochlea.hut.fi'.                                *
 *                                                                      *
 ************************************************************************/

#include "header.h"
#include <string.h>
#include "lvq_pak.h"
#include "labels.h"
#include "errors.h"

/******************************************************************* 
 * Conversion between labels and indices                           * 
 *******************************************************************/

#ifndef LABEL_ARRAY_SIZE
#define LABEL_ARRAY_SIZE 100
#endif /* LABEL_ARRAY_SIZE */

static char **labels = NULL;
static int num_labs = 0;
static int lab_array_size = 0;
  
/* enlarge_array - enlarges (or allocates) the array used to store 
   the labels. */

static int enlarge_array()
{
  char **labs = NULL;

  lab_array_size += LABEL_ARRAY_SIZE;
  labs = (char**)realloc(labels, sizeof(char *) * lab_array_size);
  
  if (labs == NULL)
    {
      Msg(0, "Can't allocate memory for labeltable \n");
      return ERR_NOMEM;
    }
  labels = labs;
  return 0;
}

/* free_labels - Free all the memory used by label list */

void free_labels()
{
  if (labels)
    free(labels);

  labels = NULL;
  num_labs = lab_array_size = 0;
}

/* find_conv_to_ind - Give the corresponding index; if the label is
   not yet there, add it to table. Empty label is always 0 */

int find_conv_to_ind(char *lab)
{
  int i, label;
  char *tmp;

  /* no string == empty label */
  if (lab == NULL)
    return LABEL_EMPTY;

  /* empty string == empty label */
  if (lab[0] == '\0')
    return LABEL_EMPTY;

  /* check if the label is already in the table */
  label = -1;
  for (i = 0; i < num_labs; i++)
    if (strcmp(labels[i], lab) == 0)
      {
	label = i;
	break;
      }
  
  if (label < 0)
    {
      /* label not found in array. Add it. */
      label = num_labs;
      if (label >= lab_array_size)
	if (enlarge_array())
	  return -1;
      
      if ((tmp = ostrdup(lab)) == NULL)
	return -1;
      
      labels[label] = tmp;
      num_labs++;
    }

  return(label + 1);
}

/* find_conv_to_lab - Give the corresponding label; if the index is
   not yet there, return NULL */

char *find_conv_to_lab(int ind)
{
  
  if (ind == LABEL_EMPTY)
    return NULL;

  if ((ind > num_labs) || (ind < 0))
    return NULL;

  return labels[ind - 1];
}

/* number_of_labels - Give the number of entries in the label table
   (including the empty label *) */

int number_of_labels()
{
  return (num_labs + 1); /* number of labels in array + empty label */
}

/* ********** Routines for manipulating labels ******************** */

/* labels are stored in the following way: If there is only one label,
   store it in the labels pointer.  If there are multiple labels, the
   labels entry is a pointer to an array of labels. The num_labs field
   in the entry tells the number of labels in that entry */

/* set_entry_label - sets the label on one data entry. All previous 
   labels are discarded. */

int set_entry_label(struct data_entry *entry, int label)
{
  clear_entry_labels(entry); /* remove previous labels if any */
  if (label != LABEL_EMPTY)  /* empty label == no label */
    {
      entry->lab.label = label;
      entry->num_labs = 1;
    }
  return 0;
}

/* get_entry_labels - get i:th label from entry (i starts from 0). */

int get_entry_labels(struct data_entry *entry, int i)
{

  if ((entry->num_labs <= 1) && (i == 0))
    return entry->lab.label;
  
  if (i >= entry->num_labs)
    return LABEL_EMPTY;
  else
    return entry->lab.label_array[i];
}

/* clear_entry_label - remove all labels from entry. */

void clear_entry_labels(struct data_entry *entry)
{
  if (entry->num_labs > 1)
    free(entry->lab.label_array);

  entry->num_labs = 0;
  entry->lab.label = LABEL_EMPTY;
}

#define ATABLE_INCREMENT 8

/* add_entry_label - add a label to entry. Returns non-zero on error. */

int add_entry_label(struct data_entry *entry, int label)
{
  int *atable = NULL;

  clear_err();

  /* adding an empty label does nothing */
  if (label == LABEL_EMPTY)
    return 0;
  
  /* add first label to entry */
  if (entry->num_labs == 0)
    {
      entry->num_labs = 1;
      entry->lab.label = label;
      return 0;
    }

  /* if there is already one label, we need to allocate a table for the 
     labels */

  if (entry->num_labs == 1)
    {
      atable = (int*)malloc(sizeof(int) * ATABLE_INCREMENT);
      if (atable == NULL)
	return ERR_NOMEM;
      
      /* move old entry to table and add the new label */
      entry->num_labs++;
      atable[0] = entry->lab.label;
      atable[1] = label;
      entry->lab.label_array = atable;
      return 0;
    }

  atable = entry->lab.label_array;

  /* enlarge label array if needed */
  if ((entry->num_labs % ATABLE_INCREMENT) == 0)
    {
      /* need more space */
      atable = (int*)realloc(atable,
		       sizeof(int) * (entry->num_labs + ATABLE_INCREMENT));
      if (atable == NULL)
	return ERR_NOMEM;
      entry->lab.label_array = atable;
    }

  atable[entry->num_labs++] = label;
      
  return 0;
}

/* copy_entry_labels - copy all labels from one entry to the other. */

int copy_entry_labels(struct data_entry *dest, struct data_entry *source)
{
  int blocks, size, *atable;
  
  clear_err();

  clear_entry_labels(dest); /* remove old labels first */

  if (source->num_labs <= 1)
    dest->lab.label = source->lab.label;
  else
    {
      blocks = (source->num_labs + ATABLE_INCREMENT - 1) / ATABLE_INCREMENT;
      size = sizeof(int) * blocks * ATABLE_INCREMENT;
      atable = (int*)malloc(size);
      if (atable == NULL)
	return ERR_NOMEM;
      memcpy(atable, source->lab.label_array, size);
      dest->lab.label_array = atable;
    }
  dest->num_labs = source->num_labs;

  return 0;
}

/* ********************************************************************** */

/* hitlists - hitlist is a list of label,frequency pairs that is kept sorted 
   so that the label with the highest frequency is always the first in the
   list. */

/* initialize a new hitlist */

struct hitlist *new_hitlist(void)
{
  struct hitlist *hl;

  clear_err();

  hl = (struct hitlist *)malloc(sizeof(struct hitlist));
  if (hl == NULL)
    {
      ERROR(ERR_NOMEM);
      return NULL;
    }

  hl->head = hl->tail = NULL;
  hl->entries = 0;
  
  return hl;
}

/* clear_hitlist - clears all entries from a hitlist */

void clear_hitlist(struct hitlist *hl)
{
  struct hit_entry *he, *next;
  if (hl)
    {
      for (he = hl->head; he; he = next)
	{
	  next = he->next;
	  free(he);
	}

      hl->head = hl->tail = NULL;
    }
}

/* free_hitlist - deallocate a hitlist */

void free_hitlist(struct hitlist *hl)
{
  if (hl)
    {
      clear_hitlist(hl); /* deallocate hits */
      free(hl);
    }
}

/* find_hit - find a hit_entry corresponding to a certain label from
   list. Returns NULL if there is no entry for the label */

struct hit_entry *find_hit(struct hitlist *hl, long label)
{
  struct hit_entry *he;

  for(he = hl->head; he; he = he->next)
    if (label == he->label)
      break;

  return he;
}

/* hit_swapwprev - (internal) exchange a hit entry with the previous
   hit in the list. Used to keep the list in order */

static struct hit_entry *hit_swapwprev(struct hitlist *hl, struct hit_entry *he)
{
  struct hit_entry *prev;
  
  prev = he->prev;

  if (prev)
    {
      prev->next = he->next;
      he->prev = prev->prev;
      he->next = prev;
      prev->prev = he;
      if (prev->next == NULL)
	hl->tail = prev;
      else
	prev->next->prev = prev;
      if (he->prev == NULL)
	hl->head = he;
      else 
	he->prev->next = he;
    }

  return he;
}

/* add_hit - add a hit in the list for a label */

int add_hit(struct hitlist *hl, long label)
{
  struct hit_entry *he;

  he = find_hit(hl, label);
  
  if (he)
    {
      /* found in list, increase counter */
      he->freq++;

      /* keep list in order, higher frequencies are in the beginning. */
      while (he->prev)
	if (he->prev->freq < he->freq)
	  he = hit_swapwprev(hl, he);
	else
	  break;
    }
  else
    {
      he = (struct hit_entry *)malloc(sizeof(struct hit_entry));
      if (he == NULL)
	{
	  ERROR(ERR_NOMEM);
	  return 0;
	}
      /* add to end of list */
      he->next = NULL;
      he->prev = hl->tail;
      he->label = label;
      he->freq = 1;
      hl->tail = he;
      if (he->prev)
	he->prev->next = he;
      else
	hl->head = he;
      hl->entries++;
    }

  return he->freq;
}

/* print_hitlist - prints the contents of a hitlist */

void print_hitlist(struct hitlist *hl, FILE *fp)
{
  struct hit_entry *he;
  int lab;

  for (he = hl->head; he; he = he->next)
    {
      lab = he->label;
       Msg(0, "%s,%d", 
	      (lab != LABEL_EMPTY) ? find_conv_to_lab(lab) : "EMPTY",
	      he->freq);
      if (he->next)
	fputs(", ", fp);
    }
  fputs("\n", fp);
}

/* hitlist_label_freq - returns the counter value for a label. If the
   label is not in the list returns 0 (naturally) */

int hitlist_label_freq(struct hitlist *hl, long label)
{
  struct hit_entry *he;

  for (he = hl->head; he != NULL; he = he->next)
    if (he->label == label)
      return he->freq;
  
  return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -