📄 hsv32image.cc
字号:
///////////////////////////////////////////////////////////////////////////////// //// HSV32Image.cc --- most of this was copied from RGB32Image.cc //// //// HSV image class derived from RGB32Image class //// //// Author : Nils T Siebel (nts), RGB32Image.cc by Adam M Baumberg //// Created : Thu Apr 19 11:59:19 BST 2001 //// Revision : 0.0 of Thu Apr 19 11:59:19 BST 2001 //// Copyright : The University of Reading //// /////////////////////////////////////////////////////////////////////////////////static const char *HSV32Image_Revision = "@(#) HSV32Image.cc, rev 0.0 of Thu Apr 19 11:59:19 BST 2001, Authors Adam M Baumberg (RGB32 basis) and Nils T Siebel (all HSV stuff), Copyright (c) 2001 The University of Reading";#include <math.h> // for fmin, fmax#include <iostream>#include "HSV32Image.h"#include "Grey8Image.h"#include "text_output.h"#ifndef NO_DISPLAY#ifdef USE_GL#include <gl/gl.h>#else#include <X11/X.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/Xatom.h>#endif#endif#include "tracker_defines_types_and_helpers.h"namespace ReadingPeopleTracker{// definition and initialisation of static member variablesconst char *HSV32Image::RGB32_to_HSV32_lookup_table_filename ="/advisor/nils/bin/RGB32_to_HSV32_lookup_table";// 64 MB lookup table for RGB->HSV. set up using member function defined belowHSV32pixel *HSV32Image::RGB32_to_HSV32_lookup_table = NULL;// write out an HSV32pixel as (h,s,v) tripletostream &operator<< (ostream &target, const HSV32pixel &HSVpix){ target << "("; u_int32_t AX = 0; *((unsigned char*) &AX) = HSVpix.H; target << AX << ","; AX = 0; *((unsigned char*) &AX) = HSVpix.S; target << AX << ","; AX = 0; *((unsigned char*) &AX) = HSVpix.V; target << AX << ")"; return target;}// FIXME: This implementation is very slow.HSV32pixel HSV32Image::to_HSV32 (const RGB32pixel *RGBpix){ HSV32pixel res; // calculate HSV (after D Travis) float R = ((float) (unsigned int) RGBpix->red) / 255; float G = ((float) (unsigned int) RGBpix->green) / 255; float B = ((float) (unsigned int) RGBpix->blue) / 255; float min_RGB = fmin(fmin(R,G),B); float max_RGB = fmax(fmax(R,G),B); float S = (max_RGB == 0) ? 1 : (max_RGB - min_RGB) / max_RGB; float V = max_RGB; float H; if (S == 0) H = 0; // in fact, undefined (colour has no hue) else { float Rdash = (max_RGB - R) / (max_RGB - min_RGB); float Gdash = (max_RGB - G) / (max_RGB - min_RGB); float Bdash = (max_RGB - B) / (max_RGB - min_RGB); if ((R == max_RGB) && (G == min_RGB)) H = 5 + Bdash; else if (R == max_RGB) H = 1 - Gdash; else if ((G == max_RGB) && (B == min_RGB)) H = 1 + Rdash; else if (G == max_RGB) H = 3 - Bdash; else if (R == max_RGB) H = 3 + Gdash; else H = 5 - Rdash; } // gives H \in [0..6] H = H / 6; res.H = (int) (255 * H); res.S = (int) (255 * S); res.V = (int) (255 * V); return res;}// This lookup version uses a 64 MB lookup table (but in spite of guaranteed// cache misses it is still faster than the calculation) --- nts.HSV32pixel HSV32Image::to_HSV32_using_lookup (const RGB32pixel *RGBpix){ if (RGB32_to_HSV32_lookup_table == NULL) // better check... { cerror << " Warning: to_HSV32_using_lookup: NULL table! " << endl; return to_HSV32 (RGBpix); } else { return RGB32_to_HSV32_lookup_table [(((RGBpix->red << 8) + RGBpix->blue) << 8) + RGBpix->green]; }}inline unsigned int HSV32Image::to_uint(const HSV32pixel colour){ return * ((unsigned int*) &colour);}// set up the lookup table for to_HSV32_using_lookupvoid HSV32Image::setup_HSV32_to_RGB32_lookup_table(){ if (RGB32_to_HSV32_lookup_table != NULL) // don't allocate 64 MB twice! { cerror << " setup_HSV32_to_RGB32_lookup_table(): Warning: alloc requested" << " when table was already set up? " << endl; return; // further operation is possible assuming table is ok. } RGB32_to_HSV32_lookup_table = new HSV32pixel [256 * 256 * 256]; if (RGB32_to_HSV32_lookup_table == NULL) // better check { cerror << " setup_HSV32_to_RGB32_lookup_table(): Warning: could not alloc" << " 64 MB for the lookup table. " << endl; return; // further operation is possible but will be slow w/o lookup } cdebug << " Setting up RGB to HSV lookup table ..."; FILE *infile; // to read a pre-computed version of the table from disk: if ((infile = fopen(RGB32_to_HSV32_lookup_table_filename,"rb")) != NULL) { // try reading the a cached version of the table from file: if (fread(RGB32_to_HSV32_lookup_table, sizeof(HSV32pixel), 256*256*256, infile) == 256*256*256) // reading went ok { cdebug << " (cached)" << endl << endl; return; } } // use this and the 2 lines below if you want to write a new table...// FILE *outfile = fopen(RGB32_to_HSV32_lookup_table,"wb"); RGB32pixel colour; colour.alpha = 0x00; HSV32pixel *colourindex = & (RGB32_to_HSV32_lookup_table[0]); for (unsigned int red = 0; red < 256; red++) { colour.red = red; for (unsigned int green = 0; green < 256; green++) { colour.green = green; for (unsigned int blue = 0; blue < 256; blue++) { colour.blue = blue; *colourindex++ = to_HSV32(&colour); } } } // do this to write out the table (once)// fwrite(RGB32_to_HSV32_lookup_table,sizeof(HSV32pixel),256*256*256,outfile);// fclose(outfile); cdebug << " done." << endl << endl;}Image *HSV32Image::copy(Image *res){ if (res == NULL) res = new HSV32Image(width, height, frame_id, frame_time_in_ms); else { // check destination image format and dimensions if ((res->get_image_type() != HSV32) || (res->get_width() != width) || (res->get_height() != height)) { cerror << " HSV32Image::copy: cannot copy to resulting image of different type/dimensions " << endl; exit(1); } // use same frame id and time since it is the same image res->set_frame_id(frame_id); res->set_frame_time_in_ms(frame_time_in_ms); } res->set_timestamp(×tamp); void *src = data; void *dest = res->get_data(); size_t n = (width * height) << 2; memcpy(dest, src, n); return res;}//// Threshold to grey (values MARK and CLEAR_MARK)//// FIXME: uses only V for now.Image *HSV32Image::threshold(unsigned int threshold, Image *res, unsigned int *no_marked){ if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); // row and column counters... unsigned int row; unsigned int col; // pointers to data: columns of image and result HSV32pixel *image_col; unsigned char *result_col; register unsigned int sum; unsigned int colour_threshold = threshold; unsigned int mark_count = 0; for (row = 0; row < height; row++) { image_col = (HSV32pixel*) get_pixel(0,row); result_col = res -> get_pixel(0,row); for (col = 0; col < width; col++) { sum = (unsigned int) image_col++ -> V; if (sum <= colour_threshold) *result_col++ = CLEAR_MARK; else { *result_col++ = MARK; mark_count++; } } } if (no_marked != NULL) *no_marked = mark_count; return res;}//// "ColourFilter" to grey //// for experimentsImage *HSV32Image::ColourFilter (Image *res, ColourFilteringMethod method){ if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); // row and column counters... unsigned int row; unsigned int col; // pointers to data: columns of image and result HSV32pixel *image_col; unsigned char *result_col; unsigned int grey; // FIXME: should put switch out of loop or use several inline // functions (pointed to) or something. No time. for (row = 0; row < height; row++) { image_col = (HSV32pixel*) get_pixel(0,row); result_col = res -> get_pixel(0,row); for (col = 0; col < width; col++) { switch (method) {// Simple norm methods case CF_METHOD_1_NORM: // 1-norm of (H,S,V) { grey = ((unsigned int) image_col->H + (unsigned int) image_col->S + (unsigned int) image_col->V + 1) / 3; break; } case CF_METHOD_2_NORM: // 2-norm of (H,S,V) { grey = (unsigned int) (sqrt( ((float) ((SQUARE ((unsigned int) image_col->H)) +(SQUARE ((unsigned int) image_col->S)) +(SQUARE ((unsigned int) image_col->V)))) / 3)); break; } case CF_METHOD_MAX_NORM: // max-norm of (H,S,V) { grey = MAX(MAX((unsigned int) image_col->H, (unsigned int) image_col->S), (unsigned int) image_col->V); break; } // HSV after D Travis. This is easy with this image class... case CF_METHOD_H: { grey = image_col->H; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -