bool loadIndexedStackFFMpeg( QByteArray* buffer, Image4DSimple& img, int channel, int num_channels, long width, long height ) { try { FFMpegVideo video( buffer ); if ( ! video.isOpen ) return false; int sx = video.getWidth(); int sy = video.getHeight(); int sz = video.getNumberOfFrames(); int sc = video.getNumberOfChannels(); // cout << "Number of frames = " << sz << endl; if ( channel == 0 ) img.createBlankImage( width, height, sz, num_channels, 1 ); // 1 byte = 8 bits per value Image4DProxy<Image4DSimple> proxy( &img ); int frameCount = 0; for ( int z = 0; z < sz; ++z ) { video.fetchFrame( z ); // int z = frameCount; frameCount++; for ( int y = 0; y < height; ++y ) { for ( int x = 0; x < width; ++x ) { proxy.put_at( x, y, z, channel, video.getPixelIntensity( x, y, ( FFMpegVideo::Channel )0 ) ); } } } cout << "Number of frames found = " << frameCount << endl; return true; } catch ( ... ) {} return false; }
bool loadStackFFMpegAsGray( QUrl url, Image4DSimple& img ) { try { FFMpegVideo video( url ); int sx = video.getWidth(); int sy = video.getHeight(); int sz = video.getNumberOfFrames(); int sc = video.getNumberOfChannels(); // cout << "Number of frames = " << sz << endl; img.createBlankImage( sx, sy, sz, 1, 1 ); // 1 byte = 8 bits per value Image4DProxy<Image4DSimple> proxy( &img ); int frameCount = 0; for ( int z = 0; z < sz; ++z ) { video.fetchFrame( z ); // int z = frameCount; frameCount++; for ( int y = 0; y < sy; ++y ) { for ( int x = 0; x < sx; ++x ) { // Use average of R,G,B as gray value int val = 0; for ( int c = 0; c < sc; ++c ) { val += video.getPixelIntensity( x, y, ( FFMpegVideo::Channel )c ); } val /= sc; // average of rgb proxy.put_at( x, y, z, 0, val ); } } } // cout << "Number of frames found = " << frameCount << endl; return true; } catch ( ... ) {} return false; }
bool loadStackFFMpeg( QUrl url, Image4DSimple& img ) { try { FFMpegVideo video( url ); if ( ! video.isOpen ) return false; int sx = video.getWidth(); int sy = video.getHeight(); int sz = video.getNumberOfFrames(); int sc = video.getNumberOfChannels(); // cout << "Number of frames = " << sz << endl; img.createBlankImage( sx, sy, sz, sc, 1 ); // 1 byte = 8 bits per value Image4DProxy<Image4DSimple> proxy( &img ); int frameCount = 0; for ( int z = 0; z < sz; ++z ) { video.fetchFrame( z ); // int z = frameCount; frameCount++; for ( int c = 0; c < sc; ++c ) { for ( int y = 0; y < sy; ++y ) { for ( int x = 0; x < sx; ++x ) { proxy.put_at( x, y, z, c, video.getPixelIntensity( x, y, ( FFMpegVideo::Channel )c ) ); } } } } cout << "Number of frames found = " << frameCount << endl; return true; } catch ( ... ) {} return false; }
void GVFplugin::domenu(const QString &menu_name, V3DPluginCallback2 &callback, QWidget *parent) { if (menu_name == tr("Gradient vector flow based Segmentation")) { // the GVF function wants a pointer to a Vol3DSimple, which I haven't seen before. // this code below generates it (take from plugin_FL_cellseg) // check what's up with the current window: is there a valid image pointer? v3dhandle curwin = callback.currentImageWindow(); if (!curwin) { v3d_msg("Please open an image."); return; } Image4DSimple* subject = callback.getImage(curwin); QString m_InputFileName = callback.getImageName(curwin); if (!subject) { QMessageBox::information(0, "", QObject::tr("No image is open.")); return; } if (subject->getDatatype()!=V3D_UINT8) { QMessageBox::information(0, "", QObject::tr("This demo program only supports 8-bit data. Your current image data type is not supported.")); return; } V3DLONG sz0 = subject->getXDim(); V3DLONG sz1 = subject->getYDim(); V3DLONG sz2 = subject->getZDim(); V3DLONG sz3 = subject->getCDim(); Image4DProxy<Image4DSimple> pSub(subject); V3DLONG channelsz = sz0*sz1*sz2; float *pLabel = 0; unsigned char *pData = 0; gvfsegPara segpara; // set these fields one at a time: segpara.diffusionIteration= 5; segpara.fusionThreshold = 10; segpara.minRegion = 10; segpara.sigma = 3; // doesn't seem to be used in the actual function? //input parameters bool ok1; int c=1; if (sz3>1) //only need to ask if more than one channel { c = QInputDialog::getInteger(parent, "Channel", "Choose channel for segmentation:", 1, 1, sz3, 1, &ok1); c = c-1; //channels are indexed to 0 in Image4DSimple->getRawDataAtChannel if (!ok1) return; } // read in parameters segpara.diffusionIteration = QInputDialog::getInteger(parent, "Diffusion Iterations", "Choose Number of Diffusion Iterations:", 5, 1, 10, 1, &ok1); if (!ok1) return; segpara.fusionThreshold = QInputDialog::getInteger(parent, "Fusion Threshold", "Choose Fusion Threshold :", 2, 1, 10, 1, &ok1); if (!ok1) return; segpara.minRegion= QInputDialog::getInteger(parent, "Minimum Region", "Choose Minimum Region Size (voxels):", 10, 1, 1000, 1, &ok1); if (!ok1) return; // allocate memory for the images Vol3DSimple <unsigned char> * tmp_inimg = 0; Vol3DSimple <USHORTINT16> * tmp_outimg = 0; try { tmp_inimg = new Vol3DSimple <unsigned char> (sz0, sz1, sz2); tmp_outimg = new Vol3DSimple <USHORTINT16> (sz0, sz1, sz2); } catch (...) { v3d_msg("Unable to allocate memory for processing."); if (tmp_inimg) {delete tmp_inimg; tmp_inimg=0;} if (tmp_outimg) {delete tmp_outimg; tmp_outimg=0;} return; } //copy image data into our new memory memcpy((void *)tmp_inimg->getData1dHandle(), (void *)subject->getRawDataAtChannel(c), sz0*sz1*sz2); //now do computation //bool b_res = gvfCellSeg(img3d, outimg3d, segpara); bool b_res = gvfCellSeg(tmp_inimg, tmp_outimg, segpara); // clear out temporary space if (tmp_inimg) {delete tmp_inimg; tmp_inimg=0;} if (!b_res) { v3d_msg("image segmentation using gvfCellSeg() failed \n"); } else { // now display the results // parameters for the new image data V3DLONG new_sz0 = tmp_outimg->sz0(); V3DLONG new_sz1 = tmp_outimg->sz1(); V3DLONG new_sz2 = tmp_outimg->sz2(); V3DLONG new_sz3 = 1; V3DLONG tunits = new_sz0*new_sz1*new_sz2*new_sz3; // USHORTINT16 * outvol1d = new USHORTINT16 [tunits]; // USHORTINT16 * tmpImg_d1d = (USHORTINT16 *)(tmp_outimg->getData1dHandle()); memcpy((void *)outvol1d, (void *)tmp_outimg->getData1dHandle(), tunits*sizeof(USHORTINT16)); if (tmp_outimg) {delete tmp_outimg; tmp_outimg=0;} //free the space immediately for better use of memory Image4DSimple p4DImage; p4DImage.setData((unsigned char*)outvol1d, sz0, sz1, sz2, 1, V3D_UINT16); v3dhandle newwin = callback.newImageWindow(); callback.setImage(newwin, &p4DImage); callback.setImageName(newwin, QString("Segmented Image")); callback.updateImageWindow(newwin); } return; } else { v3d_msg(tr("A plugin for cell segmentation using Gradient Vector Flow. " "Developed based on the source code developed by Tianming Liu, Fuhui Long, and Hanchuan Peng (2010-2014)")); } }
void imfilling(V3DPluginCallback &callback, QWidget *parent) { v3dhandleList win_list = callback.getImageWindowList(); if(win_list.size()<1) { QMessageBox::information(0, title, QObject::tr("No image is open.")); return; } ImFillDialog dialog(callback, parent); if (dialog.exec()!=QDialog::Accepted) return; int start_t = clock(); // record time point dialog.update(); int i1 = dialog.i1; int ch = dialog.ch_rgb; bool mean_thresh = dialog.mean_thresh; int thresh, range; if(mean_thresh) { thresh = dialog.thresh; range = dialog.range; } //qDebug() << " test... " << thresh << range; bool use_marker = true; Image4DSimple* subject = callback.getImage(win_list[i1]); ROIList pRoiList=callback.getROI(win_list[i1]); QString m_InputFileName = callback.getImageName(win_list[i1]); if (!subject) { QMessageBox::information(0, title, QObject::tr("No image is open.")); return; } if (subject->getDatatype()!=V3D_UINT8) { QMessageBox::information(0, title, QObject::tr("This demo program only supports 8-bit data. Your current image data type is not supported.")); return; } //also get the landmark from the subject LandmarkList list_landmark_sub=callback.getLandmark(win_list[i1]); if(list_landmark_sub.size()<1) { use_marker = false; } else { QMessageBox msgBox; msgBox.setText("The marker has been choosen."); msgBox.setInformativeText("Do you want to use your first marker as a seed to tell image background?"); msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); msgBox.setDefaultButton(QMessageBox::Ok); int ret = msgBox.exec(); switch (ret) { case QMessageBox::Ok: // Ok was clicked break; case QMessageBox::Cancel: // Cancel was clicked return; break; default: // should never be reached break; } } unsigned char* pSbject = subject->getRawData(); long sz0 = subject->getXDim(); long sz1 = subject->getYDim(); long sz2 = subject->getZDim(); long sz3 = subject->getCDim(); long pagesz_sub = sz0*sz1*sz2; //--------------------------------------------------------------------------------------------------------------------------------------------------- //finding the bounding box of ROI bool vxy=true,vyz=true,vzx=true; // 3 2d-views QRect b_xy = pRoiList.at(0).boundingRect(); QRect b_yz = pRoiList.at(1).boundingRect(); QRect b_zx = pRoiList.at(2).boundingRect(); if(b_xy.left()==-1 || b_xy.top()==-1 || b_xy.right()==-1 || b_xy.bottom()==-1) vxy=false; if(b_yz.left()==-1 || b_yz.top()==-1 || b_yz.right()==-1 || b_yz.bottom()==-1) vyz=false; if(b_zx.left()==-1 || b_zx.top()==-1 || b_zx.right()==-1 || b_zx.bottom()==-1) vzx=false; long bpos_x, bpos_y, bpos_z, bpos_c, epos_x, epos_y, epos_z, epos_c; // 8 cases if(vxy && vyz && vzx) // all 3 2d-views { bpos_x = qBound(long(0), long(qMax(b_xy.left(), b_zx.left())), sz0-1); bpos_y = qBound(long(0), long(qMax(b_xy.top(), b_yz.top())), sz1-1); bpos_z = qBound(long(0), long(qMax(b_yz.left(), b_zx.top())), sz2-1); epos_x = qBound(long(0), long(qMin(b_xy.right(), b_zx.right())), sz0-1); epos_y = qBound(long(0), long(qMin(b_xy.bottom(), b_yz.bottom())), sz1-1); epos_z = qBound(long(0), long(qMin(b_yz.right(), b_zx.bottom())), sz2-1); } else if(!vxy && vyz && vzx) // 2 of 3 { bpos_x = qBound(long(0), long(qMax(0, b_zx.left())), sz0-1); bpos_y = qBound(long(0), long(qMax(0, b_yz.top())), sz1-1); bpos_z = qBound(long(0), long(qMax(b_yz.left(), b_zx.top())), sz2-1); epos_x = qBound(long(0), long(fmin(sz0-1, b_zx.right())), sz0-1); epos_y = qBound(long(0), long(fmin(sz1-1, b_yz.bottom())), sz1-1); epos_z = qBound(long(0), long(qMin(b_yz.right(), b_zx.bottom())), sz2-1); } else if(vxy && !vyz && vzx) { bpos_x = qBound(long(0), long(qMax(b_xy.left(), b_zx.left())), sz0-1); bpos_y = qBound(long(0), long(qMax(b_xy.top(), 0)), sz1-1); bpos_z = qBound(long(0), long(qMax(0, b_zx.top())), sz2-1); epos_x = qBound(long(0), long(qMin(b_xy.right(), b_zx.right())), sz0-1); epos_y = qBound(long(0), long(fmin(b_xy.bottom(), sz1-1)), sz1-1); epos_z = qBound(long(0), long(fmin(sz2-1, b_zx.bottom())), sz2-1); } else if(vxy && vyz && !vzx) { bpos_x = qBound(long(0), long(qMax(b_xy.left(), 0)), sz0-1); bpos_y = qBound(long(0), long(qMax(b_xy.top(), b_yz.top())), sz1-1); bpos_z = qBound(long(0), long(qMax(b_yz.left(), 0)), sz2-1); epos_x = qBound(long(0), long(fmin(b_xy.right(), sz0-1)), sz0-1); epos_y = qBound(long(0), long(qMin(b_xy.bottom(), b_yz.bottom())), sz1-1); epos_z = qBound(long(0), long(fmin(b_yz.right(), sz2-1)), sz2-1); } else if(vxy && !vyz && !vzx) // only 1 of 3 { bpos_x = qBound(long(0), long(qMax(b_xy.left(), 0)), sz0-1); bpos_y = qBound(long(0), long(qMax(b_xy.top(), 0)), sz1-1); bpos_z = 0; epos_x = qBound(long(0), long(fmin(b_xy.right(), sz0-1)), sz0-1); epos_y = qBound(long(0), long(fmin(b_xy.bottom(), sz1-1)), sz1-1); epos_z = sz2-1; } else if(!vxy && vyz && !vzx) { bpos_x = 0; bpos_y = qBound(long(0), long(qMax(0, b_yz.top())), sz1-1); bpos_z = qBound(long(0), long(qMax(b_yz.left(), 0)), sz2-1); epos_x = sz0-1; epos_y = qBound(long(0), long(fmin(sz1-1, b_yz.bottom())), sz1-1); epos_z = qBound(long(0), long(fmin(b_yz.right(), sz2-1)), sz2-1); } else if(!vxy && !vyz && vzx) { bpos_x = qBound(long(0), long(qMax(0, b_zx.left())), sz0-1); bpos_y = 0; bpos_z = qBound(long(0), long(qMax(0, b_zx.top())), sz2-1); epos_x = qBound(long(0), long(fmin(sz0-1, b_zx.right())), sz0-1); epos_y = sz1-1; epos_z = qBound(long(0), long(fmin(sz2-1, b_zx.bottom())), sz2-1); } else // 0 { bpos_x = 0; bpos_y = 0; bpos_z = 0; epos_x = sz0-1; epos_y = sz1-1; epos_z = sz2-1; } //qDebug("x %d y %d z %d x %d y %d z %d ",bpos_x,bpos_y,bpos_z,epos_x,epos_y,epos_z); //ROI extraction long sx = (epos_x-bpos_x)+1; long sy = (epos_y-bpos_y)+1; long sz = (epos_z-bpos_z)+1; long sc = sz3; // 0,1,2 //choose the channel stack long pagesz = sx*sy*sz; double meanv=0; long offset_sub = ch*pagesz_sub; //------------------------------------------------------------------------------------------------------------------------------------ // scans time int i_progress=0; int num_progress = 4; // haw many scanning process // QProgressDialog progress("Filling hole...", "Abort Image Filling", 0, num_progress, parent); progress.setWindowModality(Qt::WindowModal); // first scan progress.setValue(++i_progress); unsigned char *data1d = new unsigned char [pagesz]; if (!data1d) { printf("Fail to allocate memory.\n"); return; } else { for(long k=bpos_z; k<=epos_z; k++) { long offset_z = k*sz0*sz1; long offset_crop_z = (k-bpos_z)*sx*sy; for(long j=bpos_y; j<=epos_y; j++) { long offset_y = j*sz0 + offset_z; long offset_crop_y = (j-bpos_y)*sx + offset_crop_z; for(long i=bpos_x; i<=epos_x; i++) { data1d[(i-bpos_x) + offset_crop_y] = pSbject[offset_sub + i+offset_y]; meanv += data1d[(i-bpos_x) + offset_crop_y]; } } } } meanv /= pagesz; qDebug("mean value %lf", meanv); //---------------------------------------------------------------------------------------------------------------------------------- // preprocess the landmarker int seed_x, seed_y, seed_z; unsigned char seed_val; int range_val=3; if(use_marker) { seed_x = list_landmark_sub[0].x -1; // notice 0-based and 1-based difference seed_y = list_landmark_sub[0].y -1; seed_z = list_landmark_sub[0].z -1; seed_val = pSbject[seed_z*sz0*sz1 + seed_y*sz0 + seed_x + offset_sub]; } else { if(mean_thresh) { seed_val = thresh; range_val = range; qDebug() << "seed value" << seed_val; for(long k=bpos_z; k<=epos_z; k++) { long offset_crop_z = (k-bpos_z)*sx*sy; for(long j=bpos_y; j<=epos_y; j++) { long offset_crop_y = (j-bpos_y)*sx + offset_crop_z; for(long i=bpos_x; i<=epos_x; i++) { if(i==bpos_x || i==epos_x || j==bpos_y || j==epos_y || k==bpos_z || k==epos_z) continue; if(data1d[(i-bpos_x) + offset_crop_y] == seed_val) { seed_x = (i-bpos_x) ; seed_y = (j-bpos_y); seed_z = (k-bpos_z); break; } } } } } else { seed_val = 0; range_val = meanv; qDebug() << "seed value" << seed_val; if(seed_val<0) seed_val = 0; for(long k=bpos_z; k<=epos_z; k++) { long offset_crop_z = (k-bpos_z)*sx*sy; for(long j=bpos_y; j<=epos_y; j++) { long offset_crop_y = (j-bpos_y)*sx + offset_crop_z; for(long i=bpos_x; i<=epos_x; i++) { if(i==bpos_x || i==epos_x || j==bpos_y || j==epos_y || k==bpos_z || k==epos_z) continue; if(data1d[(i-bpos_x) + offset_crop_y] == seed_val) { seed_x = (i-bpos_x) ; seed_y = (j-bpos_y); seed_z = (k-bpos_z); break; } } } } } } qDebug("x %d y %d z %d thresh %d range %d intensity %d", seed_x, seed_y, seed_z, seed_val, range_val, data1d[seed_z*sx*sy + seed_y*sx + seed_x]); //---------------------------------------------------------------------------------------------------------------------------------- // de-alloc //if (pSbject) {delete []pSbject; pSbject=0;} // image visualized in v3d now // second scan progress.setValue(++i_progress); // 3D region growing //---------------------------------------------------------------------------------------------------------------------------------- int end_preprocess = clock(); printf("time eclapse %d s for preprocessing!\n", (end_preprocess-start_t)/1000000); enum states {Known, Alive, FarAway, Trial, BOUNDARY}; long offset_y, offset_z; offset_y=sx; offset_z=sx*sy; long neighborhood_6[6] = {-1, 1, -offset_y, offset_y, -offset_z, offset_z}; long neighborhood_26[26] = {-1, 1, -offset_y, offset_y, -offset_z, offset_z, -offset_y-1, -offset_y+1, -offset_y-offset_z, -offset_y+offset_z, offset_y-1, offset_y+1, offset_y-offset_z, offset_y+offset_z, offset_z-1, offset_z+1, -offset_z-1, -offset_z+1, -1-offset_y-offset_z, -1-offset_y+offset_z, -1+offset_y-offset_z, -1+offset_y+offset_z, 1-offset_y-offset_z, 1-offset_y+offset_z, 1+offset_y-offset_z, 1+offset_y+offset_z}; long neighbors = 26; long bound_idx = (sz-1)*sx*sy + (sy-1)*sx + sx-1; //Fast Marching HeapMinSort heap(pagesz); // initial state heap unsigned char* state = new unsigned char[pagesz]; unsigned char* phi = new unsigned char [pagesz]; bool* inserted = new bool [pagesz]; for(long k = 0; k < sz; k++) { long idxk = k*offset_z; for(long j = 0; j < sy; j++) { long idxj = idxk + j*offset_y; for(long i = 0, idx = idxj; i < sx; i++, idx++) { phi[idx] = 255; state[idx] = BOUNDARY; inserted[idx] = false; if(i==0 || i==sx-1 || j==0 || j==sy-1 || k==0 || k==sz-1) continue; if( i==seed_x && j==seed_y && k==seed_z ) { heap.insert(idx, 0); phi[idx] = 0; state[idx] = Known; inserted[idx] = true; } else state[idx] = FarAway; } } } // // // progress.setValue(++i_progress); long count=1; long wc=0; // del a point from the heap long idx; float weight; while( heap.del(&idx, &weight) ) { if( state[idx] == Alive ) continue; // using region growing critera here if( state[idx] != Known ) { for(int ineighbor=0; ineighbor<neighbors; ineighbor++) { long n_idx = idx + neighborhood_26[ineighbor]; if(n_idx<bound_idx && n_idx>0) { if(phi[n_idx] == 0 && (fabs(data1d[idx] - seed_val)<=range_val)) { phi[idx] = 0; break; } } } } else { phi[idx] = 0; } count--; wc++; //set processed one to state "Alive" state[idx] = Alive; //find new neighbors and added to heap for(int ineighbor=0; ineighbor<neighbors; ineighbor++) { long n_idx = idx + neighborhood_26[ineighbor]; if(n_idx<bound_idx && n_idx>0) { if( (state[n_idx]==FarAway || state[n_idx]==Trial) && inserted[n_idx]==false) { heap.insert(n_idx, phi[n_idx]+wc); count++; state[n_idx] = Trial; inserted[n_idx] = true; } } } } // de-alloc if (inserted) {delete []inserted; inserted=0;} if (state) {delete []state; state=0;} //---------------------------------------------------------------------------------------------------------------------------------- // third scan progress.setValue(++i_progress); int end_rgn = clock(); printf("time eclapse %d s for region growing!\n", (end_rgn-end_preprocess)/1000000); // dist transform //---------------------------------------------------------------------------------------------------------------------------------- long sz_data[4]; sz_data[0]=sx; sz_data[1]=sy; sz_data[2]=sz; sz_data[3]=1; long *pDist = new long [pagesz]; if (!pDist) { printf("Fail to allocate memory.\n"); return; } long *pLabel = new long [pagesz]; if (!pLabel) { printf("Fail to allocate memory.\n"); return; } unsigned char *pData = new unsigned char [2*pagesz]; // first filled and second dist map if (!pData) { printf("Fail to allocate memory.\n"); return; } for(long k = 0; k < sz; k++) { long idxk = k*offset_z; for(long j = 0; j < sy; j++) { long idxj = idxk + j*offset_y; for(long i = 0, idx = idxj; i < sx; i++, idx++) { if(i==0 || i==sx-1 || j==0 || j==sy-1 || k==0 || k==sz-1 || phi[idx]==0) // background and boundary { pData[idx] = 0; pData[idx + pagesz] = 0; } else { pData[idx] = 1; //data1d[idx]; pData[idx + pagesz] = 1; } } } } // de-alloc if (phi) {delete []phi; phi=0;} // dist transform dt3d_binary(pData, pDist, pLabel, sz_data, 1); long maxtest=0, mintest=INF; for(long i=0; i<pagesz; i++) { long tmp=pDist[i]; if(maxtest<tmp) maxtest=tmp; if(mintest>tmp) mintest=tmp; } maxtest -= mintest; if(maxtest) { for(long i=0; i<pagesz; i++) { unsigned char tmp = 255*(pDist[i]-mintest)/maxtest; // image blending long tmp1 = tmp + data1d[i]; pData[i] = (tmp1>255)?255:tmp1; // sum pData[i + pagesz] = tmp; } } // de-alloc if (data1d) {delete []data1d; data1d=0;} // if (pDist) {delete []pDist; pDist=0;} if (pLabel) {delete []pLabel; pLabel=0;} //---------------------------------------------------------------------------------------------------------------------------------- int end_dist = clock(); printf("time eclapse %d s for dist computing!\n", (end_dist-end_rgn)/1000000); progress.setValue(num_progress); Image4DSimple p4DImage; p4DImage.setData((unsigned char*)pData, sx, sy, sz, 2, subject->datatype); v3dhandle newwin = callback.newImageWindow(); callback.setImage(newwin, &p4DImage); callback.setImageName(newwin, QString("filled_image")); callback.updateImageWindow(newwin); }
//void startVesselTracing ( V3DPluginCallback2 &v3d, QWidget *parent ) void startVesselTracing(V3DPluginCallback2 &v3d,int xflag,int yflag,int zflag,int xbegin, int xend,int xdis,int ybegin,int yend,int ydis,int zbegin,int zend,int zdis,QString swcfile,int slipsize,int pruning_flag,int c) { v3dhandle curwin = v3d.currentImageWindow(); if (!curwin) { v3d_msg("You don't have any image open in the main window."); return; } //ensure the 3d viewer window is open; if not, then open it // v3d.open3DWindow(curwin); // get land mark list LandmarkList seedList = v3d.getLandmark(curwin); Image4DSimple* oldimg = v3d.getImage(curwin); unsigned char* data1d = oldimg->getRawDataAtChannel(c-1); ImagePixelType pixeltype = oldimg->getDatatype(); V3DLONG pagesz = oldimg->getTotalUnitNumberPerChannel(); unsigned char *output_image=0; switch (pixeltype) { case V3D_UINT8: try {output_image = new unsigned char [pagesz];} catch(...) {v3d_msg("cannot allocate memory for output_image."); return;} for(V3DLONG i = 0; i<pagesz; i++) output_image[i] = data1d[i]; break; default: v3d_msg("Invalid data type. Do nothing."); return; } V3DLONG in_sz[4]; in_sz[0] = oldimg->getXDim(); in_sz[1] = oldimg->getYDim(); in_sz[2] = oldimg->getZDim();in_sz[3] = 1; // simple_saveimage_wrapper(v3d, "temp.v3draw", (unsigned char *)output_image, in_sz, pixeltype); MOSTImage img; // set data img.setData( (unsigned char*)output_image, oldimg->getXDim(),oldimg->getYDim(),oldimg->getZDim(),oldimg->getCDim(),oldimg->getDatatype()); if ( seedList.isEmpty() ) { QTime qtime_seed; qtime_seed.start(); //img.auto_detect_seedz(seedList,img.getZDim()/2); if(xflag) { for(int i =xbegin;i<=xend;i+=xdis) img.auto_detect_seedx(seedList,i,InitThreshold,seed_size_all); // img.auto_detect_seedx(seedList,xend); } if(yflag) { for(int i =ybegin;i<=yend;i+=ydis) img.auto_detect_seedy(seedList,i,InitThreshold,seed_size_all); // img.auto_detect_seedy(seedList,yend); } if(zflag) { for(int i =zbegin;i<=zend;i+=zdis) img.auto_detect_seedz(seedList,i,InitThreshold,seed_size_all); //img.auto_detect_seedz(seedList,zend); } qDebug(" cost time seed = %g sec", qtime_seed.elapsed()*0.001); } // clear visited, only excute once static long init_flag = 0; /* if ( init_flag <= 0 ) { visited.fill( false, oldimg->getTotalUnitNumber()); init_flag ++; }*/ for(init_flag = 0;init_flag<oldimg->getTotalUnitNumber();init_flag++) { visited.push_back(false); } // converte the formate NeuronTree vt; QTime qtime; qtime.start(); vt = img.trace_seed_list(seedList, visited,InitThreshold,res_x_all,res_y_all,res_z_all,swcfile,slipsize,pruning_flag); qDebug(" cost time totol= %g sec", qtime.elapsed()*0.001); v3d_msg(QString("Now you can drag and drop the generated swc fle [%1] into Vaa3D.").arg(swcfile),1); // NeuronTree vt_old = v3d.getSWC(curwin); // visualization // v3d.setLandmark(curwin, seedList); // v3d.setSWC(curwin,vt); // v3d.pushObjectIn3DWindow(curwin); // v3d.updateImageWindow(curwin); //img.~MOSTImage(); }
bool autotrace(const V3DPluginArgList & input, V3DPluginArgList & output,V3DPluginCallback2 &callback) { cout<<"Welcome to MOST tracing"<<endl; unsigned int c=1; int InitThreshold = 20; seed_size_all = 20; int slipsize=20; if (input.size()>=2) { vector<char*> paras = (*(vector<char*> *)(input.at(1).p)); cout<<paras.size()<<endl; if(paras.size() >= 1) c = atoi(paras.at(0)); if(paras.size() >= 2) InitThreshold = atoi(paras.at(1)); if(paras.size() >= 3) seed_size_all = atoi(paras.at(2)); if(paras.size() >= 4) slipsize = atoi(paras.at(3)); } char * inimg_file = ((vector<char*> *)(input.at(0).p))->at(0); cout<<"ch = "<<c<<endl; cout<<"threshold = "<<InitThreshold<<endl; cout<<"inimg_file = "<<inimg_file<<endl; cout<<"seedsize = "<<seed_size_all<<endl; cout<<"slipsize = "<<slipsize<<endl; Image4DSimple *subject = callback.loadImage(inimg_file); if(!subject || !subject->valid()) { v3d_msg("Fail to load the input image.",0); if (subject) {delete subject; subject=0;} return false; } if( c < 1 || c > subject->getCDim()) { v3d_msg("Invalid channel input.",0); if (subject) {delete subject; subject=0;} return false; } V3DLONG N = subject->getXDim(); V3DLONG M = subject->getYDim(); V3DLONG P = subject->getZDim(); V3DLONG pagesz = N*M*P; int datatype = subject->getDatatype(); unsigned char *data1d = subject->getRawDataAtChannel(c-1); unsigned char *output_image=0; switch (datatype) { case V3D_UINT8: try {output_image = new unsigned char [pagesz];} catch(...) {v3d_msg("cannot allocate memory for output_image.",0); return false;} for(V3DLONG i = 0; i<pagesz; i++) output_image[i] = data1d[i]; break; default: v3d_msg("Invalid data type. Do nothing.",0); return false; } MOSTImage img; img.setData( (unsigned char*)output_image, subject->getXDim(),subject->getYDim(),subject->getZDim(),subject->getCDim(),subject->getDatatype()); QString swcfile = QString(inimg_file) + "_MOST.swc"; LandmarkList seedList; QTime qtime_seed; qtime_seed.start(); if(1) { for(int i =1;i<=N;i+=20) img.auto_detect_seedx(seedList,i,InitThreshold,seed_size_all); } if(1) { for(int i =1;i<=M;i+=20) img.auto_detect_seedy(seedList,i,InitThreshold,seed_size_all); } if(1) { for(int i =1;i<=P;i+=20) img.auto_detect_seedz(seedList,i,InitThreshold,seed_size_all); } qDebug(" cost time seed = %g sec", qtime_seed.elapsed()*0.001); static long init_flag = 0; for(init_flag = 0;init_flag<subject->getTotalUnitNumberPerChannel();init_flag++) { visited.push_back(false); } // converte the formate NeuronTree vt; QTime qtime; qtime.start(); vt = img.trace_seed_list(seedList, visited,InitThreshold,1.0,1.0,1.0,swcfile,slipsize,0); qDebug(" cost time totol= %g sec", qtime.elapsed()*0.001); v3d_msg(QString("\nNow you can drag and drop the generated swc fle [%1] into Vaa3D.").arg(swcfile),0); if (subject) {delete subject; subject=0;} return true; }
void set_dialog(V3DPluginCallback2 &v3d, QWidget *parent) { int x_begin; int x_end; int x_distance; int y_begin; int y_end; int y_distance; int z_begin; int z_end; int z_distance; int pruning_flag; int c; QString swcfile; int sslip; x_flag = 0; y_flag = 0; z_flag = 0; pruning_flag = 0; v3dhandle curwin = v3d.currentImageWindow(); if (!curwin) { v3d_msg("You don't have any image open in the main window."); return; } Image4DSimple* img = v3d.getImage(curwin); if (!img || !img->valid()) return; AdaTDialog dialog; dialog.endx->setMaximum(img->getXDim()); dialog.endx->setMinimum(1); dialog.endx->setValue(img->getXDim()); dialog.endy->setMaximum(img->getYDim()); dialog.endy->setMinimum(1); dialog.endy->setValue(img->getYDim()); dialog.endz->setMaximum(img->getZDim()); dialog.endz->setMinimum(1); dialog.endz->setValue(img->getZDim()); dialog.ds->setText(QString(img->getFileName()) + "_MOST.swc"); dialog.channel->setMaximum(img->getCDim()); dialog.channel->setMinimum(1);dialog.channel->setValue(1); if (dialog.exec()!=QDialog::Accepted) return; else { InitThreshold = dialog.threshould_value->value(); res_x_all = dialog.resx->value(); res_y_all = dialog.resy->value(); res_z_all = dialog.resz->value(); seed_size_all = dialog.size->value(); sslip = dialog.slipsize->value(); swcfile = dialog.ds->text(); c = dialog.channel->value(); QFile file(swcfile); if (!file.open(QIODevice::WriteOnly|QIODevice::Text)) { v3d_msg("Cannot create the swc file to write, please try it again! "); return; } if(dialog.x_select->isChecked()) { x_flag =1; x_begin = dialog.beginx->value(); x_end = dialog.endx->value(); x_distance = dialog.distancex->value(); } if(dialog.y_select->isChecked()) { y_flag =1; y_begin = dialog.beginy->value(); y_end = dialog.endy->value(); y_distance = dialog.distancey->value(); } if(dialog.z_select->isChecked()) { z_flag =1; z_begin = dialog.beginz->value(); z_end = dialog.endz->value(); z_distance = dialog.distancez->value(); } // v3d.open3DWindow(curwin); if(dialog.pruning->isChecked()) { pruning_flag =1; } startVesselTracing(v3d,x_flag,y_flag,z_flag,x_begin,x_end,x_distance,y_begin,y_end,y_distance,z_begin,z_end,z_distance,swcfile,sslip,pruning_flag,c); } return; }
bool consensus_skeleton(vector<NeuronTree> & nt_list, QList<NeuronSWC> & merge_result, int method_code,V3DPluginCallback2 &callback) { double CLUSTERING_RANGE =10; //potentially, there are invalid neuron trees (massive node points, no node points, looping) remove_outliers(nt_list); int neuronNum = nt_list.size(); //initialize the image volume to record/accumulate the location votes from neurons MyBoundingBox bbUnion = neuron_trees_bb(nt_list); Point3D offset = {bbUnion.min_x ,bbUnion.min_y ,bbUnion.min_z }; float closeness = 1.0; V3DLONG sz_x = ceil((bbUnion.max_x - bbUnion.min_x ) / closeness) +1; //+0.5 to round up from float to V3DLONG V3DLONG sz_y = ceil((bbUnion.max_y - bbUnion.min_y ) / closeness) +1; V3DLONG sz_z = ceil((bbUnion.max_z - bbUnion.min_z ) / closeness) +1; V3DLONG tol_sz = sz_x * sz_y * sz_z; cout << "image size = " << tol_sz<<": " <<sz_x<<"x "<<sz_y<<" x"<<sz_z<< endl; unsigned char * img1d = new unsigned char[tol_sz]; for(V3DLONG i = 0; i < tol_sz; i++) img1d[i] = 0; //count for (int j =0; j < nt_list.size(); j++){ NeuronTree nt = nt_list[j]; for (int i =0; i < nt.listNeuron.size(); i++) { NeuronSWC node = nt.listNeuron.at(i); V3DLONG id_x = (node.x-offset.x) +0.5; //round up V3DLONG id_y = (node.y-offset.y) +0.5; V3DLONG id_z = (node.z-offset.z) +0.5; V3DLONG idx = id_z * (sz_x*sz_y) + id_y * sz_x + id_x; if (idx <tol_sz ){ img1d[idx] ++ ;} else{ cout <<"error idx" <<endl; } } } //for debug only Image4DSimple *image = new Image4DSimple(); image->setData(img1d, sz_x, sz_y, sz_z, 1, V3D_UINT8); callback.saveImage(image, "./vote_count_image.v3draw"); //non-maximum suppresion vector<Point3D> node_list; vector<unsigned int> vote_list; non_max_suppresion (img1d,sz_x,sz_y,sz_z,offset,node_list,vote_list,3); cout << "After non_max supression:"<< endl; cout << "number of nodes:"<< node_list.size() << endl; cout << "maximum votes:" << v_min(vote_list) << endl; cout << "minimum votes:" << v_max(vote_list) << endl; Image4DSimple *image2 = new Image4DSimple(); image2->setData(img1d, sz_x, sz_y, sz_z, 1, V3D_UINT8); callback.saveImage(image2, "./nms_image.v3draw"); // for debug: save node_list to check locations QList<NeuronSWC> locationTree; for (int i=0;i<node_list.size();i++) { NeuronSWC tmp; tmp.x = node_list[i].x; tmp.y = node_list[i].y; tmp.z = node_list[i].z; tmp.type = 2; //edge votes tmp.pn = -1; //parent id, form the edge tmp.r = double(vote_list[i])/neuronNum*3; //*3 for visulaization tmp.n = i+1; locationTree.append(tmp); } export_listNeuron_2swc(locationTree, "./testlocation.swc"); printf("(2). compute adjacency matrix (vote for edges).\n"); double * adjMatrix; V3DLONG * plist; V3DLONG num_nodes = node_list.size(); try{ adjMatrix = new double[num_nodes*num_nodes]; plist = new V3DLONG[num_nodes]; for (V3DLONG i=0;i<num_nodes*num_nodes;i++) adjMatrix[i] = 0; } catch (...) { fprintf(stderr,"fail to allocate memory.\n"); if (adjMatrix) {delete[] adjMatrix; adjMatrix=0;} if (plist) {delete[] plist; plist=0;} return false; } for (int i=0;i<neuronNum;i++) { QHash<V3DLONG, V3DLONG > nodeMap; for (V3DLONG j=0;j<nt_list[i].listNeuron.size();j++) { NeuronSWC s = nt_list[i].listNeuron.at(j); Point3D cur; cur.x = s.x; cur.y = s.y; cur.z = s.z; //find its nearest node V3DLONG node_id = -1;// this node does not exist double min_dis = CLUSTERING_RANGE; //threshold to ignore mapping (too far away) for (V3DLONG ni = 0; ni <node_list.size(); ni++) { Point3D p = node_list[ni]; double dis = PointDistance(p,cur); if (dis < min_dis){ min_dis = dis; node_id = ni; } } if (node_id > -1){ nodeMap.insert( j, node_id); } } //maps.push_back(nodeMap); for (V3DLONG j=0;j<nt_list[i].listNeuron.size();j++) { NeuronSWC cur = nt_list[i].listNeuron[j]; // if (cur.pn<0) continue; V3DLONG n_id,pn_id; n_id = nodeMap[j]; if (n_id > 0){ V3DLONG pidx = cur.pn-1;//nt_list[i].hashNeuron.value(cur.pn); // find the index in nueon_list pn_id = nodeMap[pidx]; if (pn_id > 0){ adjMatrix[n_id*num_nodes + pn_id] += 1; adjMatrix[pn_id*num_nodes + n_id] += 1; //cout<<adjMatrix[n_id*num_nodes + pn_id] <<endl; } } } } if (method_code ==0 ){ long rootnode =100; printf("(3). computing minimum-spanning tree.\n"); //if (!mst_dij(adjMatrix, num_nodes, plist, rootnode)) if (!mst_prim(adjMatrix, num_nodes, plist, rootnode)) { fprintf(stderr,"Error in minimum spanning tree!\n"); return false; } printf("(3). genearate consensus graph swc file by assign parents (form edges).\n"); // code the edge votes into type for visualization // graph: duplicate swc nodes are allowed to accomandate mutiple parents for the child node, no root id, merge_result.clear(); for (V3DLONG i = 0;i <num_nodes;i ++) { V3DLONG p = plist[i]; //cout <<p<<endl; unsigned int edgeVote = adjMatrix[i*num_nodes + p]; NeuronSWC tmp; tmp.x = node_list[i].x; tmp.y = node_list[i].y; tmp.z = node_list[i].z; tmp.type = edgeVote; //edge votes tmp.pn = p + 1; //parent id, form the edge tmp.r = double(vote_list[i])/double(neuronNum); tmp.n = i+1; merge_result.append(tmp); } } //### output vertices ( node lcoations) // V3DLONG count = 0; // for (V3DLONG i=0;i<num_nodes;i++) // { // NeuronSWC tmp; // tmp.x = node_list[i].x; // tmp.y = node_list[i].y; // tmp.z = node_list[i].z; // // tmp.fea_val.push_back(vote_list[i]); //location votes are coded into radius // tmp.type = 0; //vertices (soma) // tmp.pn = -1; //parent id, no edge // tmp.r = double(vote_list[i])/double(neuronNum); //location votes are coded into radius // tmp.n = count +1; //id start from 1 // merge_result.append(tmp); // count++; // } // //output edges, go through half of the symmetric matrix, not directed graph // for (V3DLONG row = 0;row <num_nodes;row ++) // { // for (V3DLONG col = row+1;col < num_nodes;col++){ // unsigned int edgeVote = adjMatrix[row*num_nodes + col]; // if (edgeVote > 1) // { // NeuronSWC tmp; // tmp.x = node_list[row].x; // tmp.y = node_list[row].y; // tmp.z = node_list[row].z; // tmp.type = edgeVote; //edge votes // tmp.pn = col + 1; //parent id , form the edge // tmp.r = double(vote_list[row])/double(neuronNum); // tmp.n = count+1; // merge_result.append(tmp); // count++; // } // } // } // alternative if (method_code == 1){ merge_result.clear(); V3DLONG count = 0; for (V3DLONG i=0;i<num_nodes;i++) { NeuronSWC tmp; tmp.x = node_list[i].x; tmp.y = node_list[i].y; tmp.z = node_list[i].z; // tmp.fea_val.push_back(vote_list[i]); //location votes are coded into radius tmp.type = 0; //vertices (soma) tmp.pn = -1; //parent id, no edge tmp.r = double(vote_list[i])/double(neuronNum); //location votes are coded into radius tmp.n = count +1; //id start from 1 merge_result.append(tmp); count++; } //output edges, go through half of the symmetric matrix, not directed graph for (V3DLONG row = 0;row <num_nodes;row ++) { for (V3DLONG col = row+1;col < num_nodes;col++){ unsigned int edgeVote = adjMatrix[row*num_nodes + col]; if (edgeVote > 0) { if (merge_result[row].pn == -1) {//exsiting isolated vertex, modify parent id merge_result[row].type = edgeVote; //edge votes merge_result[row].pn = col + 1; //parent id , form the edge merge_result[row].r = double(vote_list[row])/double(neuronNum); } else{ //add new edge , via duplication nodes with different parent id and edge votes NeuronSWC tmp; tmp.x = node_list[row].x; tmp.y = node_list[row].y; tmp.z = node_list[row].z; tmp.type = edgeVote; //edge votes tmp.pn = col + 1; //parent id , form the edge tmp.r = double(vote_list[row])/double(neuronNum); tmp.n = count+1; merge_result.append(tmp); count++; } } } } } if (adjMatrix) {delete[] adjMatrix; adjMatrix = 0;} if (plist) {delete[] plist; plist=0;} return true; }
/********************************************************************************** * Returns a new, gaussian-noise corrupted image from the given image ***********************************************************************************/ Image4DSimple* CImageUtils::addGaussianNoise( Image4DSimple* im, // input image float w) // gaussian noise weight (1 = only noise, 0 = no noise) throw (tf::RuntimeException) { // checks if(!im || !im->getRawData()) throw tf::RuntimeException("in CImageUtils::addGaussianNoise(): invalid image data"); if(im->getTDim() > 1) throw tf::RuntimeException(tf::strprintf("in CImageUtils::addGaussianNoise(): image has TDim = %d (5D not supported)", im->getTDim())); // allocate new image Image4DSimple* imout = new Image4DSimple(); imout->setXDim(im->getXDim()); imout->setYDim(im->getYDim()); imout->setZDim(im->getZDim()); imout->setCDim(im->getCDim()); imout->setTDim(im->getTDim()); imout->setDatatype(im->getDatatype()); V3DLONG data_size = imout->getTotalBytes(); unsigned char* data = new unsigned char[data_size]; imout->setRawDataPointer(data); // data corruption if(imout->getDatatype() == V3D_UINT8) { unsigned char* data_in = im->getRawData(); for(V3DLONG k=0; k<data_size; k++) data[k] = static_cast<tf::uint8>((1-w)*data_in[k] + w*(rand()%256) +0.5f); } else if(imout->getDatatype() == V3D_UINT16) { unsigned short* data_in = (unsigned short*)(im->getRawData()); for(V3DLONG k=0; k<data_size/2; k++) data[k] = static_cast<tf::uint16>((1-w)*data_in[k] + w*(rand()%65535) +0.5f); } else throw tf::RuntimeException("in CImageUtils::addGaussianNoise(): image is neither UINT8 nor UINT16 (not supported)"); return imout; }
void bwlabelimg(V3DPluginCallback2 &callback, QWidget *parent, int method_code) { v3dhandle curwin = callback.currentImageWindow(); if (!curwin) { v3d_msg("You don't have any image open in the main window."); return; } if (method_code!=3 && method_code!=2) { v3d_msg("Invalid BWLabel method code. You should never see this message. Report this bug to the developer"); return; } LabelImgObjectParaDialog dialog(callback, parent); if (!dialog.image) return; if (dialog.exec()!=QDialog::Accepted) return; V3DLONG ch = dialog.ch; V3DLONG th_idx = dialog.th_idx; double tt = dialog.thresh; V3DLONG volsz_thres = (dialog.b_filtersmallobjs) ? dialog.volsz : 0; //the threshold to filter out small objects int start_t = clock(); // record time Image4DSimple* subject = callback.getImage(curwin); QString m_InputFileName = callback.getImageName(curwin); if (!subject) { QMessageBox::information(0, title, QObject::tr("No image is open.")); return; } if (subject->getDatatype()!=V3D_UINT8) { QMessageBox::information(0, title, QObject::tr("This demo program only supports 8-bit data. Your current image data type is not supported.")); return; } if (th_idx==0 || th_idx==1) { double mm, vv; mean_and_std(subject->getRawDataAtChannel(ch), subject->getTotalUnitNumberPerChannel(), mm, vv); tt = (th_idx == 0) ? mm : mm+vv; v3d_msg(QString("in fast image object labeling: ch=%1 mean=%2 std=%2").arg(ch).arg(mm).arg(vv), 0); } Image4DProxy<Image4DSimple> pSub(subject); V3DLONG sz0 = subject->getXDim(); V3DLONG sz1 = subject->getYDim(); V3DLONG sz2 = subject->getZDim(); V3DLONG sz3 = subject->getCDim(); //---------------------------------------------------------------------------------------------------------------------------------- V3DLONG channelsz = sz0*sz1*sz2; unsigned short int *pLabel = 0; unsigned char *pData = 0; try { pLabel = new unsigned short int [channelsz]; pData = new unsigned char [channelsz]; } catch (...) { v3d_msg("Fail to allocate memory in Fast Object Labeling Plugin."); if (pLabel) {delete []pLabel; pLabel=0;} if (pData) {delete []pData; pData=0;} return; } unsigned char * pSubtmp = pSub.begin(); for(V3DLONG i = 0; i < channelsz; i++) { pData[i] = (pSubtmp[i]<=tt) ? 0 : 1; } // dist transform V3DLONG sz_data[4]; sz_data[0]=sz0; sz_data[1]=sz1; sz_data[2]=sz2; sz_data[3]=1; V3DLONG nobjs=0; if (method_code==3) { V3DLONG nh_code=26; //6,18,or 26 nobjs = findConnectedComponent(pData, sz_data, 3, nh_code, pLabel); } else if (method_code==2) { V3DLONG nh_code=8; //4 or 8 nobjs = findConnectedComponent(pData, sz_data, 2, nh_code, pLabel); } else { v3d_msg("Invalid BWLabelN method code. You should never see this message. Report this bug to the developer"); return; } if (pData) {delete []pData; pData=0;} if (volsz_thres>0) //filter out small objects { try { float * hh = new float [nobjs]; float * mapval = new float [nobjs]; V3DLONG j; for (j=0;j<nobjs;j++) {hh[j]=0; mapval[j]=j;} //of course, 0 also map to 0! for (j=0;j<channelsz;j++) { //pLabel[j]--; //it seems Fuhui's data is 1-based, so subtract 1. Is this correct? hh[pLabel[j]]++; } V3DLONG k=0; for (j=1;j<nobjs;j++) //start from 1 as it is the background! { if (hh[j]<volsz_thres) { mapval[j]=0; //if less than a thres, then map to 0, which is background } else { printf("Obj [%ld] = [%ld]\n", V3DLONG(j), V3DLONG(hh[j])); k++; mapval[j] = k; //otherwise map to a continous label-value } } for (j=0;j<channelsz;j++) pLabel[j] = mapval[pLabel[j]]; if (hh) {delete []hh; hh=0;} if (mapval) {delete []mapval; mapval=0;} } catch (...) { v3d_msg("Unable to allocate memory to filter small objects. Thus skip it."); } } //---------------------------------------------------------------------------------------------------------------------------------- int end_t = clock(); printf("time eclapse %d s for labeling objects!\n", (end_t-start_t)/1000000); Image4DSimple p4DImage; p4DImage.setData((unsigned char*)pLabel, sz0, sz1, sz2, 1, V3D_UINT16); v3dhandle newwin = callback.newImageWindow(); callback.setImage(newwin, &p4DImage); callback.setImageName(newwin, QString("Object-Labeled Image")); callback.updateImageWindow(newwin); }
// show different datatype data in V3D int datatype_converting(V3DPluginCallback2 &callback, QWidget *parent) { v3dhandleList win_list = callback.getImageWindowList(); if(win_list.size()<1) { v3d_msg("No image is open."); return -1; } // DTCDialog dialog(callback,parent); if (dialog.exec()!=QDialog::Accepted) return -1; dialog.update(); V3DLONG isub = dialog.isub; V3DLONG dt = dialog.dt; // ImagePixelType cnvrt_dt; if(dt==0) { cnvrt_dt = V3D_UINT8; } else if(dt==1) { cnvrt_dt = V3D_UINT16; } else if(dt==2) { cnvrt_dt = V3D_FLOAT32; } Image4DSimple* subject = callback.getImage(win_list[isub]); if (!subject) { QMessageBox::information(0, title, QObject::tr("Image does not exist.")); return -1; } unsigned char* subject1d = subject->getRawData(); V3DLONG sx = subject->getXDim(); V3DLONG sy = subject->getYDim(); V3DLONG sz = subject->getZDim(); V3DLONG sc = subject->getCDim(); V3DLONG sz_sub = sx*sy*sz*sc; ImagePixelType sub_dt = subject->getDatatype(); //Converting if(cnvrt_dt == V3D_UINT8) { unsigned char * data1d = NULL; try { data1d = new unsigned char [sz_sub]; } catch(...) { printf("Error allocating memory. \n"); return -1; } // if(sub_dt == V3D_UINT8) { converting<unsigned char, unsigned char>((unsigned char *)subject1d, data1d, sz_sub, cnvrt_dt); } else if(sub_dt == V3D_UINT16) { converting<unsigned short, unsigned char>((unsigned short *)subject1d, data1d, sz_sub, cnvrt_dt); } else if(sub_dt == V3D_FLOAT32) { converting<float, unsigned char>((float *)subject1d, data1d, sz_sub, cnvrt_dt); } //display Image4DSimple p4DImage; p4DImage.setData((unsigned char*)data1d, sx, sy, sz, sc, V3D_UINT8); // v3dhandle newwin = callback.newImageWindow(); callback.setImage(newwin, &p4DImage); callback.setImageName(newwin, "Converted Image"); callback.updateImageWindow(newwin); } else if(cnvrt_dt == V3D_UINT16) { unsigned short * data1d = NULL; try { data1d = new unsigned short [sz_sub]; } catch(...) { printf("Error allocating memory. \n"); return -1; } // if(sub_dt == V3D_UINT8) { converting<unsigned char, unsigned short>((unsigned char *)subject1d, data1d, sz_sub, cnvrt_dt); } else if(sub_dt == V3D_UINT16) { converting<unsigned short, unsigned short>((unsigned short *)subject1d, data1d, sz_sub, cnvrt_dt); } else if(sub_dt == V3D_FLOAT32) { converting<float, unsigned short>((float *)subject1d, data1d, sz_sub, cnvrt_dt); } //display Image4DSimple p4DImage; p4DImage.setData((unsigned char*)data1d, sx, sy, sz, sc, V3D_UINT16); // v3dhandle newwin = callback.newImageWindow(); callback.setImage(newwin, &p4DImage); callback.setImageName(newwin, "Converted Image"); callback.updateImageWindow(newwin); } else if(cnvrt_dt == V3D_FLOAT32) { float * data1d = NULL; try { data1d = new float [sz_sub]; } catch(...) { printf("Error allocating memory. \n"); return -1; } // if(sub_dt == V3D_UINT8) { converting<unsigned char, float>((unsigned char *)subject1d, data1d, sz_sub, cnvrt_dt); } else if(sub_dt == V3D_UINT16) { converting<unsigned short, float>((unsigned short *)subject1d, data1d, sz_sub, cnvrt_dt); } else if(sub_dt == V3D_FLOAT32) { converting<float, float>((float *)subject1d, data1d, sz_sub, cnvrt_dt); } //display Image4DSimple p4DImage; p4DImage.setData((unsigned char*)data1d, sx, sy, sz, sc, V3D_FLOAT32); // v3dhandle newwin = callback.newImageWindow(); callback.setImage(newwin, &p4DImage); callback.setImageName(newwin, "Converted Image"); callback.updateImageWindow(newwin); } else { printf("Currently this program only support UINT8, UINT16, and FLOAT32 data type.\n"); return -1; } // return 0; }
void FL_cellseg(V3DPluginCallback2 &callback, QWidget *parent) { v3dhandle curwin = callback.currentImageWindow(); if (!curwin) { v3d_msg("You don't have any image open in the main window."); return; } Image4DSimple* subject = callback.getImage(curwin); QString m_InputFileName = callback.getImageName(curwin); if (!subject) { QMessageBox::information(0, title, QObject::tr("No image is open.")); return; } if (subject->getDatatype()!=V3D_UINT8) { QMessageBox::information(0, title, QObject::tr("This demo program only supports 8-bit data. Your current image data type is not supported.")); return; } V3DLONG sz0 = subject->getXDim(); V3DLONG sz1 = subject->getYDim(); V3DLONG sz2 = subject->getZDim(); V3DLONG sz3 = subject->getCDim(); Image4DProxy<Image4DSimple> pSub(subject); //---------------------------------------------------------------------------------------------------------------------------------- V3DLONG channelsz = sz0*sz1*sz2; float *pLabel = 0; unsigned char *pData = 0; //get the segmentation parameters segParameter segpara; dialog_watershed_para *p_mydlg=0; if (!p_mydlg) p_mydlg = new dialog_watershed_para(&segpara, subject); int res = p_mydlg->exec(); if (res!=QDialog::Accepted) return; else p_mydlg->fetchData(&segpara); if (p_mydlg) {delete p_mydlg; p_mydlg=0;} // now allocate memory and do computation int start_t = clock(); Vol3DSimple <unsigned char> * tmp_inimg = 0; Vol3DSimple <USHORTINT16> * tmp_outimg = 0; try { tmp_inimg = new Vol3DSimple <unsigned char> (sz0, sz1, sz2); tmp_outimg = new Vol3DSimple <USHORTINT16> (sz0, sz1, sz2); } catch (...) { v3d_msg("Unable to allocate memory for processing. Do nothing."); if (tmp_inimg) {delete tmp_inimg; tmp_inimg=0;} if (tmp_outimg) {delete tmp_outimg; tmp_outimg=0;} return; } //do computation memcpy((void *)tmp_inimg->getData1dHandle(), (void *)subject->getRawDataAtChannel(segpara.channelNo), sz0*sz1*sz2); bool b_res = FL_cellseg(tmp_inimg, tmp_outimg, segpara); if (tmp_inimg) {delete tmp_inimg; tmp_inimg=0;} //free the space immediately for better use of memory if (!b_res) { v3d_msg("Fail to do the cell segmentation using FL_cellseg().\n"); } else { V3DLONG new_sz0 = tmp_outimg->sz0(); V3DLONG new_sz1 = tmp_outimg->sz1(); V3DLONG new_sz2 = tmp_outimg->sz2(); V3DLONG new_sz3 = 1; V3DLONG tunits = new_sz0*new_sz1*new_sz2*new_sz3; USHORTINT16 * outvol1d = new USHORTINT16 [tunits]; USHORTINT16 * tmpImg_d1d = (USHORTINT16 *)(tmp_outimg->getData1dHandle()); memcpy((void *)outvol1d, (void *)tmp_outimg->getData1dHandle(), tunits*sizeof(USHORTINT16)); if (tmp_outimg) {delete tmp_outimg; tmp_outimg=0;} //free the space immediately for better use of memory Image4DSimple p4DImage; p4DImage.setData((unsigned char*)outvol1d, sz0, sz1, sz2, 1, V3D_UINT16); v3dhandle newwin = callback.newImageWindow(); callback.setImage(newwin, &p4DImage); callback.setImageName(newwin, QString("Segmented Image")); callback.updateImageWindow(newwin); } //---------------------------------------------------------------------------------------------------------------------------------- int end_t = clock(); printf("time eclapse %d s for labeling objects!\n", (end_t-start_t)/1000000); }
void ThreadedTracer::run(){ qDebug()<<"loadScan input: "<<latestString; //QString latestString = getFileString(); // latestString =QString("/data/mat/BRL/DATA_FOR_GROUP/testDataForZhi/ZSeries-06092016-1407-8470/ZSeries-06092016-1407-8470_Cycle00001_Ch1_000001.ome.tif"); // bool isAdaptive = 1; // int methodChoice = 1; //LandmarkList inputRootList; QString fString; fString = QString("Cycle%1").arg(tileNumber,5,10,QLatin1Char('0')); qDebug()<<tileNumber; QList<LandmarkList> newTipsList; LandmarkList newTargetList; QFileInfo imageFileInfo = QFileInfo(latestString); if (imageFileInfo.isReadable()){ Image4DSimple * pNewImage = cb->loadImage(latestString.toLatin1().data()); QDir imageDir = imageFileInfo.dir(); QStringList filterList; filterList.append(QString("*").append(fString).append("_Ch").append(channel).append("*.tif")); qDebug()<<"filterlist.first()"<<filterList.first(); imageDir.setNameFilters(filterList); QStringList fileList = imageDir.entryList(); //use this to id the number of images in the stack (in one channel?!) V3DLONG x = pNewImage->getXDim(); V3DLONG y = pNewImage->getYDim(); V3DLONG nFrames = fileList.length(); V3DLONG tunits = x*y*nFrames; unsigned short int * total1dData = new unsigned short int [tunits]; unsigned short int * total1dData_mip= new unsigned short int [x*y]; for(V3DLONG i =0 ; i < x*y; i++) total1dData_mip[i] = 0; V3DLONG totalImageIndex = 0; double p_vmax=0; qDebug()<<"nFrames = "<<nFrames; for (int f=0; f<nFrames; f++){ qDebug()<<fileList[f]; Image4DSimple * pNewImage = cb->loadImage(imageDir.absoluteFilePath(fileList[f]).toLatin1().data()); if (pNewImage->valid()){ unsigned short int * data1d = 0; data1d = new unsigned short int [x*y]; data1d = (unsigned short int*)pNewImage->getRawData(); for (V3DLONG i = 0; i< (x*y); i++) { total1dData[totalImageIndex]= data1d[i]; if(data1d[i] > p_vmax) p_vmax = data1d[i]; if(total1dData_mip[i] < data1d[i]) total1dData_mip[i] = data1d[i]; totalImageIndex++; } if(data1d) {delete []data1d; data1d = 0;} }else{ qDebug()<<imageDir.absoluteFilePath(fileList[f])<<" failed!"; } } Image4DSimple* total4DImage = new Image4DSimple; total4DImage->setData((unsigned char*)total1dData, x, y, nFrames, 1, V3D_UINT16); Image4DSimple* total4DImage_mip = new Image4DSimple; total4DImage_mip->setData((unsigned char*)total1dData_mip, x, y, 1, 1, V3D_UINT16); QString swcString = saveDirString; swcString.append("/x_").append(QString::number((int)tileLocation.x)).append("_y_").append(QString::number((int)tileLocation.y)).append("_").append(imageFileInfo.fileName()).append(fString).append(".swc"); QString scanDataFileString = saveDirString; scanDataFileString.append("/").append("scanData.txt"); qDebug()<<scanDataFileString; QFile saveTextFile; saveTextFile.setFileName(scanDataFileString);// add currentScanFile if (!saveTextFile.isOpen()){ if (!saveTextFile.open(QIODevice::Text|QIODevice::Append )){ qDebug()<<"unable to save file!"; return;} } QTextStream outputStream; outputStream.setDevice(&saveTextFile); total4DImage->setOriginX(tileLocation.x); total4DImage->setOriginY(tileLocation.y); qDebug()<<total4DImage->getOriginX(); outputStream<< (int) total4DImage->getOriginX()<<" "<< (int) total4DImage->getOriginY()<<" "<<swcString<<" "<< (int) x<<" "<< (int) y<<" "<<"\n"; saveTextFile.close(); V3DLONG mysz[4]; mysz[0] = total4DImage->getXDim(); mysz[1] = total4DImage->getYDim(); mysz[2] = total4DImage->getZDim(); mysz[3] = total4DImage->getCDim(); tileLocation.ev_pc1 = (double) total4DImage->getXDim(); tileLocation.ev_pc2 = (double) total4DImage->getYDim(); QString imageSaveString = saveDirString; // add bit of code to image green - red channels. This will require an additional argument or another signal/slot combination to monitor the value of a combobox in the GUI... // add button to do || nT on mXtls //convert to 8bit image using 8 shiftnbits unsigned char * total1dData_8bit = 0; try { total1dData_8bit = new unsigned char [tunits]; } catch (...) { v3d_msg("Fail to allocate memory in total1dData_8bit.\n"); return; } double dn = pow(2.0, double(5)); for (V3DLONG i=0;i<tunits;i++) { double tmp = (double)(total1dData[i]) / dn; if (tmp>255) total1dData_8bit[i] = 255; else total1dData_8bit[i] = (unsigned char)(tmp); } total4DImage->setData((unsigned char*)total1dData_8bit, x, y, nFrames, 1, V3D_UINT8); imageSaveString.append("/x_").append(QString::number((int)tileLocation.x)).append("_y_").append(QString::number((int)tileLocation.y)).append("_").append(imageFileInfo.fileName()).append(imageFileInfo.fileName()).append(fString).append(".v3draw"); simple_saveimage_wrapper(*cb, imageSaveString.toLatin1().data(),(unsigned char *)total1dData_8bit, mysz, V3D_UINT8); qDebug()<<"=== immediately before tracing ====="; //------------- V3DPluginArgItem arg; V3DPluginArgList input; V3DPluginArgList output; QString full_plugin_name; QString func_name; arg.type = "random";std::vector<char*> arg_input; std:: string fileName_Qstring(imageSaveString.toStdString());char* fileName_string = new char[fileName_Qstring.length() + 1]; strcpy(fileName_string, fileName_Qstring.c_str()); arg_input.push_back(fileName_string); arg.p = (void *) & arg_input; input<< arg; char* char_swcout = new char[swcString.length() + 1];strcpy(char_swcout, swcString.toStdString().c_str()); arg.type = "random";std::vector<char*> arg_output;arg_output.push_back(char_swcout); arg.p = (void *) & arg_output; output<< arg; arg.type = "random"; std::vector<char*> arg_para; arg_para.push_back("1"); arg_para.push_back("1"); full_plugin_name = "neuTube"; func_name = "neutube_trace"; arg.p = (void *) & arg_para; input << arg; if(!cb->callPluginFunc(full_plugin_name,func_name,input,output)) { qDebug()<<("Can not find the tracing plugin!\n"); return; } emit done(); }else{ qDebug()<<"invalid image"; } }
//return a list of predictions ? Or a mask image? // Also need numbers of cells, and centers of cells //work on local maxima //use different preprocessing, feature extraction etc. //1d_dimension is ROIDImension + 1 //Note: be aware of the order x, y, z are passed to submethods. unsigned char* CellClassifier::annotateAnImage(V3DPluginCallback &callback, v3dhandle win, Image4DSimple* image, int ch, int grid, int dimension_1d) { std::vector <LocationSimple> detectedPos; LandmarkList markerList; long sx=image->sz0, sy=image->sz1, sz=image->sz2; long pagesz=sx*sy; long channelsz=sx*sy*sz; //smoothed and get local maxima //sensitive gaussian filtering radius // ??????? use distance transform image??????? int Wx = dimension_1d, Wy = dimension_1d, Wz = dimension_1d; unsigned char * filtered = gaussianfiltering(image->getRawData(), sx, sy, sz, Wx, Wy, Wz); unsigned char * flag_lm = check_localMaxima_ker(filtered, sx, sy, sz, 0); //unsigned char * flag_lm = check_localMaxima(callback, image, ch); //062110 unsigned char *results = new unsigned char [channelsz]; //prediction results. if (!results) { printf("Fail to allocate memory.\n"); return NULL; } unsigned char *clearFlag = new unsigned char [channelsz]; //prediction results. if (!clearFlag) { printf("Fail to allocate memory.\n"); return NULL; } //get model from file //string modelfile = "test_svm_model.txt"; struct svm_model * pmodel = pclassifier->loadSVMModel(); int r = dimension_1d/2; int prediction; int total = 0, cellcount = 0; //use (a somehow more restrict) template matching for adding some candidates. bool candidateflag = false; long cubesize = dimension_1d*dimension_1d*dimension_1d; double sigmax = (dimension_1d-1)/4.0, sigmay = (dimension_1d-1)/4.0, sigmaz = (dimension_1d-1)/4.0; double *g_1d = genGaussianKernel1D(dimension_1d, dimension_1d, dimension_1d, sigmax, sigmay, sigmaz); double curcoeff; //double coeff_th = 0.66; //will use average coeff of positive ones from training!!!! //init results for(long iz = 0; iz < sz; iz++) { long offsetk = iz*sx*sy; for(long iy = 0; iy < sy; iy++) { long offsetj = iy*sx; for(long ix = 0; ix < sx; ix++) { long idx = offsetk + offsetj + ix; results[idx] = 0; clearFlag[idx] = 1; //will be cleared later } } } //start search int denied = 0; for(long iz = r; iz < sz-r; iz++) { long offsetk = iz*sx*sy; for(long iy = r; iy < sy-r; iy++) { long offsetj = iy*sx; for(long ix = r; ix < sx-r; ix++) { long idx = offsetk + offsetj + ix; //debug: //if(ix == 61 && iy==39 && iz==17) cout << "the missed one is here!!" << (int) flag_lm[idx] << endl; //if(ix == 63 && iy ==43 && iz ==16) cout << "the valley one (#3) is here!!" << (int) flag_lm[idx] << endl;; //if(ix == 65 && iy ==43 && iz ==14) cout << "the valley start point is here!!" << (int) flag_lm[idx] << endl;; if(flag_lm[idx] == 255 && clearFlag[idx] == 1 ) //only work on local maxima (and not cleared) { //classify to see if it is a center prediction = classifyAVoxel(image, ch, iz, iy, ix, dimension_1d, pmodel); if(prediction == 0) denied ++; candidateflag = false; if (prediction == 1 || candidateflag) { //cellcount ++; //results[idx] = 255; // double ncx, ncy, ncz; unsigned char * currentCube =getACube(image, ch, iz, iy, ix, dimension_1d, dimension_1d*dimension_1d, pagesz, channelsz); //fixed a bug 060210 curcoeff = coeff(currentCube, g_1d, cubesize); //debug if(ix == 65 && iy ==43 && iz ==14) std::cout << "coeff at valley:" << curcoeff << std::endl ; delete[] currentCube; //if(curcoeff < 0.45) //{ // std::cout << "coeff too low for (" << ix << " " << iy << " " << iz << ") " << " coef: " << curcoeff << endl; // continue; //} //converge toward center of mass, //move the center using highest score (either matching or classifier). /* getMatchingCenter(image, ix, iy, iz, r, ch, ncx, ncy, ncz, flag_lm); double nncx, nncy, nncz; //getMassCenter(image, ncx, ncy, ncz, r, ch, nncx, nncy, nncz, flag_lm); getMassCenter(filtered, sx,sy,sz, ncx, ncy, ncz, r, ch, nncx, nncy, nncz, flag_lm); int newx = (int) (nncx+0.5), newy = (int) (nncy+0.5), newz = (int) (nncz+0.5); //rounding */ getMassCenter(filtered, sx,sy,sz, ix, iy, iz, r, ch, ncx, ncy, ncz, flag_lm); int newx = (int) (ncx+0.5), newy = (int) (ncy+0.5), newz = (int) (ncz+0.5); //rounding //make a final decision if, after moving, there is a close neighbor identified already on the new spot if (nearACenter(newx, newy, newz, results, r, sx, sy, sz)) { // std::cout << "#" << cellcount << ", there's 1 nearby. Skip. " ; continue; } long foundidx = newz*sx*sy + newy*sx + newx; //check if move to a lm , possible for valley area between cells. //why this made the debug image has 20 down to 9 cells!! /*if ( flag_lm[foundidx] == 0) { std::cout << "non-lm. Skip. " ; continue; }*/ //else: a cell is found, set that to 255 results[foundidx] = 255; //remove foreground around that center from image: based on radius? reestimate based on std? //int testt=0; for(int lll =0; lll < channelsz; lll++) if (flag_lm[lll] ==255) testt ++; //cout << "postive flags: " << testt << endl; //will not consider its neighbors in the future. clearSurrounding(image, ch, newx, newy, newz, r, clearFlag); //testt=0; for(int lll =0; lll < channelsz; lll++) if (flag_lm[lll] ==255) testt ++; //cout << "postive flags after: " << testt << endl; //increase cell counter by 1. LocationSimple pp(newx, newy, newz); detectedPos.push_back(pp); LocationSimple marker(newx +1, newy +1, newz +1); //convert back to 1-base marker.radius = r; markerList.push_back(marker); cellcount ++; } }//end local maxima }//end ix }//end iy }//end iz std::cout << "total number of cells:" << cellcount << std::endl; char buf[30]; itoa(cellcount, buf, 10); string resstring = "total cells:"; resstring.append(buf); QMessageBox::information(0, "debug", QString(resstring.c_str())); std::cout << "total denied local maximum:" << denied << std::endl; svm_destroy_model(pmodel); /* //results only Image4DSimple p4DImage; p4DImage.setData(results, sx, sy, sz, 1, image->datatype); v3dhandle newwin = callback.newImageWindow(); callback.setImage(newwin, &p4DImage); callback.setImageName(newwin, "prediction results image"); callback.updateImageWindow(newwin); */ //v3d does not allow me to use the same image data in a different (new) window? //I need to make a copy of the data first? unsigned char *newimage1d = new unsigned char [channelsz]; if(!newimage1d) { std::cout << "not enough memory to create result window"; return results; } unsigned char* image1d = image->getRawData(); for(long n = 0; n < channelsz; n++) newimage1d[n] = image1d[ch*channelsz + n]; //show resulting cell markers in a new window Image4DSimple newImage; newImage.setData(newimage1d, sx, sy, sz, 1, image->datatype); v3dhandle newwin = callback.newImageWindow(); callback.setImage(newwin, &newImage); callback.setImageName(newwin, "cell_counted"); callback.updateImageWindow(newwin); callback.setLandmark(newwin, markerList); //de-alloc //should I close svm file here??? if(filtered) { std::cout << "clean up memory for filtered image." << endl; delete[] filtered; } if(flag_lm) { std::cout << "clean up memory for local maximum." << endl; delete[] flag_lm; } if(clearFlag) { std::cout << "clean up memory for flags." << endl; delete[] clearFlag; } return results; }
bool findedgeimg(V3DPluginCallback2 &callback, const V3DPluginArgList & input, V3DPluginArgList & output) { cout<<"Welcome to Label edge of a mask image"<<endl; if (output.size() != 1) return false; int method_code = 0; if (input.size()>=2) { vector<char*> paras = (*(vector<char*> *)(input.at(1).p)); if(paras.size() >= 1) method_code = atoi(paras.at(0)); } char * inimg_file = ((vector<char*> *)(input.at(0).p))->at(0); char * outimg_file = ((vector<char*> *)(output.at(0).p))->at(0); cout<<"method_code = "<<method_code<<endl; cout<<"inimg_file = "<<inimg_file<<endl; cout<<"outimg_file = "<<outimg_file<<endl; Image4DSimple *image = callback.loadImage(inimg_file); if (!image || !image->valid()) { cerr<<"load image "<<inimg_file<<" error!"<<endl; return false; } V3DLONG szx=image->getXDim(), szy=image->getYDim(), szz=image->getZDim(), szc=image->getCDim(); V3DLONG N = image->getTotalUnitNumber(); //create the output buffer unsigned char *outputData = 0; try { outputData = new unsigned char [N]; for (V3DLONG tmpi=0; tmpi<N; ++tmpi) outputData[tmpi] = 0; //preset to be all 0 } catch (...) { v3d_msg("Fail to allocate memory."); if (outputData) { delete []outputData; outputData=0; } return false; } Image4DSimple outputImage; outputImage.setData((unsigned char*)outputData, szx, szy, szz, szc, V3D_UINT8); Image4DProxy<Image4DSimple> outputIProxy(&outputImage); //now do computation { bool bset255 = (method_code==0) ? false : true; Image4DProxy<Image4DSimple> p(image); Image4DProxy_foreach(p, ix, iy, iz, ic) { double v = p.value_at(ix, iy, iz, ic); V3DLONG cx, cy, cz; bool bb=false; for (cz = iz-1; cz<iz+2; ++cz) { for (cy = iy-1; cy<iy+2; ++cy) { for (cx = ix-1; cx<ix+2; ++cx) { if (!p.is_inner(cx, cy, cz, ic)) continue; if (v!=p.value_at(cx, cy, cz, ic)) { *outputIProxy.at(ix, iy, iz, ic) = (bset255) ? 255 : v; bb = true; break; } } if (bb) break; } if (bb) break; } //note that all value had been preset as 0, thus no need to set as the background color in case not an edge point } }
void processImage(V3DPluginCallback2 &callback, QWidget *parent, unsigned int rotateflag) { v3dhandle curwin = callback.currentImageWindow(); if (!curwin) { QMessageBox::information(0, "", "You don't have any image open in the main window."); return; } Image4DSimple* image = callback.getImage(curwin); if (!image) { QMessageBox::information(0, "", "The image pointer is invalid. Ensure your data is valid and try again!"); return; } unsigned char* data1d = image->getRawData(); V3DLONG szx = image->getXDim(), szy = image->getYDim(), szz = image->getZDim(), szc = image->getCDim(); // V3DLONG szchan = image->getTotalUnitNumberPerChannel(), szplane = image->getTotalUnitNumberPerPlane(); // V3DLONG N = image->getTotalBytes(); // V3DLONG i,j,k,c; if (!data1d || szx<=0 || szy<=0 || szz<=0 || szc<=0) { throw("Your data to the plugin is invalid. Check the program."); return; } ImagePixelType pixeltype = image->getDatatype(); V3DLONG in_sz[4]; in_sz[0]=szx; in_sz[1]=szy; in_sz[2]=szz; in_sz[3]=szc; unsigned char* outimg=0; rotateimage(data1d, in_sz, pixeltype, rotateflag, outimg); // image->setData(outimg, szy, szx, szz, szc, image->getDatatype()); // display Image4DSimple * new4DImage = new Image4DSimple(); switch(rotateflag) { case 1: new4DImage->setData((unsigned char*)outimg, szy, szx, szz, szc, image->getDatatype()); break; case 2: new4DImage->setData((unsigned char*)outimg, szy, szx, szz, szc, image->getDatatype()); break; case 3: new4DImage->setData((unsigned char*)outimg, szx, szy, szz, szc, image->getDatatype()); break; default: break; } v3dhandle newwin = callback.newImageWindow(); callback.setImage(newwin, new4DImage); callback.setImageName(newwin, title); callback.updateImageWindow(newwin); }
/********************************************************************************** * Returns a new, interpolated image from the two given images ***********************************************************************************/ Image4DSimple* CImageUtils::interpolateLinear( Image4DSimple* im1, // first image Image4DSimple* im2, // second image int i, // step index int N) // steps number throw (tf::RuntimeException) { // checks if(!im1 || !im1->getRawData()) throw tf::RuntimeException("in CImageUtils::interpolate_linear(): invalid 1st image data"); if(!im2 || !im2->getRawData()) throw tf::RuntimeException("in CImageUtils::interpolate_linear(): invalid 2nd image data"); if(im1->getXDim() != im2->getXDim()) throw tf::RuntimeException("in CImageUtils::interpolate_linear(): the two images differ in X dimensions"); if(im1->getYDim() != im2->getYDim()) throw tf::RuntimeException("in CImageUtils::interpolate_linear(): the two images differ in Y dimensions"); if(im1->getZDim() != im2->getZDim()) throw tf::RuntimeException("in CImageUtils::interpolate_linear(): the two images differ in Z dimensions"); if(im1->getCDim() != im2->getCDim()) throw tf::RuntimeException("in CImageUtils::interpolate_linear(): the two images differ in channel dimensions"); if(im1->getTDim() > 1) throw tf::RuntimeException(tf::strprintf("in CImageUtils::interpolate_linear(): 1st image has TDim = %d (5D not supported)", im1->getTDim())); if(im2->getTDim() > 1) throw tf::RuntimeException(tf::strprintf("in CImageUtils::interpolate_linear(): 2nd image has TDim = %d (5D not supported)", im2->getTDim())); if(im1->getDatatype() != V3D_UINT8) throw tf::RuntimeException("in CImageUtils::interpolate_linear(): 1st image is not UINT8 (not supported)"); if(im2->getDatatype() != V3D_UINT8) throw tf::RuntimeException("in CImageUtils::interpolate_linear(): 2nd image is not UINT8 (not supported)"); // allocate new image Image4DSimple* imout = new Image4DSimple(); imout->setXDim(im1->getXDim()); imout->setYDim(im1->getYDim()); imout->setZDim(im1->getZDim()); imout->setCDim(im1->getCDim()); imout->setTDim(im1->getTDim()); imout->setDatatype(V3D_UINT8); V3DLONG data_size = imout->getXDim()*imout->getYDim()*imout->getZDim()*imout->getCDim(); unsigned char* data = new unsigned char[data_size]; imout->setRawDataPointer(data); // interpolation channel-by-channel (it would be way better in the HSV space...) unsigned char* data1 = im1->getRawData(); unsigned char* data2 = im2->getRawData(); for(V3DLONG k=0; k<data_size; k++) data[k] = tf::linear<unsigned char>(data1[k], data2[k], i, N); return imout; }