main(int argc, char *argv[]) { Img *img, *tmp, *overpose; char filename[100] = "../images/bicycle.png"; annotated_skl *skl; int thresh=25, i; animal_err_set_trace(ANIMAL_ERR_TRACE_ON); if (--argc >=1) strncpy(filename, argv[1],99); if (argc == 2) sscanf(argv[2], "%d",&thresh); img=imread(filename); im2binary_ip(img); // regularize the image tmp = img; img = imregularize(img, NULL); imfree(&tmp); skl = msskl(img,INTERIOR,SKL_IFT); if (!skl) animal_err_default_reporter(); overpose = new_img(img->rows,img->cols); for (i=0; i<img->rows*img->cols; i++) overpose->data[i] =(skl->skl->data[i] >= (puint32) thresh) + img->data[i]; if (!imshow(overpose,0,-1)) printf("err\n"); tmp=msskl_filter(NULL, skl, thresh); for (i=0; i<img->rows*img->cols; i++) overpose->data[i] = (skl->skl->data[i] >= (puint32) thresh) + tmp->data[i]; imshow(overpose,0,-1); imwrite(overpose,"teste.png",true); free_ann_skl(&skl); imfree(&img); imfree(&tmp); imfree(&overpose); animal_heap_report(NULL); return 0; }
AnimalExport int percol(Img *img, int opt) { int i,lbl; point pt; bool percolated=false; img = impad(img,1,1,BG); if (opt == 1) { // test connectivity in horizontal direction for (i=1,lbl=2,pt.x=1; i<img->rows-1; i++,lbl++) if (RC(img,i,1) == FG) { pt.y = i; imfill(img,&pt,lbl,FG,DEFAULT_NHOOD); } for (i=1; i<img->rows-1; i++) if ( RC(img,i,img->cols-2) >= 2) percolated = true; } else { // test connectivity in vertical direction for (i=1,lbl=2,pt.y=1; i<img->cols-1; i++,lbl++) if (RC(img,1,i) == 1) { pt.x = i; imfill(img,&pt,lbl,FG,DEFAULT_NHOOD); } for (i=1; i<img->cols-1; i++) if ( RC(img,img->rows-2,i) >= 2) percolated = true; } imfree(&img); return percolated; }
/* subtracao de media local 2D (vizinhanca circular) outside param: indicates value to assume outside the image when it will be padded. */ AnimalExport Img * smedia2d(Img *img, int radius, pixval outside) { int i,j, cod; unsigned k; double sum; Img *out; DblM *aux; nhood *nh; /* pad image */ img = impad(img,radius,radius,outside); aux = new_dbl_m(img->rows,img->cols); nh = circular_nhood((double)radius); /* @@@@@@@ This is better done in scilab using fft convolution by a disk image. This technique might be used with exact dilation as well as with morphological dilation. */ sum=0; for (i=radius; i<img->rows-radius-1; i++) for (j=radius; j<img->cols-radius-1; j++) { for (k=0; k < nh->n; k++) sum += (double)RC(img,i+nh->dy[k],j+nh->dx[k])/(double)nh->n; RC(aux,i,j) = (double)RC(img,i,j)-(double)sum; sum=0; } /* normalize */ /* @@@ if speed is needed, maybe normalize within the above loop */ cod = normal_dbl_m(aux,0,255); if (!cod) return NULL; out = new_img(img->rows-2*radius, img->cols-2*radius); for (i=0; i<out->rows; i++) for (j=0; j<out->cols; j++) RC(out,i,j) =(pixval) RC(aux,i+radius,j+radius); free_dbl_m(&aux); imfree(&img); return out; }
main (int argc, char *argv[]) { Img *im; animal_err_set_trace(ANIMAL_ERR_TRACE_ON); im = imread("/home/rfabbri/tmp/sip/images/bin.xpm"); if (!im) animal_err_default_reporter(); imfree(&im); im = imread("/home/rfabbri/tmp/sip/images/bin.xpm"); if (!im) animal_err_default_reporter(); animal_heap_report(NULL); return 0; }
main (int argc, char *argv[]) { Img *im; animal_err_set_trace(ANIMAL_ERR_TRACE_ON); im = imread("../images/integral.png"); if (!im) animal_err_default_reporter(); imfree(&im); im = imread("../images/integral.png"); if (!im) animal_err_default_reporter(); animal_heap_report(NULL); return 0; }
/*--------------------------------------------------------------------- * Multiscale Shape Reconstruction using Multiscale Skeletons * - if thresh is negative, assume already thresholded skeleton * - if thresh is positive, sklimg is not used at all (may be null) *---------------------------------------------------------------------*/ AnimalExport Img * msskl_filter(Img *sklimg, annotated_skl *skl, int thresh) { Img *shp, *result; int maxrad, r, c; r = skl->skl->rows; c = skl->skl->cols; maxrad = skl->maxradius; shp= new_img(r + 2*maxrad,c + 2*maxrad); shp->isbinary=true; // calls core routine if (!msskl_filter_np(shp, sklimg, skl, thresh)) return NULL; result = imtrim(shp,maxrad,maxrad); imfree(&shp); return result; }
main(int argc, char *argv[]) { Img *img; nhood *nh; int i,radius=10; if (--argc == 1) sscanf(argv[1],"%d",&radius); img=new_img(2*radius+1,2*radius+1); nh = circular_nhood(radius); for (i=0; i<nh->n; i++) RC(img,radius+nh->dy[i],radius+nh->dx[i]) = 1; imshow(img,0,-1); free_nhood(&nh); imfree(&img); return 0; }
AnimalExport int thinzs_np(Img *A) { bool repeat; Img *B; int i,j,n; B = new_img(A->rows,A->cols); if (!B) return false; do { repeat=false; for (i=1; i < A->rows-1; i++) for (j=1; j < A->cols-1; j++) if ((RC(B,i,j) = RC(A,i,j)) == FG) { n = nh8count_np(A,i,j,FG); if ( n>=2 && n<=6 && crossing_index_np(A,i,j) == 2 ) if((RC(A,i-1,j)==BG || RC(A,i,j+1)==BG || RC(A,i+1,j)==BG) && (RC(A,i-1,j)==BG || RC(A,i+1,j)==BG || RC(A,i,j-1)==BG)){ RC(B,i,j) = BG; repeat=true; } } for (i=1; i < A->rows-1; i++) for (j=1; j < A->cols-1; j++) if ((RC(A,i,j) = RC(B,i,j)) == FG) { n = nh8count_np(B,i,j,FG); if ( n>=2 && n<=6 && crossing_index_np(B,i,j) == 2 ) if((RC(B,i,j+1)==BG || RC(B,i,j-1)==BG || RC(B,i-1,j)==BG) && (RC(B,i-1,j)==BG || RC(B,i,j-1)==BG || RC(B,i+1,j)==BG)){ RC(A,i,j) = BG; repeat=true; } } } while (repeat); imfree(&B); return true; }
/*----------------------------------------------------------------- * Binary Contour Follower * - Extracts parametric contours from binary objects * - nhood parameter may be 4 or 8 (defaults to 8) * - bottom-left to upper-right coordinates *-----------------------------------------------------------------*/ AnimalExport int follow(Img *img, int **xlist, int **ylist, int nhood) { int (*path)[2], next8[8] = {1,2,3,4,5,6,7,0}, invert8[8] = {4,5,6,7,0,1,2,3}, next4[4] = {1,2,3,0}, invert4[4] = {2,3,0,1}, neighbours[8][2] = {}, *next, *invert, cane, cini, i, j, k, a, b, *x=NULL, *y=NULL, t; /* t: index into x and y */ bool finished; switch (nhood) { case 4: path = n4; next = next4; invert= invert4; cane = 1; break; default: nhood = 8; path = n8; next = next8; invert= invert8; cane = 2; break; } // looks for object for (k=0; (k < img->rows*img->cols) && (img->data[k] != 1); k++) ; if (k == img->rows*img->cols) /* no object */ return 0; // get 2D coordinate from index k i = k / img->cols; j = k % img->cols; i++; j++; img = impad(img,1,1,0); // Assume 0 out of the image // get absolute coordinate of the neighbours for (k=0; k<nhood; k++) { neighbours[k][0] = path[k][0]+ i; neighbours[k][1] = path[k][1]+ j; } t=0; finished=false; while ( !finished ) { // realloc x,y x = (int *)realloc(x,(t+1)*sizeof(int)); y = (int *)realloc(y,(t+1)*sizeof(int)); x[t] = j; y[t] = i; t++; // Twist the "blindman's cane" to locate the next contour point cini=cane; do { cane=next[cane]; a = neighbours[cane][0]; b = neighbours[cane][1]; } while (RC(img,a,b) == 0 && cane != cini); if (cane == cini) finished = true; else { i += path[cane][0]; j += path[cane][1]; for (k=0; k<nhood; k++) { // Move to a new contour point neighbours[k][0] += path[cane][0]; neighbours[k][1] += path[cane][1]; } cane = invert[cane]; finished = j==x[0] && i==y[0]; } } for (i=0; i<t; i++) { // bottom-left to upper-right coordinates x[i] -= 1; y[i] = img->rows - y[i] -2; } *xlist = x; *ylist = y; imfree(&img); return t; }
AnimalExport ann_img * exact_propagation(Img *image, ImgPUInt32 *label, list *seed, char side) { char *fname="exact_propagation"; SEDR *sedr; int maxrad, r, c, prev_col, n, rw, cl, i, j, x, y, *pt, *pi, *pf, *lut, d, cp; unsigned maxdist, k, pos; int *p; /* @@@ perhaps a register variable is faster */ ImgPUInt32 *lbl_img, *dist, *pred; puint32 *lbl_data, *dist_data, *pred_data; pixval *img_data; Img *img; list_ptr ptr; ann_img *aimg; r = image->rows; c = image->cols; /* estimate the maximum distance to grow */ if (side != INTERIOR) maxrad = ceil(hypot(r,c)); else { maxrad = (int) (ceil((float)MIN(r,c)/2)); for (n=0,i=0; i<r*c; i++) n += (image->data[i] == FG); maxrad = MIN(maxrad,(int) ceil(sqrt((double)n) / 2)); } sedr = grow_sedr(maxrad); if (!sedr) { animal_err_register (fname, ANIMAL_ERROR_FAILURE,""); return NULL; } img = impad(image, maxrad, maxrad, 0); img_data = img->data; prev_col = c; r = img->rows; c = img->cols; n=r*c; dist = new_img_puint32(r,c); dist_data = dist->data; lut = dist->lut; /* table for (r,c) indexing */ lbl_img = impad_puint32(label, maxrad, maxrad, 0); lbl_data = lbl_img->data; pred = new_img_puint32(r,c); pred_data = pred->data; /* We must mark as INVALID_DIST only those pixels that _will_ be processed by the propagation. */ switch (side) { case INTERIOR: for (i=0; i<n; i++) { pred_data[i] = prev_col*(i/c-maxrad) + i%c - maxrad; if (img_data[i] == FG && lbl_data[i] == 0) /* (**) */ dist_data[i] = INVALID_DIST; } /* OBS: condition (**) tests for lbl_data[i] == 0 because the * seed pixels don't need processing. In fact, the for loop * for the propagation starts at i=1 (distance =1), not i=0 * (distance == 0). */ break; case EXTERIOR: for (i=0; i<n; i++) { pred_data[i] = prev_col*(i/c-maxrad) + i%c - maxrad; if (img_data[i] == BG) dist_data[i] = INVALID_DIST; } break; case BOTH: for (i=0; i<n; i++) { pred_data[i] = prev_col*(i/c-maxrad) + i%c - maxrad; if (lbl_data[i] == 0) dist_data[i] = INVALID_DIST; } break; default: ANIMAL_ERR_FIRST("exact_propagation", ANIMAL_ERROR_FAILURE, "Invalid side parameter", NULL); } maxdist = (unsigned) maxrad*maxrad; /* -- distances >= 1 -- */ pt = sedr->pt; p = pt+2; for (i=1; i < (int)sedr->length && maxdist >= sedr->sqrd_dist[i]; i++) { d = (int)sedr->sqrd_dist[i]; k=1; ptr = get_list_head(seed); pi = p; pf = pt + sedr->npts[i]; do { /* loop the contour */ cp = get_list_point(ptr); x = cp % prev_col + maxrad; y = cp / prev_col + maxrad; p = pi; do { /* loop displacements with distance d */ rw = y + *p; cl = x + *(p+1); p+=2; pos = cl + lut[rw]; if (dist_data[pos] == INVALID_DIST) { dist_data[pos] = d; lbl_data[pos] = k; pred_data[pos] = cp; } /* Four-fold unroll: # of pts at any distance is a multiple of 4 */ rw = y + *p; cl = x + *(p+1); p+=2; pos = cl + lut[rw]; if (dist_data[pos] == INVALID_DIST) { dist_data[pos] = d; lbl_data[pos] = k; pred_data[pos] = cp; } rw = y + *p; cl = x + *(p+1); p+=2; pos = cl + lut[rw]; if (dist_data[pos] == INVALID_DIST) { dist_data[pos] = d; lbl_data[pos] = k; pred_data[pos] = cp; } rw = y + *p; cl = x + *(p+1); p+=2; pos = cl + lut[rw]; if (dist_data[pos] == INVALID_DIST) { dist_data[pos] = d; lbl_data[pos] = k; pred_data[pos] = cp; } } while (p < pf); k++; ptr = next_list_node(ptr); } while (not_nil(ptr)); } aimg = new_ann_img(image); for (i=maxrad; i<r-maxrad; i++) for (j=maxrad; j<c-maxrad; j++) { RC(aimg->label,i-maxrad, j-maxrad) = RC(lbl_img, i, j); RC(aimg->cost, i-maxrad, j-maxrad) = RC(dist, i, j); RC(aimg->pred, i-maxrad, j-maxrad) = RC(pred, i, j); } /* Liberate memory */ imfree(&img); imfree_puint32(&lbl_img); imfree_puint32(&dist); imfree_puint32(&pred); return aimg; }
IMAGE *process_pipeline(IMAGE *image){ if(!image){ /// "Не задано входное изображение" ERRX(_("No input image given")); } if(!farray || !farray_size){ /// "Не заданы параметры конвейера" WARNX(_("No pipeline parameters given")); } size_t i; Filter **far = farray; IMAGE *in = copyFITS(image); // copy original image to leave it unchanged IMAGE *processed = NULL; for(i = 0; i < farray_size; ++i, ++far){ Filter *f = *far; DBG("Got filter #%d: w=%d, h=%d, sx=%g, sy=%g\n", f->FilterType, f->w, f->h, f->sx, f->sy); printf("try filter %zd\n", i); Itmarray oarg = {NULL, 0}; processed = f->imfunc(in, f, &oarg); /// "Ошибка в обработке конвейера" if(!processed) ERRX(_("Error on pipeline processing!")); // TODO: what should I do with oarg??? if(oarg.size){ size_t i, l = oarg.size; //if(verbose_level){ green("got oarg: \n"); for(i = 0; i < l; ++i){ printf("%5zd: %g\n", i, oarg.data[i]); } //} char tabname[80]; snprintf(tabname, 80, "%s_CONVERSION", f->name); FITStable *tab = table_new(processed, tabname); if(tab){ table_column col = { .width = sizeof(int32_t), .repeat = l, .coltype = TINT }; int32_t *levls = MALLOC(int32_t, l); for(i = 0; i < l; ++i) levls[i] = (int32_t) i; col.contents = levls; sprintf(col.colname, "level"); *col.unit = 0; table_addcolumn(tab, &col); FREE(levls); col.contents = oarg.data; col.coltype = TDOUBLE; col.width = sizeof(double), sprintf(col.colname, "value"); sprintf(col.unit, "ADU"); table_addcolumn(tab, &col); printf("Create table:\n"); table_print(tab); } FREE(oarg.data); } processed->keylist = in->keylist; char changes[FLEN_CARD]; snprintf(changes, FLEN_CARD, "HISTORY modified by routine %s", f->name); list_add_record(&(processed->keylist), changes); //list_print(processed->keylist); in->keylist = NULL; // prevent deleting global keylist imfree(&in); in = processed; } return processed; }
/** * read FITS file and fill 'IMAGE' structure (with headers and tables) * can't work with image stack - opens the first image met * works only with binary tables */ IMAGE* readFITS(char *filename, IMAGE **fits){ FNAME(); #define TRYRET(f, ...) do{TRYFITS(f, __VA_ARGS__); if(fitsstatus) goto returning;}while(0) fitsfile *fp; int i, j, hdunum = 0, hdutype, nkeys, keypos; int naxis; long naxes[2]; char card[FLEN_CARD]; IMAGE *img = MALLOC(IMAGE, 1); TRYRET(fits_open_file, &fp, filename, READONLY); FITSFUN(fits_get_num_hdus, fp, &hdunum); if(hdunum < 1){ WARNX(_("Can't read HDU")); fitsstatus = 1; goto returning; } // get image dimensions TRYRET(fits_get_img_param, fp, 2, &img->dtype, &naxis, naxes); if(naxis > 2){ WARNX(_("Images with > 2 dimensions are not supported")); fitsstatus = 1; goto returning; } img->width = naxes[0]; img->height = naxes[1]; DBG("got image %ldx%ld pix, bitpix=%d", naxes[0], naxes[1], img->dtype); // loop through all HDUs KeyList *list = img->keylist; int imghdu = -1; for(i = 1; !(fits_movabs_hdu(fp, i, &hdutype, &fitsstatus)); ++i){ int hdutype; TRYFITS(fits_get_hdu_type, fp, &hdutype); // types: IMAGE_HDU , ASCII_TBL, BINARY_TBL if(fitsstatus) continue; DBG("HDU type %d", hdutype); //if(hdutype == ASCII_TBL || hdutype == BINARY_TBL){ if(hdutype == BINARY_TBL){ table_read(img, fp); continue; } if(imghdu < 1) imghdu = i; TRYFITS(fits_get_hdrpos, fp, &nkeys, &keypos); if(fitsstatus) continue; //DBG("HDU # %d of %d keys", i, nkeys); for(j = 1; j <= nkeys; ++j){ FITSFUN(fits_read_record, fp, j, card); if(!fitsstatus){ if(!list_add_record(&list, card)){ /// "Не могу добавить запись в список" WARNX(_("Can't add record to list")); } //DBG("key %d: %s", j, card); } } } img->keylist = list; if(fitsstatus == END_OF_FILE){ fitsstatus = 0; }else{ fits_report_error(stderr, fitsstatus); goto returning; } if(fits_movabs_hdu(fp, imghdu, &hdutype, &fitsstatus)){ WARNX(_("Can't open image HDU #%d"), imghdu); fitsstatus = 1; goto returning; } size_t sz = naxes[0] * naxes[1]; img->data = MALLOC(double, sz); int stat = 0; TRYFITS(fits_read_img, fp, TDOUBLE, 1, sz, NULL, img->data, &stat); if(stat) WARNX(_("Found %d pixels with undefined value"), stat); DBG("ready"); #undef TRYRET returning: if(fitsstatus){ imfree(&img); } FITSFUN(fits_close_file, fp); if(fits){ FREE(*fits); *fits = img; } return img; }