📄 image.cc
字号:
}void Image::draw_rectangle(int xmin, int xmax, int ymin, int ymax, int val){ cerror << "illegal call to Image::draw_rectangle " << endl; abort();}Image *Image::transform(int centre_x, int centre_y, realno angle, realno scale, Image *r){ cerror << "illegal call to Image::transform " << endl; abort();}// base class implementation assumes noise is to be added// to each byte (i.e. each field is stored in a byte)#ifdef _SVID_SOURCE// the following uses SVID 48-bit random numbers...static int set_seed = 0;static int iset = 0;static realno gset;Image *Image::add_gaussian_noise(realno sd, realno &noise, Image *res){ if (res == NULL) res = copy_type(); if (set_seed == 0) { long rseed = time(NULL); srand48(rseed); set_seed = 1; } noise = 0; unsigned char *in_pnt = data; unsigned char *out_pnt = res->data; while (in_pnt < end_data) { realno fac, rsq, v1, v2, corrupt; if (iset == 0) { do { v1 = 2.0 * drand48() - 1.0; v2 = 2.0 * drand48() - 1.0; rsq = (v1 * v1) + (v2 * v2); } while ((rsq >= 1.0 )|| (rsq == 0.0)); fac = sqrt(-2.0 * log(rsq)/rsq); gset = v1 * fac; iset = 1; corrupt = v2 * fac; } else { iset = 0; corrupt = gset; } int icorrupt = (int) (sd * corrupt + 0.5); int ipix = (int) *in_pnt++; int new_ipix = ipix + icorrupt; if (new_ipix > 255) new_ipix = 255; if (new_ipix < 0) new_ipix = 0; *out_pnt++ = new_ipix; noise += (new_ipix - ipix) * (new_ipix - ipix); } return res;}#endif // ifdef _SVID_SOURCE// sum pixel values // assume each field is stored in a byte// all fields are setinline realno Image::sum_pixels(){ realno total = 0; unsigned char *pix_field = data; while (pix_field < end_data) total += (realno) (*pix_field++); return total;}// sum [I(x,y) - zero]^2realno Image::sum_square_pixels(int zero){ realno total = 0; unsigned char *pix_field = data; while (pix_field < end_data) { int ival = *pix_field++ - zero; total += (realno) (ival * ival); } return total;}void Image::median_img_array(Image **arr, int i){ cerror << "illegal call to Image::median_img_array " << endl;}Image *Image::plane_project(const realno m00, const realno m01, const realno m02, const realno m10, const realno m11, const realno m12, const realno m20, const realno m21, const realno m22, Image *res){ if (res == NULL) res = copy_type(); realno depth, back_x, back_y; int rw = res->get_width(); int rh = res->get_height(); for (int x = 0; x < rw; x++) for (int y = 0; y < rh; y++) { depth = m20 * x + m21 * y + m22; back_x = (m00 * x + m01 * y + m02) / depth; back_y = (m10 * x + m11 * y + m12) / depth; unsigned char *p1 = nearest_pixel(back_x, back_y); if (p1 != NULL) memcpy(res->get_pixel(x,y), p1, bytes_per_pixel); else memset(res->get_pixel(x,y), 0, bytes_per_pixel); } return res;}void Image::poly_delete(int i, int &nact, Edge *active) { int j; for (j=0; j<nact && active[j].i!=i; j++) ; if (j>=nact) return; nact--; memcpy(&active[j], &active[j+1], (nact-j)*sizeof(active[0]));}void Image::poly_insert(int i, int y, int nvert, int &nact, Edge *active) { int j; double dx; Point2 *p, *q; j = i<nvert-1 ? i+1 : 0; if (pt[i].y < pt[j].y) { p = &pt[i]; q = &pt[j]; } else { p = &pt[j]; q = &pt[i]; } // initialize x position at intersection of edge with scanline y active[nact].dx = dx = (q->x-p->x)/(q->y-p->y); active[nact].x = dx*(y+.5-p->y)+p->x; active[nact].i = i; nact++;}void Image::draw_filled_polygon(int n, Point2 *vertices){ // // Concave Polygon Scan Conversion // by Paul Heckbert // from "Graphics Gems", Academic Press, 1990 // // modified by amb pt = vertices; Edge *active = new Edge[n]; int win_x0 = 0, win_x1 = width-1; int win_y0 = 0, win_y1 = height-1; int y0, y1, i, j, xl, xr; int *ind = new int[n]; int k; if (n<=0) return; for (k=0; k<n; k++) ind[k] = k; qsort(ind, n, sizeof(ind[0]), &compare_ind); // sort ind by pt[ind[k]].y int nact = 0; k = 0; y0 = max(win_y0, (int) ceil(pt[ind[0]].y-0.5)); y1 = min(win_y1, (int) floor(pt[ind[n-1]].y-0.5)); for (signed int y=y0; y<=y1; y++) // step through scanlines { // scanline y is at y+.5 in continuous coordinates // check vertices between previous scanline and current one, if any for (; k<n && pt[ind[k]].y<=y+.5; k++) { // to simplify, if pt.y=y+.5, pretend it's above // invariant: y-.5 < pt[i].y <= y+.5 i = ind[k]; // // insert or delete edges before and after vertex i (i-1 to i // and i to i+1) from active list if they cross scanline y // j = (i>0) ? i-1 : n-1; // vertex previous to i if (pt[j].y <= y-.5) // old edge, remove from active list poly_delete(j, nact, active); else if (pt[j].y > y+.5) // new edge, add to active list poly_insert(j, y, n, nact, active); j = (i<n-1) ? i+1 : 0; // vertex next after i if (pt[j].y <= y-.5) // old edge, remove from active list poly_delete(i, nact, active); else if (pt[j].y > y+.5) // new edge, add to active list poly_insert(i, y, n, nact, active); } // NB: nact at this point is usually 2, sometimes 0 // if no edges, simply continue if (nact == 0) continue; // sort active edge list by active[j].x qsort(active, nact, sizeof(active[0]), &compare_active); // draw horizontal segments for scanline y for (j=0; j<nact; j+=2) // draw horizontal segments { // span between j & j+1 is inside, span tween j+1 & j+2 is outside xl = (int) ceil(active[j].x-.5); // left end of span if (xl<win_x0) xl = win_x0; xr = (int) floor(active[j+1].x-.5); // right end of span if (xr>win_x1) xr = win_x1; if (xl<=xr) draw_horizontal(y, xl, xr); active[j].x += active[j].dx; // increment edge coords active[j+1].x += active[j+1].dx; } } delete [] ind; delete [] active; }void Image::draw_filled_circle(int x0, int y0, int r){ int limit = 0; int sigma; int x = 0; int y = r; int delta = (1 - r) << 1; while (y >= limit) { if (delta < 0) { sigma = ((delta + y) << 1) - 1; if (sigma > 0) { draw_horizontal(y0+y, x0-x, x0+x); draw_horizontal(y0-y, x0-x, x0+x); x++;y--; delta += (x - y + 1) << 1; } else { x++; delta += (x << 1) + 1; } } else if (delta > 0) { sigma = ((delta - x) << 1) - 1; if (sigma > 0) { draw_horizontal(y+y0, x0-x, x0+x); draw_horizontal(y0-y, x0-x, x0+x); y--; delta += 1 - (y << 1); } else { draw_horizontal(y+y0, x0-x, x0+x); draw_horizontal(y0-y, x0-x, x0+x); x++; y--; delta += (x - y + 1) << 1; } } else { draw_horizontal(y+y0, x0-x, x0+x); draw_horizontal(y0-y, x0-x, x0+x); x++;y--; delta += (x - y + 1) << 1; } }}void Image::draw_line(int x0, int y0, int x1, int y1){ if (DrawLineWidth > 1) { Point2 plist[4]; realno delta_x, delta_y, dlength; delta_x = (realno) (x1 - x0); delta_y = (realno) (y1 - y0); dlength = sqrt((delta_x * delta_x) + (delta_y * delta_y)); int r = (int) ((DrawLineWidth - 0.99) / 2); if (dlength > 0) { realno dx = delta_x / dlength; realno dy = delta_y / dlength; realno nx = dy; realno ny = -dx; plist[0].x = x0 + 0.5 + ((r + 0.5) * nx) - (dx * 0.5); plist[0].y = y0 + 0.5 + ((r + 0.5) * ny) - (dy * 0.5); plist[1].x = x0 + 0.5 - ((r + 0.5) * nx) - (dx * 0.5); plist[1].y = y0 + 0.5 - ((r + 0.5) * ny) - (dy * 0.5); plist[2].x = x1 + 0.5 - ((r + 0.5) * nx) + (dx * 0.5); plist[2].y = y1 + 0.5 - ((r + 0.5) * ny) + (dy * 0.5); plist[3].x = x1 + 0.5 + ((r + 0.5) * nx) + (dx * 0.5); plist[3].y = y1 + 0.5 + ((r + 0.5) * ny) + (dy * 0.5); draw_filled_polygon(4, plist); } draw_filled_circle(x0,y0,r); draw_filled_circle(x1,y1,r); return; } int d; int x; int y; int ax; int ay; int sx; int sy; int dx; int dy; dx = x1-x0; ax = ABS(dx)<<1; sx = SGN(dx); dy = y1-y0; ay = ABS(dy)<<1; sy = SGN(dy); if ((dx == 0) && (dy == 0)) return; x = x0; y = y0; if (ax>ay) { // x dominant d = ay-(ax>>1); for (;;) { plot_pixel(x,y); if (x==x1) return; if (d>=0) { y += sy; d -= ax; } x += sx; d += ay; } } else { // y dominant d = ax-(ay>>1); for (;;) { plot_pixel(x,y); if (y==y1) return; if (d>=0) { x += sx; d -= ay; } y += sy; d += ax; } }}void Image::draw_circle(int x0, int y0, int r){ static const realno cth = cos(M_PI_2 / ((realno) CIRCLE_PRECISION)); static const realno sth = sin(M_PI_2 / ((realno) CIRCLE_PRECISION)); int i; if (DrawLineWidth > 1) { Point2 *pnt_data = new Point2[CIRCLE_PRECISION*8+2]; Point2 *big_circle = pnt_data; Point2 *small_circle = &pnt_data[CIRCLE_PRECISION*4+1]; realno x_big = 0; realno y_big = r + 0.5; realno x_small = 0; realno y_small = (r - DrawLineWidth); Point2 origin(x0+0.5, y0+0.5); for (i = 0; i < CIRCLE_PRECISION; i++) { big_circle[i] = Point2(x_big, y_big); big_circle[i+CIRCLE_PRECISION] = Point2(y_big, -x_big); big_circle[i+2*CIRCLE_PRECISION] = Point2(-x_big, -y_big); big_circle[i+3*CIRCLE_PRECISION] = Point2(-y_big, x_big); small_circle[i] = Point2(x_small, y_small); small_circle[i+CIRCLE_PRECISION] = Point2(y_small, -x_small); small_circle[i+2*CIRCLE_PRECISION] = Point2(-x_small, -y_small); small_circle[i+3*CIRCLE_PRECISION] = Point2(-y_small, x_small); realno new_x_big = cth * x_big + sth * y_big; realno new_y_big = -sth * x_big + cth * y_big; x_big = new_x_big; y_big = new_y_big; realno new_x_small = cth * x_small + sth * y_small; realno new_y_small = -sth * x_small + cth * y_small; x_small = new_x_small; y_small = new_y_small; } big_circle[4*CIRCLE_PRECISION] = big_circle[0]; small_circle[4*CIRCLE_PRECISION] = small_circle[0]; for (i = 0; i < (8 * CIRCLE_PRECISION + 2); i++) pnt_data[i] = pnt_data[i] + origin; draw_filled_polygon(8*CIRCLE_PRECISION+2, pnt_data); delete [] pnt_data; return; } register int x = 0; register int y = r; register int delta = ( 1 - r) << 1; int limit = 0; int sigma; while (y >= limit) { plot_pixel(x0-x,y0+y); plot_pixel(x0+x,y0+y); plot_pixel(x0-x,y0-y); plot_pixel(x0+x,y0-y); if (delta < 0) { sigma = ((delta + y) << 1) - 1; if (sigma > 0) { x++;y--; delta += (x - y + 1) << 1; } else { x++; delta += (x << 1) + 1; } } else if (delta > 0) { sigma = ((delta - x) << 1) - 1; if (sigma > 0) { y--; delta += 1 - (y << 1); } else { x++; y--; delta += (x - y + 1) << 1; } } else { x++; y--; delta += (x - y + 1) << 1; } }}} // namespace ReadingPeopleTracker
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -