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

📄 cmvision.cpp

📁 1394 接口视觉工具箱 (英文工具箱
💻 CPP
📖 第 1 页 / 共 2 页
字号:
      slot = ((p->area) >> shift) & CMV_RMASK;
      p->next = tbl[slot];
      tbl[slot] = p;
      p = pn;
    }

    // integrate back into partially ordered list
    list = NULL;
    for(j=0; j<CMV_RADIX; j++){
      p = tbl[j];
      tbl[j] = NULL;  // clear out table for next pass
      while(p){
        pn = p->next;
        p->next = list;
        list = p;
        p = pn;
      }
    }
  }

  return(list);
}

void CMVision::sortRegions(int max_area)
// Sorts entire region table by area, using the above
// function to sort each threaded region list.
{
  int i,p;

  // do minimal number of passes sufficient to touch all set bits
  p = top_bit((max_area + CMV_RBITS-1) / CMV_RBITS);

  // sort each list
  for(i=0; i<CMV_MAX_COLORS; i++){
    region_list[i] = sortRegionListByArea(region_list[i],p);
  }
}

int CMVision::mergeRegions(region *p,int num,double density_thresh)
// Looks through regions and merges pairs of the same color that would
// have a high density after combining them (where density is the area
// in pixels of the region divided by the bounding box area).  This
// implementation sucks, and I promise real spatial data structures in
// the future so n^2 ugliness like this is not necessary.
{
  region *q,*s;
  int l,r,t,b;
  int a;
  int merged;

  merged = 0;

  while(p && merged<num){
    q = p->next;
    s = p;

    while(q){
      // find union box and get its total area
      l = min(p->x1,q->x1);
      r = max(p->x2,q->x2);
      t = min(p->y1,q->y1);
      b = max(p->y2,q->y2);
      a = (r-l) * (b-t);

      // if density of merged region is still above threshold
      if((double)(p->area + q->area) / a > density_thresh){
	// merge them to create a new region
	a = p->area + q->area;
	p->x1 = l;
	p->x2 = r;
	p->y1 = t;
	p->y2 = b;
	p->cen_x = ((p->cen_x * p->area) + (q->cen_x * q->area)) / a;
	p->cen_y = ((p->cen_y * p->area) + (q->cen_y * q->area)) / a;
	p->area = a;

	// remove q from list (old smaller region)
	q = q->next;
	s->next = q;
	merged++;
      }else{
	s = q;
	q = q->next;
      }
    }
    p = p->next;
  }

  return(merged);
}

int CMVision::mergeRegions()
// Apply merge operation to all regions using the above function.
{
  int i,m;
  int num;

  num = 0;

  for(i=0; i<CMV_MAX_COLORS; i++){
    m = mergeRegions(region_list[i],colors[i].expected_num,colors[i].merge);
    region_count[i] -= m;
    num += m;
  }

  return(num);
}

//==== Interface/Public Functions ==================================//

#define ZERO(x) memset(x,0,sizeof(x))

void CMVision::clear()
{
  ZERO(y_class);
  ZERO(u_class);
  ZERO(v_class);

  ZERO(region_list);
  ZERO(region_count);

  ZERO(colors);

  map = NULL;
}

bool CMVision::initialize(int nwidth,int nheight)
// Initializes library to work with images of specified size
{
  width = nwidth;
  height = nheight;

  if(map) delete(map);

  map = new unsigned[width * height + 1];
  // Need 1 extra element to store terminator value in encodeRuns()

  options = CMV_THRESHOLD;

  return(map != NULL);
}

// sets bits in k in array arr[l..r]
template <class num>
void set_bits(num *arr,int len,int l,int r,num k)
{
  int i;

  l = max(l,0);
  r = min(r+1,len);

  for(i=l; i<r; i++) arr[i] |= k;
}

template <class num>
void clear_bits(num *arr,int len,int l,int r,num k)
{
  int i;

  l = max(l,0);
  r = min(r+1,len);

  k = ~k;
  for(i=l; i<r; i++) arr[i] &= k;
}

#define CMV_STATE_SCAN   0
#define CMV_STATE_COLORS 1
#define CMV_STATE_THRESH 2
#define CMV_MAX_BUF 256

