virtual Vasp *do_shift(OpParam &p) { CVasp cdst(dst),cref(ref); return VaspOp::m_tilt(p,cref,arg,&cdst); }
void crossCorr( const Mat& img, const Mat& _templ, Mat& corr, Size corrsize, int ctype, Point anchor, double delta, int borderType ) { const double blockScale = 4.5; const int minBlockSize = 256; std::vector<uchar> buf; Mat templ = _templ; int depth = img.depth(), cn = img.channels(); int tdepth = templ.depth(), tcn = templ.channels(); int cdepth = CV_MAT_DEPTH(ctype), ccn = CV_MAT_CN(ctype); CV_Assert( img.dims <= 2 && templ.dims <= 2 && corr.dims <= 2 ); if( depth != tdepth && tdepth != std::max(CV_32F, depth) ) { _templ.convertTo(templ, std::max(CV_32F, depth)); tdepth = templ.depth(); } CV_Assert( depth == tdepth || tdepth == CV_32F); CV_Assert( corrsize.height <= img.rows + templ.rows - 1 && corrsize.width <= img.cols + templ.cols - 1 ); CV_Assert( ccn == 1 || delta == 0 ); corr.create(corrsize, ctype); int maxDepth = depth > CV_8S ? CV_64F : std::max(std::max(CV_32F, tdepth), cdepth); Size blocksize, dftsize; blocksize.width = cvRound(templ.cols*blockScale); blocksize.width = std::max( blocksize.width, minBlockSize - templ.cols + 1 ); blocksize.width = std::min( blocksize.width, corr.cols ); blocksize.height = cvRound(templ.rows*blockScale); blocksize.height = std::max( blocksize.height, minBlockSize - templ.rows + 1 ); blocksize.height = std::min( blocksize.height, corr.rows ); dftsize.width = std::max(getOptimalDFTSize(blocksize.width + templ.cols - 1), 2); dftsize.height = getOptimalDFTSize(blocksize.height + templ.rows - 1); if( dftsize.width <= 0 || dftsize.height <= 0 ) CV_Error( CV_StsOutOfRange, "the input arrays are too big" ); // recompute block size blocksize.width = dftsize.width - templ.cols + 1; blocksize.width = MIN( blocksize.width, corr.cols ); blocksize.height = dftsize.height - templ.rows + 1; blocksize.height = MIN( blocksize.height, corr.rows ); Mat dftTempl( dftsize.height*tcn, dftsize.width, maxDepth ); Mat dftImg( dftsize, maxDepth ); int i, k, bufSize = 0; if( tcn > 1 && tdepth != maxDepth ) bufSize = templ.cols*templ.rows*CV_ELEM_SIZE(tdepth); if( cn > 1 && depth != maxDepth ) bufSize = std::max( bufSize, (blocksize.width + templ.cols - 1)* (blocksize.height + templ.rows - 1)*CV_ELEM_SIZE(depth)); if( (ccn > 1 || cn > 1) && cdepth != maxDepth ) bufSize = std::max( bufSize, blocksize.width*blocksize.height*CV_ELEM_SIZE(cdepth)); buf.resize(bufSize); // compute DFT of each template plane for( k = 0; k < tcn; k++ ) { int yofs = k*dftsize.height; Mat src = templ; Mat dst(dftTempl, Rect(0, yofs, dftsize.width, dftsize.height)); Mat dst1(dftTempl, Rect(0, yofs, templ.cols, templ.rows)); if( tcn > 1 ) { src = tdepth == maxDepth ? dst1 : Mat(templ.size(), tdepth, &buf[0]); int pairs[] = {k, 0}; mixChannels(&templ, 1, &src, 1, pairs, 1); } if( dst1.data != src.data ) src.convertTo(dst1, dst1.depth()); if( dst.cols > templ.cols ) { Mat part(dst, Range(0, templ.rows), Range(templ.cols, dst.cols)); part = Scalar::all(0); } dft(dst, dst, 0, templ.rows); } int tileCountX = (corr.cols + blocksize.width - 1)/blocksize.width; int tileCountY = (corr.rows + blocksize.height - 1)/blocksize.height; int tileCount = tileCountX * tileCountY; Size wholeSize = img.size(); Point roiofs(0,0); Mat img0 = img; if( !(borderType & BORDER_ISOLATED) ) { img.locateROI(wholeSize, roiofs); img0.adjustROI(roiofs.y, wholeSize.height-img.rows-roiofs.y, roiofs.x, wholeSize.width-img.cols-roiofs.x); } borderType |= BORDER_ISOLATED; // calculate correlation by blocks for( i = 0; i < tileCount; i++ ) { int x = (i%tileCountX)*blocksize.width; int y = (i/tileCountX)*blocksize.height; Size bsz(std::min(blocksize.width, corr.cols - x), std::min(blocksize.height, corr.rows - y)); Size dsz(bsz.width + templ.cols - 1, bsz.height + templ.rows - 1); int x0 = x - anchor.x + roiofs.x, y0 = y - anchor.y + roiofs.y; int x1 = std::max(0, x0), y1 = std::max(0, y0); int x2 = std::min(img0.cols, x0 + dsz.width); int y2 = std::min(img0.rows, y0 + dsz.height); Mat src0(img0, Range(y1, y2), Range(x1, x2)); Mat dst(dftImg, Rect(0, 0, dsz.width, dsz.height)); Mat dst1(dftImg, Rect(x1-x0, y1-y0, x2-x1, y2-y1)); Mat cdst(corr, Rect(x, y, bsz.width, bsz.height)); for( k = 0; k < cn; k++ ) { Mat src = src0; dftImg = Scalar::all(0); if( cn > 1 ) { src = depth == maxDepth ? dst1 : Mat(y2-y1, x2-x1, depth, &buf[0]); int pairs[] = {k, 0}; mixChannels(&src0, 1, &src, 1, pairs, 1); } if( dst1.data != src.data ) src.convertTo(dst1, dst1.depth()); if( x2 - x1 < dsz.width || y2 - y1 < dsz.height ) copyMakeBorder(dst1, dst, y1-y0, dst.rows-dst1.rows-(y1-y0), x1-x0, dst.cols-dst1.cols-(x1-x0), borderType); dft( dftImg, dftImg, 0, dsz.height ); Mat dftTempl1(dftTempl, Rect(0, tcn > 1 ? k*dftsize.height : 0, dftsize.width, dftsize.height)); mulSpectrums(dftImg, dftTempl1, dftImg, 0, true); dft( dftImg, dftImg, DFT_INVERSE + DFT_SCALE, bsz.height ); src = dftImg(Rect(0, 0, bsz.width, bsz.height)); if( ccn > 1 ) { if( cdepth != maxDepth ) { Mat plane(bsz, cdepth, &buf[0]); src.convertTo(plane, cdepth, 1, delta); src = plane; } int pairs[] = {0, k}; mixChannels(&src, 1, &cdst, 1, pairs, 1); } else { if( k == 0 ) src.convertTo(cdst, cdepth, 1, delta); else { if( maxDepth != cdepth ) { Mat plane(bsz, cdepth, &buf[0]); src.convertTo(plane, cdepth); src = plane; } add(src, cdst, cdst); } } } } }
void LinkLinkComponent::render(Graphics& g) { LinkComponentStyle* style = (LinkComponentStyle*)this->style; if(!style) return; g.set_opacity(style->opacity); if(!style->glows.empty() && !style->noglows) { Vector2D a = src->center(),b = dst->center(); Vector2D normal = (b-a).normalize().normal(); Rectangle r = bezier_absolute().get_bounds(); r.augment(1000/canvas->get_zoom()); double cursize = 0; for(uint i=0; i<style->glows.size(); i++) { g.reset_clip(); Circle2D csrc(src->get_bounds().augment(cursize/canvas->get_zoom())); Circle2D cdst(dst->get_bounds().augment(cursize/canvas->get_zoom())); g.rectangle(r); g.mask_circle(csrc); g.rectangle(r); g.mask_circle(cdst); Vector2D n = normal*(cursize/canvas->get_zoom()); g.line(Line2D(src->center()-n, dst->center()-n)); g.line(Line2D(src->center()+n, dst->center()+n)); g.stroke_alpha(style->glows[i].color, (i==0? 2:1)*style->glows[i].size/canvas->get_zoom(), style->glows[i].alpha * style->opacity); cursize += (i==0? 1.5:1)*style->glows[i].size; // Blur last if(i==style->glows.size()-1 && style->bPretty) { cursize -= 0.5*style->glows[i].size; float alpha = style->glows[i].alpha/2; while(alpha > 0.01) { alpha *= 0.8; Vector2D n = normal*(cursize/canvas->get_zoom()); g.line(Line2D(src->center()-n, dst->center()-n)); g.line(Line2D(src->center()+n, dst->center()+n)); g.stroke_alpha(style->glows[i].color, 4/canvas->get_zoom(), alpha * style->opacity); cursize += 2; } } } } g.set_color(style->color); g.set_font(style->font_size, style->font, style->font_style); if(style->dashed > 0) g.dash(style->dashed); render_line(g, link->bSelected ? style->thickness_selected : style->thickness); double t1 = render_arrow(g, _scale * (link->bSelected ? style->arrow_size_selected : style->arrow_size )); Bezier b = bezier_absolute(); double t2 = -1; if(style->slashes) { if(t2==-1) t2 = b.intersect_location(src->get_bounds()); if(t2==-1) t2 = 0; g.draw_slashes(style->slashes, b.get((t1+t2)/2), b.get((t1+t2)/2 - 0.01)); } g.scale(_scale); if(!link->text.empty() || !link->text2.empty()) { if(t2==-1) t2 = b.intersect_location(src->get_bounds()); if(t2==-1) t2 = 0; Vector2D p = b.get((t1+t2)/2); if(!link->text.empty() && (style->bText || LinkComponentStyle::bText_force)) { Rectangle r(p.x, p.y+6, 0,0); r.x /= _scale; r.y /= _scale; g.text(link->text, r); } if(!link->text2.empty() && (style->bText2 || LinkComponentStyle::bText2_force)) { Rectangle r(p.x, p.y-6, 0,0); r.x /= _scale; r.y /= _scale; g.set_font(style->font_size_text2, style->font_text2, style->font_style_text2); g.text(link->text2, r); } } }