www.pudn.com > ReadingPeopleTracker-1.28.rar > Grey8Image.cc
/* * Grey8Image.cc * Image class for 8-bit greylevel images * * author : A M Baumberg */ #include "Grey8Image.h" #include#include #include #include #include #include "Kernel.h" #include "RGB32Image.h" #include "Point2.h" #include "text_output.h" #include "tracker_defines_types_and_helpers.h" #ifndef NO_DISPLAY #ifdef USE_GL #include #else #include #include #include #include #endif #endif // #ifndef NO_DISPLAY namespace ReadingPeopleTracker { // definition and initialisation of static member variables const int Grey8Image::BOX_SIZE = 8; // definition and initialisation of static member variables #ifndef NO_DISPLAY #ifndef USE_GL // definition and initialisation of X11 interface specific static member variables Grey8Image::Colormap cmap = 0; int Grey8Image::no_using_cmap = 0; unsigned char Grey8Image::pixel; //unsigned long plane_masks[8]; //unsigned int no_planes = 8; unsigned long Grey8Image::reverse_cmap[256]; int Grey8Image::no_grey_cells; #endif // ifndef USE_GL #endif // ifndef NO_DISPLAY Image *Grey8Image::copy(Image *res) const { if (res == NULL) res = (Image *) new Grey8Image(width, height, frame_id, frame_time_in_ms); else { // check destination image format and dimensions assert (res->get_image_type() == GREY8); assert (res->get_width() == width); assert (res->get_height() == height); // 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_draw_colour(Grey8_draw_colour); res->set_timestamp(×tamp); // copy over actual image data... void *src = data; void *dest = res->get_data(); size_t n = width * height; memcpy(dest, src, n); return res; } Image *Grey8Image::resample(unsigned int xstep, unsigned int ystep, Image *resampled) { int new_width = ((width / xstep) / 4) * 4; int new_height = height / ystep; if ((height % ystep) != 0) new_height++; if (resampled == NULL) resampled = new Grey8Image(new_width, new_height, frame_id, frame_time_in_ms); unsigned char *idat; unsigned char *odat; unsigned int outy = 0; for (unsigned int y = 0; y < height; y += ystep) { idat = get_pixel(0,y); odat = resampled->get_pixel(0, outy); for (unsigned int x = 0; x < new_width; x ++) { *odat = *idat; odat++; idat = idat + xstep; } outy++; } return resampled; } void Grey8Image::clear_border() { int w1 = width-1; int h1 = height-1; for (int y = 0; y < height; y++) { *get_pixel(0,y) = CLEAR_MARK; *get_pixel(w1,y) = CLEAR_MARK; } for (int x = 0; x < width; x++) { *get_pixel(x,0) = CLEAR_MARK; *get_pixel(x,h1) = CLEAR_MARK; } } Image *Grey8Image::convolve(Kernel k, Image *convolved) { unsigned char *upnt, *pnt, *dpnt; unsigned char *out; int temp_total; int k11 = k.coeff[0][0], k12 = k.coeff[0][1], k13 = k.coeff[0][2]; int k21 = k.coeff[1][0], k22 = k.coeff[1][1], k23 = k.coeff[1][2]; int k31 = k.coeff[2][0], k32 = k.coeff[2][1], k33 = k.coeff[2][2]; int ksum = abs(k11)+abs(k12)+abs(k13) +abs(k21)+abs(k22)+abs(k23) +abs(k31)+abs(k32)+abs(k33); if (convolved == NULL) convolved = new Grey8Image(width, height, frame_id, frame_time_in_ms); convolved->clear_border(); for (int y = 1; y < (height-1); y++) { upnt = get_pixel(0,y-1); pnt = get_pixel(0,y); dpnt = get_pixel(0,y+1); out = convolved->get_pixel(1,y); for (int x = 1; x < (width-1); x++) { temp_total = k11 * upnt[0] + k12 * upnt[1] + k13 * upnt[2]; temp_total += k21 * pnt[0] + k22 * pnt[1] + k23 * pnt[2]; temp_total += k31 * dpnt[0] + k32 * dpnt[1] + k33 * dpnt[2]; *(out++) = (unsigned char) abs(temp_total / ksum); upnt++; pnt++; dpnt++; } } return convolved; } inline int Grey8Image::compar_char(const void *c1, const void *c2) { return (int) (*((unsigned char *) c1) - *((unsigned char *) c2)); } Image *Grey8Image::neighbour_order(unsigned int n, Image *ordered) { if (ordered == NULL) ordered = new Grey8Image (width, height, frame_id, frame_time_in_ms); ordered->clear_border(); unsigned char table[9]; unsigned char *upnt, *pnt, *dpnt; unsigned char *out; int ntake1 = n - 1; for (int y = 1; y < height-1; y++) { upnt = get_pixel(0,y-1); pnt = get_pixel(0,y); dpnt = get_pixel(0,y+1); out = ordered->get_pixel(1,y); for (int x = 1; x < width-1; x++) { table[0] = upnt[0]; table[1] = upnt[1]; table[2] = upnt[2]; table[3] = pnt[0]; table[4] = pnt[1]; table[5] = pnt[2]; table[6] = dpnt[0]; table[7] = dpnt[1]; table[8] = dpnt[2]; qsort(table, 9, sizeof(unsigned char), &compar_char); *out = table[ntake1]; upnt++; pnt++; dpnt++;out++; } } return ordered; } Image *Grey8Image::minimum(Image *res) { if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); res->clear_border(); unsigned char *upnt, *pnt, *dpnt, min, tmp; unsigned char *out; for (int y = 1; y < height-1; y++) { upnt = get_pixel(0,y-1); pnt = get_pixel(0,y); dpnt = get_pixel(0,y+1); out = res->get_pixel(1,y); for (int x = 1; x < width-1; x++) { min = *upnt; if (min > (tmp = *(upnt + 1))) min = tmp; if (min > (tmp = *(upnt + 2))) min = tmp; if (min > (tmp = *(pnt))) min = tmp; if (min > (tmp = *(pnt + 1))) min = tmp; if (min > (tmp = *(pnt + 2))) min = tmp; if (min > (tmp = *(dpnt))) min = tmp; if (min > (tmp = *(dpnt + 1))) min = tmp; if (min > (tmp = *(dpnt + 2))) min = tmp; *out++ = min; upnt++; pnt++; dpnt++; } } return res; } Image *Grey8Image::maximum(Image *res) { if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); res->clear_border(); unsigned char *upnt, *pnt, *dpnt, max, tmp; unsigned char *out; for (unsigned int y = 1; y < height-1; y++) { upnt = get_pixel(0,y-1); pnt = get_pixel(0,y); dpnt = get_pixel(0,y+1); out = res->get_pixel(1,y); for (unsigned int x = 1; x < width-1; x++) { max = *upnt; if (max < (tmp = *(upnt + 1))) max = tmp; if (max < (tmp = *(upnt + 2))) max = tmp; if (max < (tmp = *(pnt))) max = tmp; if (max < (tmp = *(pnt + 1))) max = tmp; if (max < (tmp = *(pnt + 2))) max = tmp; if (max < (tmp = *(dpnt))) max = tmp; if (max < (tmp = *(dpnt + 1))) max = tmp; if (max < (tmp = *(dpnt + 2))) max = tmp; *out++ = max; upnt++; pnt++; dpnt++; } } return res; } unsigned char Grey8Image::get_mid (unsigned char &a, unsigned char &b, unsigned char &c) { if (a < b) { if (b <= c) return b; else { if (c <= a) return a; else return c; } } else { if (a <= c) return a; else { if (b >= c) return b; else return c; } } } Image *Grey8Image::fmed(Image *res) { if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); res->clear_border(); unsigned char *upnt, *pnt, *dpnt, mid1, mid2, mid3; unsigned char *out; for (int y = 1; y < height-1; y++) { upnt = get_pixel(0,y-1); pnt = get_pixel(0,y); dpnt = get_pixel(0,y+1); out = res->get_pixel(1,y); for (int x = 1; x < width-1; x++) { mid1 = get_mid(upnt[0],upnt[1],upnt[2]); mid2 = get_mid(pnt[0],pnt[1],pnt[2]); mid3 = get_mid(dpnt[0],dpnt[1],dpnt[2]); *out++ = get_mid(mid1, mid2, mid3); upnt++; pnt++; dpnt++; } } return res; } Image *Grey8Image::sobel(unsigned int threshold, Image *hsobel) { unsigned int sqthresh = threshold * threshold; unsigned int hpix; unsigned int vpix; hsobel = convolve(SOBELH_KER, hsobel); Image *vsobel = convolve(SOBELV_KER); unsigned char *hdat, *vdat, *idat, *enddat; enddat = get_end_data(); hdat = hsobel->get_data(); vdat = vsobel->get_data(); for (idat = data; idat < enddat; idat++) { hpix = (int) *hdat; vpix = (int) *vdat; if ((hpix * hpix + vpix * vpix) > sqthresh) *hdat = MARK; else *hdat = CLEAR_MARK; hdat++; vdat++; } delete vsobel; return hsobel; } Image *Grey8Image::sobel(Image *hsobel) { int hpix, vpix; hsobel = convolve(Kernel(1,0,-1,2,0,-2,1,0,-1,true), hsobel); Image *vsobel = convolve(Kernel(1,0,-1,2,0,-2,1,0,-1,false)); unsigned char *hdat, *vdat, *idat, *enddat; enddat = get_end_data(); hdat = hsobel->get_data(); vdat = vsobel->get_data(); for (idat = data; idat < enddat; idat++) { hpix = (int) *hdat; vpix = (int) *vdat; *hdat = (unsigned char) (MAX(hpix,vpix)); hdat++; vdat++; } delete vsobel; return hsobel; } Image *Grey8Image::threshold(unsigned int thresh, Image *outimg, unsigned int *no_marked) { if (outimg == NULL) outimg = new Grey8Image(width, height, frame_id, frame_time_in_ms); unsigned int mark_count = 0; unsigned char *idat = data, *odat = outimg->get_data(); unsigned char *enddat = get_end_data(); for (;idat thresh) { *odat = MARK; mark_count++; } else *odat = CLEAR_MARK; odat ++; } if (no_marked != NULL) *no_marked = mark_count; return outimg; } Image *Grey8Image::extract_subimage(int xmin, int xmax, int ymin, int ymax, Image *subimg) { assert (xmin < xmax); assert (ymin < ymax); assert (check_coords(xmin,ymin) == true); assert (check_coords(xmax,ymax) == true); if (subimg == NULL) subimg = new Grey8Image((xmax - xmin) + 1, (ymax - ymin) + 1, frame_id, frame_time_in_ms); else { assert (subimg->get_width() == (xmax - xmin) + 1); assert (subimg->get_height() == (ymax - ymin) + 1); } unsigned char *indat; unsigned char *outdat; for (int y = ymin; y <= ymax; y++) { indat = get_pixel(xmin,y); outdat = subimg->get_pixel(0,y-ymin); for (int x = xmin; x <= xmax; x++) { *outdat++ = *indat; *indat++ = CLEAR_MARK; } } return subimg; } Image *Grey8Image::fcombine(Image *image2, int (*func) (void*, void*), Image *res) { if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); unsigned char *idat1 = data, *idat2 = image2->get_data(); unsigned char *odat = res->get_data(), *enddat = get_end_data(); for (;idat1 < enddat; idat1++) *odat++ = (*func) ((void*) (idat1), (void*) (idat2++)); return res; } Image *Grey8Image::simple_difference(Image *image2, realno thresh, unsigned int *no_marked, Image *res) { unsigned int mark_count = 0; unsigned int threshold = (unsigned int) thresh; // if thresh < 0 don't threshold, just subtract if (thresh < 0) { if (no_marked != NULL) *no_marked = 0; return difference(image2, res); } if (image2->get_width() != width || image2->get_height() != height) { cerror << " cannot difference different sized images !"; exit(1); } if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); unsigned char *idat1 = data; unsigned char *idat2 = image2->get_data(); unsigned char *odat = res->get_data(); unsigned char *enddat = get_end_data(); for ( ;idat1 < enddat; idat1++) { if (abs(*idat1 - *idat2) > threshold) { *odat = MARK; mark_count++; } else *odat = CLEAR_MARK; idat2++;odat++; } if (no_marked != NULL) *no_marked = mark_count; return res; } Image *Grey8Image::difference(Image *image2, Image *res) { if (image2->get_width() != width || image2->get_height() != height) { cerror << " cannot difference different sized images !"; exit(1); } if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); unsigned char *idat1; unsigned char *idat2 = image2->get_data(); unsigned char *odat = res->get_data(); unsigned char *enddat = get_end_data(); for (idat1 = data; idat1 < enddat; idat1++, idat2++) { *odat++ = abs (*idat1 - *idat2); } return res; } Image *Grey8Image::half_blur(Image *res) { int new_width = width / 2; int new_height = height / 2; if (res == NULL) res = new Grey8Image(new_width, new_height, frame_id, frame_time_in_ms); unsigned char *odat = res->get_data(); for (int y = 0; y < new_height; y++) { unsigned char *in_even = get_pixel(0,y * 2); unsigned char *in_odd = get_pixel(0,y * 2 + 1); for (int x = 0; x < new_width; x++) { int curr_pix = *in_even++ + *in_odd++ + *in_even++ + *in_odd++; *odat++ = (curr_pix >> 2); } } return res; } Image *Grey8Image::blur(Image *res) { unsigned char *upnt, *pnt, *dpnt; unsigned char *out; int temp_total; if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); for (int y = 1; y < height-1; y++) { upnt = get_pixel(0,y-1); pnt = get_pixel(0,y); dpnt = get_pixel(0,y+1); out = res->get_pixel(1,y); for (int x = 1; x < width; x++) { temp_total = upnt[0] + upnt[1] + upnt[2] + pnt[0] + pnt[2] + dpnt[0] + dpnt[1] + dpnt[2]; *(out++) = (unsigned char) (temp_total >> 3); upnt++; pnt++; dpnt++; } } return res; } Image *Grey8Image::mask(Image *mask, Image *res) { if (mask == NULL) return NULL; if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); if ((mask->get_width() != width) || (mask->get_height() != height)) { int x; int y; register unsigned char *mask_pix; for (y = 0; y < height; y++) for (x = 0; x < width; x++) { if (mask->check_coords(x,y)) { mask_pix = mask->get_pixel(x,y); if (*mask_pix != (unsigned char) 0x00) *res->get_pixel(x,y) = *get_pixel(x,y); } } } else { unsigned char *rdat = res->get_data(); unsigned char *dat1 = data; unsigned char *dat2 = mask->get_data(); unsigned char *edat = get_end_data(); while (dat1 < edat) *rdat++ = *dat1++ & *dat2++; } return res; } Image *Grey8Image::fix_holes(int gapsize, Image *res) { int i; if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); Grey8Image *temp_img1; Grey8Image *temp_img2; Grey8Image *dummy; temp_img1 = new Grey8Image(width, height, frame_id, frame_time_in_ms); temp_img2 = new Grey8Image(width, height, frame_id, frame_time_in_ms); temp_img1->clear(CLEAR_MARK); temp_img2->clear(CLEAR_MARK); this->maximum(temp_img1); for (i = 1; i < gapsize; i++) { temp_img1->maximum(temp_img2); dummy = temp_img1; temp_img1 = temp_img2; temp_img2 = dummy; } for (i = 0; i < gapsize; i++) { temp_img1->minimum(temp_img2); dummy = temp_img1; temp_img1 = temp_img2; temp_img2 = dummy; } temp_img1->copy(res); delete temp_img2; delete temp_img1; return res; } #ifdef USE_GL ///////////////////////// GL interface //////////////////////////// long Grey8Image::display(long awindow) { #ifdef NO_DISPLAY return NULLWIN; #else int width4 = width; if ((width % 4) != 0) width4 = 4 * ((width / 4) + 1); if (awindow != NULLWIN) glwin = awindow; if (glwin == NULLWIN) { int zoom = Image::display_zoom->value; prefsize(width4 * zoom, height * zoom); // nts: this gives an error in Ygl version 4.x // foreground(); if (window_title[0] == 0) // no title given? default to this: sprintf(window_title," GREY8 image %d by %d ", width, height); glwin = winopen(window_title); if (glwin < 0) // error { cerror << " Warning: cannot open window for Grey8Image display " << endl << flush; } winset(glwin); reshapeviewport(); prefsize(width4 * zoom, height * zoom); if (zoom != 1) { // nts: this is included in Ygl version 4.x ! rectzoom((float) zoom, (float) zoom); viewport(0, width4 * zoom - 1, 0, height * zoom - 1); ortho2(-0.5, width4 + 0.5, -0.5, height + 0.5); } winconstraints(); cmode(); gflush(); //#ifndef LINUX for (int k = 0; k < 256; k++) mapcolor(k,k,k,k); //#endif gflush(); gconfig(); } if (width != width4) { Grey8Image tmp_image(width4,height); tmp_image.clear(CLEAR_MARK); tmp_image.paste_subimage(0,width-1,0,height-1, this); winset(glwin); crectwrite(0,0,width4-1,height-1, (Uint8*) tmp_image.get_data()); } else { winset(glwin); crectwrite(0,0,width-1,height-1,(Uint8 *) data); } return glwin; #endif // #ifdef NO_DISPLAY #else } ///////////////////////// GL interface ends //////////////////////////// #else ///////////////////////// X interface //////////////////////////// #ifndef NO_DISPLAY void Grey8Image::setup_greymap(Display *mydisplay, int screen, Window mywindow) { cmap = DefaultColormap(mydisplay, screen); no_grey_cells = 256; unsigned int min_cells = 256; Status res = 0; unsigned long pix_vals[256]; unsigned int no_cells = no_grey_cells; while ((res == 0) && (no_cells >= min_cells)) { res = XAllocColorCells(mydisplay, cmap, False, NULL, 0, pix_vals, no_cells); no_cells /= 2; } if (res == 0) { cmap = XCreateColormap(mydisplay, mywindow, DefaultVisual(mydisplay, screen), AllocNone); no_cells = no_grey_cells; while ((res == 0) && (no_cells >= 8)) { res = XAllocColorCells(mydisplay, cmap, True, NULL, 0, pix_vals, no_cells); no_cells /= 2; } if (res == 0) exit(1); } no_cells *= 2; XColor *grey = (XColor *) new XColor [no_cells]; for (unsigned int cell = 0; cell < no_cells; cell++) { unsigned int intensity = (unsigned int) ((cell * (long) 65536 ) / (no_cells)); grey[cell].red = grey[cell].green = grey[cell].blue = intensity; grey[cell].pixel = pix_vals[cell]; grey[cell].flags = DoRed | DoGreen | DoBlue; } for (unsigned int i = 0; i < 256; i++) reverse_cmap[i] = pix_vals[(i * no_cells) / 256]; XStoreColors(mydisplay, cmap, grey, no_cells); delete grey; pixel = (unsigned char) pix_vals[0]; } #endif // #ifndef NO_DISPLAY void Grey8Image::virtual_display() { #ifndef NO_DISPLAY if (mydisplay == NULL) { mydisplay = XOpenDisplay(""); int screen = DefaultScreen(mydisplay); mypixmap = XCreatePixmap(mydisplay, DefaultRootWindow(mydisplay), width, height, 8); myimage = XCreateImage( mydisplay, DefaultVisual(mydisplay, screen), 8, ZPixmap, 0, None, width, height, 8, 0); mygc = XCreateGC (mydisplay, mypixmap, 0, 0); // X11 works with images stored IA_TOP_TO_BOTTOM and 8-bit grey values. // Check whether we do, too: if ((no_grey_cells == 256) && (Image::image_storage_mode == IA_TOP_TO_BOTTOM)) myimage->data = (unsigned char *) data; else myimage->data = new unsigned char[width * height]; } if ((unsigned char*) data != myimage->data) { Grey8Image tmp_img(width, height, (unsigned char*) myimage->data); flip_vertically(&tmp_img); } XPutImage(mydisplay, mypixmap, mygc, myimage, 0,0,0,0,width, height); #endif // #ifndef NO_DISPLAY } long Grey8Image::display(long dummy) { #ifndef NO_DISPLAY if (mydisplay == NULL) { if (window_title[0] == 0) { if (window_title[0] == 0) // no title given? default to this: sprintf(window_title," GREY8 image %d by %d ", width, height); } XSizeHints myhints; myhints.width = width; myhints.height = height; myhints.flags = PSize; mydisplay = XOpenDisplay(""); int screen = DefaultScreen(mydisplay); unsigned long white = WhitePixel(mydisplay, screen); unsigned long black = BlackPixel(mydisplay, screen); mywindow = XCreateSimpleWindow (mydisplay, DefaultRootWindow(mydisplay) ,100,100,width,height,5,black, white); mypixmap = XCreatePixmap(mydisplay, DefaultRootWindow(mydisplay), width, height, 8); XSetStandardProperties(mydisplay, mywindow, window_title, "image", None, NULL, 0, &myhints); XSetWindowBackgroundPixmap(mydisplay, mywindow, mypixmap); XMapRaised(mydisplay, mywindow); myimage = XCreateImage( mydisplay, DefaultVisual(mydisplay, screen), 8, ZPixmap, 0, None, width, height, 8, 0); if (no_using_cmap == 0) setup_greymap(mydisplay, screen, mywindow); no_using_cmap++; XSetWindowColormap(mydisplay, mywindow, cmap); // XSetWindowAttributes xswa; // xswa.backing_pixel = (unsigned long) pixel; // xswa.backing_planes = plane_masks[0] | plane_masks[1] | plane_masks[2] // | plane_masks[3] | plane_masks[4] | plane_masks[5] | plane_masks[6] // | plane_masks[7]; // XChangeWindowAttributes(mydisplay, mywindow, CWBackingPlanes | // CWBackingPixel, &xswa); //mygc = XCreateGC (mydisplay, mywindow, 0, 0); mygc = XCreateGC (mydisplay, mypixmap, 0, 0); /*if ((shift == 0) && (offset == 0)) myimage->data = (char *) data; else*/ // X11 works with images stored IA_TOP_TO_BOTTOM and 8-bit grey values. // Check whether we do, too: if ((no_grey_cells == 256) && (Image::image_storage_mode == IA_TOP_TO_BOTTOM)) myimage->data = (unsigned char*) data; else myimage->data = new unsigned char[width * height]; } if ((unsigned char*) data != myimage->data) { unsigned int x,y; unsigned char *idat, *odat = (unsigned char*) myimage->data; for (y = height; y > 0; y--) { idat = get_pixel(0, (y-1)); for (x = 0; x < width; x++) *odat++ = reverse_cmap[*idat++]; } } //XPutImage(mydisplay, mywindow, mygc, myimage, 0,0,0,0,width, //height); XPutImage(mydisplay, mypixmap, mygc, myimage, 0,0,0,0,width, height); XClearArea(mydisplay, mywindow, 0,0,0,0, True); #endif // #ifndef NO_DISPLAY return 0; } #endif // ifdef USE_GL else ie use X11 ///////////////////////// X interface ends //////////////////////////// Image *Grey8Image::diff_stats(Image *image2, realno &mean, realno &variance, Image *res) { if (image2->get_width() != width || image2->get_height() != height) { cerror << " can't difference different sized images !"; exit(1); } if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); unsigned char *idat1 = data, *idat2 = image2->get_data() , *odat = res->get_data(), *enddat = get_end_data(); int diff, no_pixels = enddat - data; realno total_diff = 0 , total_square = 0; for ( ;idat1 < enddat; idat1++) { diff = (*idat1 - *idat2); *odat++ = abs (diff); total_diff += diff; total_square += (diff * diff); idat2++; } mean = (total_diff / no_pixels); variance = (total_square / no_pixels) - (mean * mean); return res; } Image *Grey8Image::image_blend(Image *i2, int a, int b, Image *res) { // if trying to blend a Greyscale and colour image if ((i2 != NULL) && (i2->get_image_type() == RGB32)) return i2->image_blend(this,b,a,res); if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); unsigned char *idat1 = data, *idat2 = i2->get_data(), *odat = res->get_data(), *enddat = get_end_data(); int pix; int aplusb = a + b; for ( ;idat1 < enddat; idat1++) { pix = (a * *idat1) + (b * *idat2); *odat++ = (pix / aplusb); idat2++; } return res; } Image *Grey8Image::map_intensities(PntGreyMap gmap, Image *res) { if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); unsigned char *idat = data, *odat = res->get_data(), *enddat = get_end_data(); for ( ;idat < enddat; idat++) *odat++ = gmap[*idat]; return res; } Image *Grey8Image::b_w_compress(Image *res) { if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); unsigned char *idat = data, *odat = res->get_data(); unsigned char flag; int counter; while (idat < end_data) { flag = *idat; counter = -1; while ((idat < end_data) && (*idat == flag) && counter < 127) { counter++; idat++; } if (flag == MARK) counter = counter | 128; *odat++ = counter; } res->set_end_data(odat); return res; } Image *Grey8Image::b_w_uncompress(Image *res) { if (res == NULL) res = new Grey8Image(width, height, frame_id, frame_time_in_ms); unsigned char *idat = data, *odat = res->get_data(); unsigned char *edat = res->get_end_data(); unsigned char flag; int counter; while (odat < edat) { counter = (*idat & 127) + 1; if ((*idat & 128) != 0) flag = MARK; else flag = CLEAR_MARK; while (counter > 0 && odat < edat) { counter--; *odat++ = flag; } idat++; } return res; } realno Grey8Image::get_marked_fraction() { int total_marked = 0; for (unsigned char *idat = data; idat < end_data; idat ++) { if (*idat == MARK) total_marked++; } return (realno) total_marked / (end_data - data); } void Grey8Image::save_pnm(char *filename) // save PGM file { // save as portable grey map (binary mode) FILE *outfile = NULL; if (filename == NULL) outfile = stdout; else { outfile = fopen(filename,"wb"); // `b' may be important on non-UNIX if (outfile == NULL) { cerror << " Grey8Image::save_pnm: could not open output file »" << filename << "« " << endl; exit(1); } } fprintf(outfile,"P5\n%d %d\n255\n", width, height); // write pixel values, depending on image_storage_mode // The PNM formats are storing the image IA_TOP_TO_BOTTOM if (Image::image_storage_mode == IA_TOP_TO_BOTTOM) { // no need to convert. write out all data in one go: fwrite(data, 1, width*height, outfile); } else { // flip image (y lines) as we write the file for (unsigned int y = height; y > 0; y--) fwrite(get_pixel(0, y-1), 1, width, outfile); } if (filename != NULL) fclose(outfile); } Grey8Image::Grey8Image(char *pgmfile) { FILE *infile = NULL; if ((infile = fopen(pgmfile,"rb")) == NULL) // `b' may be important on non-UNIX { cerror << " Grey8Image::Grey8Image: could not open input file »" << pgmfile << "« " << endl; exit(1); } char c1,c2; fscanf(infile,"%c%c", &c1, &c2); if (c1 != 'P' || c2 != '5') { cerror << " file not pgm in Grey8Image::Grey8Image " << endl; exit(1); } char aline[100]; fgets(aline, 99, infile); while (aline[0] == '#' || aline[0] == '\n') fgets(aline, 99, infile); sscanf(aline,"%d %d\n", (int *) &width, (int *) &height); fscanf(infile,"%d\n", (int *) &bytes_per_pixel); if (bytes_per_pixel != 255) { cerror << " bad pgm format " << endl; exit(1); } bytes_per_pixel = 1; line_length = width * bytes_per_pixel; data = new unsigned char[width * height * bytes_per_pixel]; end_data = (data + width * height * bytes_per_pixel); image_type = GREY8; // read pixel values, depending on image_storage_mode // The PNM formats are storing the image IA_TOP_TO_BOTTOM if (Image::image_storage_mode == IA_TOP_TO_BOTTOM) { // no flipping necessary, read all data in one go fread(data, 1, width*height, infile); } else { // flip image (y lines) as we read the file for (unsigned int y = height; y > 0; y--) { fread(get_pixel(0, y-1), 1, width, infile); } } #ifndef NO_DISPLAY #ifdef USE_GL glwin = NULLWIN; #else mydisplay = NULL; #endif Grey8_draw_colour = 255; #endif // #ifndef NO_DISPLAY } Image *Grey8Image::to_rgb(Image *res) { if (res == NULL) res = new RGB32Image(width, height, frame_id, frame_time_in_ms); unsigned char *idat = data; //unsigned char *odat = res->get_data(); RGB32pixel *odat = (RGB32pixel*) res->get_data(); unsigned char *edat = get_end_data(); //RGB8pixel *pix; unsigned char glevel; for ( ;idat < edat; idat ++) { if ((*idat * 1.164) > 255) glevel = 255; else glevel = (unsigned char) (*idat * 1.164); //glevel = glevel >> 5; //pix = (RGB32pixel*) odat; //pix->blue = (glevel / 2); odat->blue = (glevel); odat->green = (glevel); odat->red = (glevel); odat++; } return res; } void Grey8Image::draw_rectangle(int xmin, int xmax, int ymin, int ymax, int val) { if ((xmin > xmax) || (ymin > ymax)) { cerror << " Grey8Image::draw_rectangle(" << xmin << "," << xmax << "," << ymin << "," << ymax << ", " << val << ") : cannot draw! " << endl; return; } if (xmin < 0) xmin = 0; if (ymin < 0) ymin = 0; if (xmax >= width) xmax = (width-1); if (ymax >= height) ymax = (height-1); // maybe we were called with something like (-10,-5 \ETC) so check again: if ((xmin > xmax) || (ymin > ymax)) { cerror << " Grey8Image::draw_rectangle (corrected values " << xmin << "," << xmax << "," << ymin << "," << ymax << ", " << val << ") : cannot draw! " << endl; return; } int nbytes = (xmax - xmin + 1) * bytes_per_pixel; for (int y = ymin; y <= ymax; y++) memset(get_pixel(xmin,y),val, nbytes); } Image *Grey8Image::transform(int centre_x, int centre_y, realno angle, realno scale, Image *res) { if (res == NULL) res = copy_type(); unsigned char *dest; int x_from, y_from; realno cosa = cos(angle) / scale; realno sina = sin(angle) / scale; const int &dw = res->get_width(); const int &dh = res->get_height(); int dw2 = dw / 2; int dh2 = dh / 2; for (int y = 0; y < dh; ++y) { dest = res->get_pixel(0,y); for (int x = 0; x < dw; ++x) { int x1 = x - dw2; int y1 = y - dh2; x_from = (int) (centre_x + x1 * cosa + y1 * sina); y_from = (int) (centre_y + y1 * cosa - x1 * sina); if ((x_from < 0) || (y_from < 0) || (x_from >= width) || (y_from >= height)) *dest++ = 0; else *dest++ = *get_pixel(x_from, y_from); } } return res; } Grey8Image::~Grey8Image() { #ifndef NO_DISPLAY #ifndef USE_GL if (mydisplay != NULL) { XFreeGC(mydisplay, mygc); XFreePixmap(mydisplay, mypixmap); if (mywindow != NULLWIN) { XDestroyWindow(mydisplay, mywindow); no_using_cmap--; if (no_using_cmap == 0) { XFreeColormap(mydisplay, cmap); //cerror << " Freeing colormap " << endl; cmap = 0; no_using_cmap = 0; } } if (myimage->data != (char *) data) delete [] (myimage->data); myimage->data = None; XFree((char *) myimage); mydisplay = NULL; } #endif #endif // #ifndef NO_DISPLAY } void Grey8Image::median_img_array(Image* *img_array, int asize) { if (img_array[0]->get_image_type() != GREY8) { cerror << " bad call to Grey8Image::median_img_array " << endl; abort(); } unsigned char *table = new unsigned char[asize]; int cpos = (asize + 1) / 2; int i,j,k; for (i = 0; i < width; i++) for (j = 0; j < height; j++) { for (k = 0; k < asize; k++) table[k] = *(img_array[k]->get_pixel(i,j)); qsort(table, asize, sizeof(unsigned char), &compar_char); *get_pixel(i,j) = table[cpos]; } delete [] table; } RGB32Image *Grey8Image::rgb_read_image(RGB32Image *res) { #ifdef NO_DISPLAY // mission impossible cerror << "Grey8Image::rgb_read_image not possible without display " << endl; abort(); return NULL; #else #ifdef USE_GL Int32 xsize; Int32 ysize; winset(glwin); getsize(&xsize, &ysize); if (res == NULL) res = new RGB32Image(xsize, ysize, frame_id, frame_time_in_ms); // read colour mapped pixel data //Image *tmp_img = new Grey8Image(xsize, ysize, frame_id, frame_time_in_ms); Colorindex *image_data = new Colorindex[xsize * ysize]; rectread(0,0,xsize-1,ysize-1, (Int16*)(image_data)); // unmap the data Colorindex *idat = image_data; Colorindex *edat = &image_data[xsize * ysize]; RGB32pixel *odat = (RGB32pixel*) res->get_data(); Int16 red_val; Int16 green_val; Int16 blue_val; for ( ; idat < edat; idat++) { getmcolor(*idat, &red_val, &green_val, &blue_val); odat->alpha = 0; odat->red = (unsigned char) red_val; odat->green = (unsigned char) green_val; odat->blue = (unsigned char) blue_val; odat++; } delete [] image_data; return res; #else // to be implemented ! cerror << "Grey8Image::rgb_read_image not implemented on X11 " << endl; abort(); return NULL; #endif #endif // #ifdef NO_DISPLAY #else } void Grey8Image::set_draw_colour(unsigned char red, unsigned char green, unsigned char blue) { realno col = 0.299 * red + 0.587 * green + 0.114 * blue; Grey8_draw_colour = (unsigned char) (col + 0.5); } void Grey8Image::set_draw_colour(unsigned char grey_value) { Grey8_draw_colour = grey_value; } void Grey8Image::draw_horizontal(unsigned int y, unsigned int xl, unsigned int xr, bool dotted) { if ((check_coords(xl, y) == false) || (check_coords(xr,y) == false)) return; unsigned char *pixleft = get_pixel(xl, y); unsigned char *pixright = get_pixel(xr,y); while (pixleft <= pixright) { *pixleft++ = Grey8_draw_colour; if (dotted) pixleft++; // skip another pixel } } void Grey8Image::draw_vertical(unsigned int x, unsigned int yl, unsigned int yu, bool dotted) { if ((check_coords(x,yl) == false) || (check_coords(x,yu) == false)) return; if (yl > yu) { // exchange values if coordinates are upside down unsigned int tmp = yl; yl = yu; yu = tmp; } for (unsigned int y = yl; y <= yu; y++) { if ((dotted) && ((y & 1) == 1)) continue; *get_pixel(x,y) = Grey8_draw_colour; } } void Grey8Image::plot_pixel(unsigned int x, unsigned int y) { if (check_coords(x,y) == true) *get_pixel(x,y) = Grey8_draw_colour; } Image *Grey8Image::to_rgb(RGB32pixel *color_map, Image *res) { if (res == NULL) res = new RGB32Image(width, height, frame_id, frame_time_in_ms); RGB32pixel *pnt_out = (RGB32pixel*) res->get_data(); unsigned char *pnt_in = data; while (pnt_in < end_data) *pnt_out++ = color_map[*pnt_in++]; return res; } void Grey8Image::get_detail(unsigned char *g1, unsigned char *g2, unsigned char *r, int &width) { int lpx,lpy; unsigned char *tg1, *tg2, *tr; for (lpy = 0; lpy < BOX_SIZE; lpy++) { tg1 = g1; tg2 = g2; tr = r; for (lpx = 0; lpx < BOX_SIZE; lpx++) *r++ = abs(*g2++ - *g1++); g1 = tg1 + width; g2 = tg2 + width; r = tr + width; } } Image *Grey8Image::difference(Image *image2, realno threshold, Image *res) { if ((this == NULL) || (image2 == NULL)) return NULL; if (image2->get_image_type() != GREY8) { cerror << " Grey8Image::difference: cannot difference different image types! " << endl; exit(1); } if (res == NULL) res = new Grey8Image(width, height); res->clear(CLEAR_MARK); unsigned char *g1 = data; unsigned char *g2 = image2->get_data(); unsigned char *tg1, *tg2, *trdat; unsigned char *rdat = res->get_data(); int up = BOX_SIZE * width; int left = BOX_SIZE; int upleft = left + up; int upleft2 = upleft / 2; int upright = up - left; g1 += (upleft2) * 3; g2 += (upleft2) * 3; rdat += (upleft2) * 3; unsigned int lx, ly; unsigned int lymax = height / BOX_SIZE; unsigned int lxmax = width / BOX_SIZE; int interest_threshold = (int) threshold; int adj1 = upleft2; int adj2 = left+adj1; int adj3 = up+adj1; int adj4 = upleft+adj1; int adj5 = adj1-left; int adj6 = adj1-up; int adj7 = adj1-upleft; int adj8 = adj1-upright; int adj9 = adj1+upright; Image *flag_img = new Grey8Image(lxmax, lymax); lxmax -=2 ;lymax -=2; flag_img->clear(CLEAR_MARK); for (ly = 1; ly < lymax; ly++) { tg1 = g1; tg2 = g2; trdat = rdat; for (lx = 1; lx < lxmax; lx++) { *rdat = abs (*g2 - *g1); if (*rdat >= interest_threshold) { // this square if (!*(flag_img->get_pixel(lx,ly))) { get_detail(g1-adj1,g2-adj1, rdat-adj1, (int &) width); *(flag_img->get_pixel(lx,ly)) = MARK; } // left if (!*(flag_img->get_pixel(lx-1,ly))) { get_detail(g1-adj2,g2-adj2, rdat-adj2, (int &) width); *(flag_img->get_pixel(lx-1,ly)) = MARK; } // up if (!*(flag_img->get_pixel(lx,ly-1))) { get_detail(g1-adj3,g2-adj3, rdat-adj3, (int &) width); *(flag_img->get_pixel(lx,ly-1)) = MARK; } // up-left if (!*(flag_img->get_pixel(lx-1,ly-1))) { get_detail(g1-adj4,g2-adj4, rdat-adj4, (int &) width); *(flag_img->get_pixel(lx-1,ly-1)) = MARK; } // right if (!*(flag_img->get_pixel(lx+1,ly))) { get_detail(g1-adj5,g2-adj5, rdat-adj5, (int &) width); *(flag_img->get_pixel(lx+1,ly)) = MARK; } // down if (!*(flag_img->get_pixel(lx,ly+1))) { get_detail(g1-adj6,g2-adj6, rdat-adj6, (int &) width); *(flag_img->get_pixel(lx,ly+1)) = MARK; } // down-right if (!*(flag_img->get_pixel(lx+1,ly+1))) { get_detail(g1-adj7,g2-adj7, rdat-adj7, (int &) width); *(flag_img->get_pixel(lx+1,ly+1)) = MARK; } // down-left if (!*(flag_img->get_pixel(lx-1,ly+1))) { get_detail(g1-adj8,g2-adj8, rdat-adj8, (int &) width); *(flag_img->get_pixel(lx-1,ly+1)) = MARK; } // up-right if (!*(flag_img->get_pixel(lx+1,ly-1))) { get_detail(g1-adj9,g2-adj9, rdat-adj9, (int &) width); *(flag_img->get_pixel(lx+1,ly-1)) = MARK; } } g1 += left; g2 += left; rdat += left; } g1 = tg1 + up; g2 = tg2 + up; rdat = trdat + up; } delete flag_img; return res; } Grey8Image *Grey8Image::invert(Grey8Image *res) { assert (line_length %4 == 0); // we will read 4 pixels in one go for speed if (res == NULL) res = new Grey8Image(width, height); else if ((width != res->get_width()) || (height != res->get_height()) || (image_type != res->get_image_type())) { cerror << " Grey8Image::invert: Error: cannot invert to differnt size / type image " << endl; abort(); } u_int32_t *from = (u_int32_t *) data; u_int32_t *to = (u_int32_t *) res->get_data(); while ((void *) from < (void *) end_data) *to++ = ! (*from++); // bitwise negation return res; } } // namespace ReadingPeopleTracker