int CMVision::loadOptions(char *filename)
//bool CMVision::loadOptions(char *filename)
// Loads in options file specifying color names and representative
// rgb triplets.  Also loads in color class threshold values.
{
  char buf[CMV_MAX_BUF],str[CMV_MAX_BUF];
  FILE *in;
  int state,i,n;

  int r,g,b;
  int exp_num;
  double merge;
  color_info *c;

  int y1,y2,u1,u2,v1,v2;
  unsigned k;

  // Open options file
  in = fopen(filename,"rt");
  if(!in) return(false);

  // Clear out previously set options
  for(i=0; i<CMV_COLOR_LEVELS; i++){
    y_class[i] = u_class[i] = v_class[i] = 0;
  }
  for(i=0; i<CMV_MAX_COLORS; i++){
    if(colors[i].name){
      delete(colors[i].name);
      colors[i].name = NULL;
    }
  }

	// Loop ever lines, processing via a simple parser
	state = 0;
	while(fgets(buf, CMV_MAX_BUF, in)) {
		
		switch(state) {
			
		case CMV_STATE_SCAN:

			n = sscanf(buf, "[%s", str);
			if(n == 1) {
				if(!strnicmp(str,"colors]",CMV_MAX_BUF)) {
					state = CMV_STATE_COLORS;
					i = 0;
				} else if(!strnicmp(str,"thresholds]",CMV_MAX_BUF)) {
					state = CMV_STATE_THRESH;
					i = 0;
				} else {
					printf("CMVision: Ignoring unknown option header '%s'.\n", str);
				}
			}
			
			break;

		case CMV_STATE_COLORS:
			
			n = sscanf(buf,"(%d, %d, %d) %lf %d %s", &r, &g, &b, &merge, &exp_num, str);
	        if(n == 6) {

				//printf("(%d,%d,%d) %lf %d '%s'\n", r,g,b,merge,exp_num,str); fflush(stdout);
				if(i < CMV_MAX_COLORS) {
					c = &colors[i];
					c->color.red   = r;
					c->color.green = g;
					c->color.blue  = b;
					c->name  = strdup(str);
					c->merge = merge;
					c->expected_num = exp_num;
					i++;
				
				} else {
					printf("CMVision: Too many colors, ignoring '%s'.\n",str);
				}
			} else if(n == 0) {
				state = CMV_STATE_SCAN;
			}
			
			break;

		case CMV_STATE_THRESH:

			n = sscanf(buf,"(%d:%d,%d:%d,%d:%d)",&y1,&y2,&u1,&u2,&v1,&v2);
			if(n == 6) {
				
				//printf("(%d:%d,%d:%d,%d:%d)\n",y1,y2,u1,u2,v1,v2);
				if(i < CMV_MAX_COLORS) {
					c = &colors[i];
					c->y_low = y1;  c->y_high = y2;
					c->u_low = u1;  c->u_high = u2;
					c->v_low = v1;  c->v_high = v2;

					k = (1 << i);
					set_bits(y_class,CMV_COLOR_LEVELS,y1,y2,k);
					set_bits(u_class,CMV_COLOR_LEVELS,u1,u2,k);
					set_bits(v_class,CMV_COLOR_LEVELS,v1,v2,k);
					i++;
				} else {
					printf("CMVision: Too many thresholds.\n");
				}
			
			} else if(n == 0) {
				state = CMV_STATE_SCAN;
			}
		
			break;
		
		} /* switch */
	} /* while */

  /*
  for(i=0; i<CMV_COLOR_LEVELS; i++){
    printf("%08X %08X %08X\n",y_class[i],u_class[i],v_class[i]);
  }
  */

  fclose(in);

  return(true);
}

bool CMVision::saveOptions(char *filename)
{
  color_info *c;
  FILE *out;
  int i;

  out = fopen(filename,"wt");
  if(!out) return(false);

  fprintf(out,"[Colors]\n");
  i = 0;
  while(colors[i].name){
    c = &colors[i];
    fprintf(out,"(%3d,%3d,%3d) %6.4lf %d %s\n",
      c->color.red,c->color.green,c->color.blue,
      c->merge,c->expected_num,c->name);
    i++;
  }

  fprintf(out,"\n[Thresholds]\n");
  i = 0;
  while(colors[i].name){
    c = &colors[i];
    fprintf(out,"(%3d:%3d,%3d:%3d,%3d:%3d)\n",
      c->y_low,c->y_high,
      c->u_low,c->u_high,
      c->v_low,c->v_high);
    i++;
  }

  fclose(out);

  return(true);
}

bool CMVision::enable(unsigned opt)
{
  unsigned int valid;

  valid = opt & CMV_VALID_OPTIONS;
  options |= valid;

  return(opt == valid);
}

bool CMVision::disable(unsigned opt)
{
  unsigned int valid;

  valid = opt & CMV_VALID_OPTIONS;
  options &= ~valid;

  return(opt == valid);
}

void CMVision::close()
{
  if(map) delete(map);
  map = NULL;
}


//==== Vision Testing Functions ====================================//

bool CMVision::testClassify(rgb * restrict out,image_pixel * restrict image)
{
  int i,s;
  rgb black = {0,0,0};

  if(!image || !out) return(false);

  classifyFrame(image,map);

  s = width * height;

  i = 0;
  while(i < s){
    while(i<s && !map[i]){
      out[i] = black;
      i++;
    }
    while(i<s && map[i]){
      out[i] = colors[bottom_bit((int)map[i])-1].color;
      i++;
    }
  }

  return(true);
}

bool CMVision::getThreshold(int color,
       int &y_low,int &y_high,
       int &u_low,int &u_high,
       int &v_low,int &v_high)
{
  color_info *c;

  if(color<0 || color>=CMV_MAX_COLORS) return(false);

  c = &colors[color];
  y_low = c->y_low;  y_high = c->y_high;
  u_low = c->u_low;  u_high = c->u_high;
  v_low = c->v_low;  v_high = c->v_high;

  return(true);
}

bool CMVision::setThreshold(int color,
       int y_low,int y_high,
       int u_low,int u_high,
       int v_low,int v_high)
{
  color_info *c;
  unsigned k;

  if(color<0 || color>=CMV_MAX_COLORS) return(false);

  c = &colors[color];
  k = 1 << color;

  clear_bits(y_class,CMV_COLOR_LEVELS,c->y_low,c->y_high,k);
  clear_bits(u_class,CMV_COLOR_LEVELS,c->u_low,c->u_high,k);
  clear_bits(v_class,CMV_COLOR_LEVELS,c->v_low,c->v_high,k);

  c->y_low = y_low;  c->y_high = y_high;
  c->u_low = u_low;  c->u_high = u_high;
  c->v_low = v_low;  c->v_high = v_high;

  set_bits(y_class,CMV_COLOR_LEVELS,y_low,y_high,k);
  set_bits(u_class,CMV_COLOR_LEVELS,u_low,u_high,k);
  set_bits(v_class,CMV_COLOR_LEVELS,v_low,v_high,k);

  return(true);
}

//==== Main Vision Functions =======================================//

bool CMVision::processFrame(image_pixel *image)
{
  int runs;
  int regions;
  int max_area;

  if(!image) return(false);

  if(options & CMV_THRESHOLD){

    classifyFrame(image,map);
    runs = encodeRuns(rmap,map);
    connectComponents(rmap,runs);

    regions = extractRegions(region_table,rmap,runs);

    if(options & CMV_COLOR_AVERAGES){
      calcAverageColors(region_table,regions,image,rmap,runs);
    }

    max_area = separateRegions(region_table,regions);
    sortRegions(max_area);

    if(options & CMV_DENSITY_MERGE){
      mergeRegions();
    }
  }

  return(true);
}

bool CMVision::processFrame(unsigned *map)
{
  int runs;
  int regions;
  int max_area;

  if(!map) return(false);

  runs = encodeRuns(rmap,map);
  connectComponents(rmap,runs);

  regions = extractRegions(region_table,rmap,runs);

  // if(options & CMV_COLOR_AVERAGES){
  //   calcAverageColors(region_table,regions,image,rmap,runs);
  // }

  max_area = separateRegions(region_table,regions);
  sortRegions(max_area);

  if(options & CMV_DENSITY_MERGE){
    mergeRegions();
  }

  return(true);
}

int CMVision::numRegions(int color_id)
{
  if(color_id<0 || color_id>=CMV_MAX_COLORS) return(CMV_NONE);
  return(region_count[color_id]);
}

CMVision::region *CMVision::getRegions(int color_id)
{
  if(color_id<0 || color_id>=CMV_MAX_COLORS) return(NULL);
  return(region_list[color_id]);
}

⌨️ 快捷键说明

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