// floating reference date, fixed market data SwaptionVolatilityHullWhite::SwaptionVolatilityHullWhite(const Real reversion, const Handle<YieldTermStructure>& yts, const boost::shared_ptr<SwapIndex> indexBase, const Calendar& cal, BusinessDayConvention bdc, const std::vector<Period>& optionT, const std::vector<Period>& swapT, const Matrix& vols, const DayCounter& dc) : reversion_(reversion),yts_(yts),indexBase_(indexBase),SwaptionVolatilityDiscrete(optionT, swapT, 0, cal, bdc, dc), volHandles_(vols.rows()), hwsigmas_(vols.rows(), vols.columns()), volatilities_(vols.rows(), vols.columns()) { checkInputs(vols.rows(), vols.columns()); // fill dummy handles to allow generic handle-based // computations later on for (Size i=0; i<vols.rows(); ++i) { volHandles_[i].resize(vols.columns()); for (Size j=0; j<vols.columns(); ++j) volHandles_[i][j] = Handle<Quote>(boost::shared_ptr<Quote>(new SimpleQuote(vols[i][j]))); } interpolation_ = BilinearInterpolation(swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(), volatilities_); interpolationSigma_ = BilinearInterpolation(swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(), hwsigmas_); }
// fixed reference date, floating market data SwaptionVolatilityMatrix::SwaptionVolatilityMatrix( const Date& refDate, const Calendar& cal, BusinessDayConvention bdc, const std::vector<Period>& optionT, const std::vector<Period>& swapT, const std::vector<std::vector<Handle<Quote> > >& vols, const DayCounter& dc, const bool flatExtrapolation, const std::vector<std::vector<Real> >& shifts) : SwaptionVolatilityDiscrete(optionT, swapT, refDate, cal, bdc, dc), volHandles_(vols), shiftValues_(shifts), volatilities_(vols.size(), vols.front().size()), shifts_(vols.size(), vols.front().size(), 0.0) { checkInputs(volatilities_.rows(), volatilities_.columns(), shifts.size(), shifts.size() == 0 ? 0 : shifts.front().size()); registerWithMarketData(); if (flatExtrapolation) { interpolation_ = FlatExtrapolator2D(boost::make_shared<BilinearInterpolation>( swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(), volatilities_)); interpolationShifts_ = FlatExtrapolator2D(boost::make_shared<BilinearInterpolation>( swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(), shifts_)); } else { interpolation_ = BilinearInterpolation( swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(), volatilities_); interpolationShifts_ = BilinearInterpolation( swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(), shifts_); } }
void Canny(Mat src, Mat& dst, int thres) { Mat mdx, mdy; printf("Canny thresheold %d\n", thres); Sobel(src, mdx, CV_64F, 1, 0); Sobel(src, mdy, CV_64F, 0, 1); dst.create(src.rows, src.cols, CV_64F); int x, y; double dx, dy; double mag, orien; // // Compute edge response // for(x = 0; x < src.cols; x++) for(y = 0; y < src.rows; y++) { dx = mdx.at<double>(y, x); dy = mdy.at<double>(y, x); dst.at<double>(y, x) = hypot(dx, dy); // Gradient magnitude } // // Max supression // for(x = 0; x < src.cols; x++) for(y = 0; y < src.rows; y++) { dx = mdx.at<double>(y, x); dy = mdy.at<double>(y, x); mag = dst.at<double>(y,x); orien = atan2(dx, dy); // Gradient direction in radians if(mag > thres) { double delta_x = cos(orien); double delta_y = sin(orien); double pixel; pixel = BilinearInterpolation(dst, x + delta_x, y + delta_y); // e0 is one pixel away in the gradient direction if(mag > pixel) { pixel = BilinearInterpolation(dst, x - delta_x, y - delta_y); // e1 is one pixel away in the opposite direction to the gradient if(mag > pixel) continue; } } dst.at<double>(y, x) = 0; // Supress } }
void SegmentListVIIRSM::SmoothVIIRSImage() { qDebug() << "start SegmentListVIIRSM::SmoothVIIRSImage()"; int lineimage = 0; QList<Segment *>::iterator segsel; segsel = segsselected.begin(); SegmentVIIRSM *segmsave; while ( segsel != segsselected.end() ) { SegmentVIIRSM *segm = (SegmentVIIRSM *)(*segsel); if(segsel != segsselected.begin()) BilinearBetweenSegments(segmsave, segm); segmsave = segm; BilinearInterpolation(segm); //printData(segm); ++segsel; lineimage += segm->NbrOfLines; } }
// fixed reference date, fixed market data SwaptionVolatilityMatrix::SwaptionVolatilityMatrix( const Date& refDate, const Calendar& cal, BusinessDayConvention bdc, const std::vector<Period>& optionT, const std::vector<Period>& swapT, const Matrix& vols, const DayCounter& dc) : SwaptionVolatilityDiscrete(optionT, swapT, refDate, cal, bdc, dc), volHandles_(vols.rows()), volatilities_(vols.rows(), vols.columns()) { checkInputs(vols.rows(), vols.columns()); // fill dummy handles to allow generic handle-based // computations later on for (Size i=0; i<vols.rows(); ++i) { volHandles_[i].resize(vols.columns()); for (Size j=0; j<vols.columns(); ++j) volHandles_[i][j] = Handle<Quote>(boost::shared_ptr<Quote>(new SimpleQuote(vols[i][j]))); } interpolation_ = BilinearInterpolation(swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(), volatilities_); }
// fixed reference date, fixed market data SwaptionVolatilityMatrix::SwaptionVolatilityMatrix( const Date& refDate, const Calendar& cal, BusinessDayConvention bdc, const std::vector<Period>& optionT, const std::vector<Period>& swapT, const Matrix& vols, const DayCounter& dc, const bool flatExtrapolation, const VolatilityType type, const Matrix& shifts) : SwaptionVolatilityDiscrete(optionT, swapT, refDate, cal, bdc, dc), volHandles_(vols.rows()), shiftValues_(vols.rows()), volatilities_(vols.rows(), vols.columns()), shifts_(shifts.rows(), shifts.columns(), 0.0), volatilityType_(type) { checkInputs(vols.rows(), vols.columns(), shifts.rows(), shifts.columns()); // fill dummy handles to allow generic handle-based // computations later on for (Size i=0; i<vols.rows(); ++i) { volHandles_[i].resize(vols.columns()); shiftValues_[i].resize(vols.columns()); for (Size j=0; j<vols.columns(); ++j) { volHandles_[i][j] = Handle<Quote>(boost::shared_ptr<Quote>(new SimpleQuote(vols[i][j]))); shiftValues_[i][j] = shifts.rows() > 0 ? shifts[i][j] : 0.0; } } if (flatExtrapolation) { interpolation_ = FlatExtrapolator2D(boost::make_shared<BilinearInterpolation>( swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(), volatilities_)); interpolationShifts_ = FlatExtrapolator2D(boost::make_shared<BilinearInterpolation>( swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(), shifts_)); } else { interpolation_ = BilinearInterpolation( swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(), volatilities_); interpolationShifts_ = BilinearInterpolation( swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(), shifts_); } }
// floating reference date, floating market data SwaptionVolatilityHullWhite::SwaptionVolatilityHullWhite(const Real reversion, const Handle<YieldTermStructure>& yts, const boost::shared_ptr<SwapIndex> indexBase, const Calendar& cal, BusinessDayConvention bdc, const std::vector<Period>& optionT, const std::vector<Period>& swapT, const std::vector<std::vector<Handle<Quote> > >& vols, const DayCounter& dc) : reversion_(reversion),yts_(yts),indexBase_(indexBase),SwaptionVolatilityDiscrete(optionT, swapT, 0, cal, bdc, dc), volHandles_(vols), hwsigmas_(vols.size(), vols.front().size()), volatilities_(vols.size(), vols.front().size()) { checkInputs(volatilities_.rows(), volatilities_.columns()); registerWithMarketData(); interpolation_ = BilinearInterpolation(swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(), volatilities_); interpolationSigma_ = BilinearInterpolation(swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(), hwsigmas_); }
// floating reference date, floating market data SwaptionVolatilityMatrix::SwaptionVolatilityMatrix( const Calendar& cal, BusinessDayConvention bdc, const std::vector<Period>& optionT, const std::vector<Period>& swapT, const std::vector<std::vector<Handle<Quote> > >& vols, const DayCounter& dc) : SwaptionVolatilityDiscrete(optionT, swapT, 0, cal, bdc, dc), volHandles_(vols), volatilities_(vols.size(), vols.front().size()) { checkInputs(volatilities_.rows(), volatilities_.columns()); registerWithMarketData(); interpolation_ = BilinearInterpolation(swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(), volatilities_); }
void SwaptionVolCube2::performCalculations() const{ SwaptionVolatilityCube::performCalculations(); //! set volSpreadsMatrix_ by volSpreads_ quotes for (Size i=0; i<nStrikes_; i++) for (Size j=0; j<nOptionTenors_; j++) for (Size k=0; k<nSwapTenors_; k++) { volSpreadsMatrix_[i][j][k] = volSpreads_[j*nSwapTenors_+k][i]->value(); } //! create volSpreadsInterpolator_ for (Size i=0; i<nStrikes_; i++) { volSpreadsInterpolator_[i] = BilinearInterpolation( swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), optionTimes_.end(), volSpreadsMatrix_[i]); volSpreadsInterpolator_[i].enableExtrapolation(); } }
void MainWindow::RotateImage(QImage *image, double orien) { int r, c; QRgb pixel; QImage buffer; int w = image->width(); int h = image->height(); double radians = -2.0*3.141*orien/360.0; buffer = image->copy(); pixel = qRgb(0, 0, 0); image->fill(pixel); for(r=0;r<h;r++) { for(c=0;c<w;c++) { double rgb[3]; double x0, y0; double x1, y1; // Rotate around the center of the image. x0 = (double) (c - w/2); y0 = (double) (r - h/2); // Rotate using rotation matrix x1 = x0*cos(radians) - y0*sin(radians); y1 = x0*sin(radians) + y0*cos(radians); x1 += (double) (w/2); y1 += (double) (h/2); BilinearInterpolation(&buffer, x1, y1, rgb); image->setPixel(c, r, qRgb((int) floor(rgb[0] + 0.5), (int) floor(rgb[1] + 0.5), (int) floor(rgb[2] + 0.5))); } } }
void SegmentListOLCI::SmoothOLCIImage(bool combine) { qDebug() << "start SegmentListOLCI::SmoothOLCIImage()"; int lineimage = 0; QList<Segment *>::iterator segsel; segsel = segsselected.begin(); SegmentOLCI *segmsave; while ( segsel != segsselected.end() ) { SegmentOLCI *segm = (SegmentOLCI *)(*segsel); if(segsel != segsselected.begin()) BilinearBetweenSegments(segmsave, segm, combine); segmsave = segm; BilinearInterpolation(segm, combine); ++segsel; lineimage += segm->NbrOfLines; } }
void MainWindow::FindPeaksImage(QImage *image, double thres) { // First compute edge magnitude and orientation for the image with sobel operator int r, c, rd, cd; QRgb pixel; // Graytones first BlackWhiteImage(image); QImage buffer; // store pixel magnitude QImage magnitude = image->copy(); // store pixel orientation QImage orientation = image->copy(); int w = image->width(); int h = image->height(); double gx[9] = {1, 0, -1, 2, 0, -2, 1, 0, -1}; double gy[9] = {-1, -2, -1, 0, 0, 0, 1, 2, 1}; buffer = image->copy(-1, -1, w + 2, h + 2); for(r = 0; r < h; r++) { for(c = 0; c < w; c++) { double magX = 0.0; double magY = 0.0; for(rd = -1; rd <= 1; rd++) { for(cd = -1; cd <= 1; cd++) { pixel = buffer.pixel(c + cd + 1, r + rd + 1); // Get the value of the kernel double weightX = gx[(rd + 1) * 3 + cd + 1]; double weightY = gy[(rd + 1) * 3 + cd + 1]; magX += weightX * (double) qRed(pixel); magY += weightY * (double) qRed(pixel); } } magX /= 8.0; magY /= 8.0; double mag = sqrt(magX * magX + magY * magY); // magnitude magnitude.setPixel(c, r, qRgb(0, (int)mag, 0)); double orien = atan2(magY, magX); // orientation double red = sin(orien); double green = cos(orien); orientation.setPixel(c, r, qRgb((int)red, (int)green, 0)); } } pixel = qRgb(0, 0, 0); // zero out the image image->fill(pixel); // Compare edge magnitude for(r = 0; r < h; r++) { for(c = 0; c < w; c++) { pixel = magnitude.pixel(c, r); double mag0 = (double)qGreen(pixel); if(mag0 > thres) { pixel = orientation.pixel(c, r); double dsin = (double)qRed(pixel); double dcos = (double)qGreen(pixel); // pixel perpendicular double x1, y1; double e0[3]; x1 = dcos + c; y1 = dsin + r; BilinearInterpolation(&magnitude, x1, y1, e0); // pixel perpendicular double x2, y2; double e1[3]; x2 = -dcos + c; y2 = -dsin + r; BilinearInterpolation(&magnitude, x2, y2, e1); if(mag0 >= e0[1] && mag0 >= e1[1]) { image->setPixel(c, r, qRgb(255, 255, 255)); } } } } }
RGBColor ImageTexture::getColor(const Point& coord) { if (i==NEAREST) { switch(bh) { float x1,y1; case REPEAT: x1 = coord.x; y1 = coord.y; if(coord.x>1) x1 = coord.x - (int)coord.x; if(coord.y>1) y1 = coord.y - (int)coord.y; if(coord.x<0) x1 = coord.x - floor(coord.x); if(coord.y<0) y1 = coord.y - floor(coord.y); x1 = x1*(image.width()-1); y1 = y1*(image.height()-1); return RGBColor(image(floor(x1+0.5),floor(y1+0.5))); case MIRROR: x1 = coord.x; y1 = coord.y; if((int)(floor(coord.x))%2==0) x1 = coord.x - floor(coord.x); else x1 = 1 - (coord.x - floor(coord.x)); if((int)(floor(coord.y))%2==0) y1 = coord.y - floor(coord.y); else y1 = 1 - (coord.y - floor(coord.y)); x1 = x1*(image.width()-1); y1 = y1*(image.height()-1); return RGBColor(image(floor(x1+0.5),floor(y1+0.5))); case CLAMP: x1 = coord.x; y1 = coord.y; if(coord.x>1) x1 = 1; if(coord.y>1) y1 = 1; if(coord.x<0) x1 = 0; if(coord.y<0) y1 = 0; x1 = x1*(image.width()-1); y1 = y1*(image.height()-1); return RGBColor(image(floor(x1+0.5),floor(y1+0.5))); } } if (i==BILINEAR) { Point q1,q2,q3,q4; float x1,y1,r_,g_,b_; switch(bh) { case REPEAT: x1 = coord.x; y1 = coord.y; if(coord.x>1) x1 = coord.x - (int)coord.x; if(coord.y>1) y1 = coord.y - (int)coord.y; if(coord.x<0) x1 = coord.x - floor(coord.x); if(coord.y<0) y1 = coord.y - floor(coord.y); x1 = x1*(image.width()-1); y1 = y1*(image.height()-1); return BilinearInterpolation(x1,y1,image, bh); case MIRROR: x1 = coord.x; y1 = coord.y; if((int)(floor(coord.x))%2==0) x1 = coord.x - floor(coord.x); else x1 = 1 - (coord.x - floor(coord.x)); if((int)(floor(coord.y))%2==0) y1 = coord.y - floor(coord.y); else y1 = 1 - (coord.y - floor(coord.y)); x1 = x1*(image.width()-1); y1 = y1*(image.height()-1); return BilinearInterpolation(x1,y1,image, bh); case CLAMP: x1 = coord.x; y1 = coord.y; if(coord.x>1) x1 = 1; if(coord.y>1) y1 = 1; if(coord.x<0) x1 = 0; if(coord.y<0) y1 = 0; x1 = x1*(image.width()-1); y1 = y1*(image.height()-1); return BilinearInterpolation(x1,y1,image, bh); } } }
RGBColor ImageTexture::getColorDY(const Point& coord) { if (i==NEAREST) { switch(bh) { float y1a, y1b ,x1; case REPEAT: y1a = coord.y - floor(coord.y); y1a = y1a*(image.height()-1); y1b = floor(y1a+0.5); if(y1a < y1b){ y1a = y1b - 1; y1a = y1a < 0? image.height() - 1:y1a; } else { y1a = y1b; y1b = y1a + 1; y1b = y1b > image.height() - 1? y1b - image.height():y1b; } x1 = coord.x - floor(coord.x); x1 = x1*(image.width()-1); return RGBColor(image(floor(x1+0.5),y1b)) - RGBColor(image(floor(x1+0.5), y1a)); case MIRROR: if((int)(floor(coord.y))%2==0){ y1a = coord.y - floor(coord.y); y1a = y1a*(image.height()-1); y1b = floor(y1a+0.5); if(y1a < y1b){ y1a = y1b - 1; y1a = y1a < 0? image.height() - 1:y1a; } else { y1a = y1b; y1b = y1a + 1; y1b = y1b > image.height() - 1? y1b - image.height():y1b; } }else{ y1a = 1 - (coord.y - floor(coord.y)); y1a = y1a*(image.height()-1); y1b = floor(y1a+0.5); if(y1a <= y1b){ y1a = y1b; y1b = y1a - 1; y1b = y1b < 0? -y1b : y1b; } else { y1a = y1b + 1; y1a = y1a > image.height() - 1? image.height() - 1 : y1a; } } if((int)(floor(coord.x))%2==0) x1 = coord.x - floor(coord.x); else x1 = 1 - (coord.x - floor(coord.x)); x1 = x1*(image.width()-1); return RGBColor(image(floor(x1+0.5),y1b)) - RGBColor(image(floor(x1+0.5), y1a)); case CLAMP: if(coord.x>1) y1a = 1; if(coord.y>1) x1 = 1; if(coord.x<0) y1a = 0; if(coord.y<0) x1 = 0; y1a = y1a*(image.height()-1); y1b = floor(y1a+0.5); if(y1a < y1b){ y1a = y1b - 1; y1a = y1a < 0? 0:y1a; } else { y1a = y1b; y1b = y1a + 1; y1b = y1b > image.height() - 1? image.height() - 1:y1b; } x1 = x1*(image.height()-1); return RGBColor(image(floor(x1+0.5),y1b)) - RGBColor(image(floor(x1+0.5),y1a)); } } if (i==BILINEAR) { Point q1,q2,q3,q4; float x1,y1,r_,g_,b_,y1_f,y1_c; switch(bh) { case REPEAT: x1 = coord.x; y1 = coord.y; if(coord.x>1) x1 = coord.x - (int)coord.x; if(coord.y>1) y1 = coord.y - (int)coord.y; if(coord.x<0) x1 = coord.x - floor(coord.x); if(coord.y<0) y1 = coord.y - floor(coord.y); x1 = x1*(image.width()-1); y1 = y1*(image.height()-1); y1_f = floor(y1); y1_c = ceil(y1); return BilinearInterpolation(x1,y1_c,image, bh) - BilinearInterpolation(x1,y1_f,image, bh); case MIRROR: x1 = coord.x; y1 = coord.y; if((int)(floor(coord.x))%2==0) x1 = coord.x - floor(coord.x); else x1 = 1 - (coord.x - floor(coord.x)); if((int)(floor(coord.y))%2==0) y1 = coord.y - floor(coord.y); else y1 = 1 - (coord.y - floor(coord.y)); x1 = x1*(image.width()-1); y1 = y1*(image.height()-1); y1_f = floor(y1); y1_c = ceil(y1); return BilinearInterpolation(x1,y1_c,image, bh) - BilinearInterpolation(x1,y1_f,image, bh); case CLAMP: x1 = coord.x; y1 = coord.y; if(coord.x>1) x1 = 1; if(coord.y>1) y1 = 1; if(coord.x<0) x1 = 0; if(coord.y<0) y1 = 0; x1 = x1*(image.width()-1); y1 = y1*(image.height()-1); y1_f = floor(y1); y1_c = ceil(y1); return BilinearInterpolation(x1,y1_c,image, bh) - BilinearInterpolation(x1,y1_f,image, bh); } } }
/******************************************************************************* Stitch together two images using the homography transformation image1: first input image image2: second input image hom: homography transformation (image1 -> image2) homInv: inverse homography transformation (image2 -> image1) stitchedImage: returned stitched image *******************************************************************************/ void MainWindow::Stitch(QImage image1, QImage image2, double hom[3][3], double homInv[3][3], QImage &stitchedImage) { // Width and height of stitchedImage int sWidth, sHeight; // To compute the width and height of stitchedImage, let's first get the corners of image2 // Corners are like so (image2): // // A B // // // // C D // // (x, y) is for the original coordinates in image2's corners, while // (x_proj, y_proj) is the projected coordinates of image2's corners projected into image1 double image2CornerA_x = 0.0; double image2CornerA_y = 0.0; double image2CornerB_x = image2.width(); double image2CornerB_y = 0.0; double image2CornerC_x = 0.0; double image2CornerC_y = image2.height(); double image2CornerD_x = image2.width(); double image2CornerD_y = image2.height(); double image2CornerA_x_proj, image2CornerA_y_proj, image2CornerB_x_proj, image2CornerB_y_proj, image2CornerC_x_proj, image2CornerC_y_proj, image2CornerD_x_proj, image2CornerD_y_proj; // Project points into image1 Project(image2CornerA_x, image2CornerA_y, image2CornerA_x_proj, image2CornerA_y_proj, homInv); Project(image2CornerB_x, image2CornerB_y, image2CornerB_x_proj, image2CornerB_y_proj, homInv); Project(image2CornerC_x, image2CornerC_y, image2CornerC_x_proj, image2CornerC_y_proj, homInv); Project(image2CornerD_x, image2CornerD_y, image2CornerD_x_proj, image2CornerD_y_proj, homInv); // See how large we'll need to make the combined image sWidth = (int) ceil(max((double) image1.width(), max(image2CornerB_x_proj, image2CornerD_x_proj)) - min(0.0, min(image2CornerA_x_proj, image2CornerC_x_proj))); sHeight = (int) ceil(max((double) image1.height(), max(image2CornerC_y_proj, image2CornerD_y_proj)) - min(0.0, min(image2CornerA_y_proj, image2CornerB_y_proj))); stitchedImage = QImage(sWidth, sHeight, QImage::Format_RGB32); stitchedImage.fill(qRgb(0,0,0)); // Copy image 1 into stitched image at offset determined by difference of dimensions // between it and the stitched image if image1 is to the right/below image2; // if image1 is to the left/above image2, then place it at 0 for the x-/y-axis int x_offset, y_offset; // If image2's farthest left corner is to the left of image1, give image1 an x offset if(min(image2CornerA_x_proj, image2CornerC_x_proj) < 0.0) { x_offset = stitchedImage.width() - image1.width(); } else { x_offset = 0; } // If image2's farthest top corner is above image1, give image1 a y offset if(min(image2CornerA_y_proj, image2CornerB_y_proj) < 0.0) { y_offset = stitchedImage.height() - image1.height(); } else { y_offset = 0; } for(int row = y_offset; row < image1.height() + y_offset; row++) { for(int col = x_offset; col < image1.width() + x_offset; col++) { stitchedImage.setPixel(col, row, image1.pixel(col - x_offset, row - y_offset)); } } double stitchedImage_x_proj, stitchedImage_y_proj; // Place image 2 into stitched image for(int row = 0; row < stitchedImage.height(); row++) { for(int col = 0; col < stitchedImage.width(); col++) { // Project this point onto image2 Project(col - x_offset, row - y_offset, stitchedImage_x_proj, stitchedImage_y_proj, hom); // If the projected point is within image2's boundaries, // add the pixel value to the stitched image if( (0.0 < stitchedImage_x_proj) && (stitchedImage_x_proj < image2.width()) && (0.0 < stitchedImage_y_proj) && (stitchedImage_y_proj < image2.height())) { double color[3]; BilinearInterpolation(&image2, stitchedImage_x_proj, stitchedImage_y_proj, color); // Modify colors to blend edges, if image1 is already drawn here if(stitchedImage.pixel(col, row) != qRgb(0, 0, 0)) { // Weight each image equally color[0] = 0.5 * color[0] + 0.5 * qRed(stitchedImage.pixel(col, row)); color[1] = 0.5 * color[1] + 0.5 * qGreen(stitchedImage.pixel(col, row)); color[2] = 0.5 * color[2] + 0.5 * qBlue(stitchedImage.pixel(col, row)); } else { // Just use the image2 colors as-is } stitchedImage.setPixel(col, row, qRgb((int) color[0], (int) color[1], (int) color[2])); } } } }
/******************************************************************************* Stitch together two images using the homography transformation image1 - first input image image2 - second input image hom - homography transformation (image1 -> image2) homInv - inverse homography transformation (image2 -> image1) stitchedImage - returned stitched image *******************************************************************************/ void MainWindow::Stitch(QImage image1, QImage image2, double hom[3][3], double homInv[3][3], QImage &stitchedImage) { int r, c, i; QRgb pixel; int ws, hs; int w1 = image1.width(); int h1 = image1.height(); int w2 = image2.width(); int h2 = image2.height(); int cmin = 0; int cmax = w1; int rmin = 0; int rmax = h1; double corners[8]; corners[0] = corners[1] = corners[3] = corners[4] = 0.0; corners[2] = corners[6] = (double) w2; corners[5] = corners[7] = (double) h2; // Compute ws and has by projecting four corners of image2 to image1 for(i = 0; i < 4; i++) { double x, y; Project(corners[i * 2], corners[i * 2 + 1], x, y, homInv); int r = floor(y + 0.5); int c = floor(x + 0.5); cmin = cmin > c ? c : cmin; cmax = cmax < c ? c : cmax; rmin = rmin > r ? r : rmin; rmax = rmax < r ? r : rmax; } ws = cmax - cmin; hs = rmax - rmin; // Initialize the stitchedImage stitchedImage = QImage(ws, hs, QImage::Format_RGB32); stitchedImage.fill(qRgb(0,0,0)); // Warp image1 and image2 to stitchedImage. // Copy image1 to stitchedImage for(r = 0; r < h1; r++) { for(c = 0; c < w1; c++) { pixel = image1.pixel(c, r); stitchedImage.setPixel(c - cmin, r - rmin, pixel); } } // Project each pixel of stitchedImage onto image2 // bilinearInterpolate the value for(r = 0; r < hs; r++) { for(c = 0; c < ws; c++) { double x, y; double rgb[3]; pixel = stitchedImage.pixel(c, r); Project((double)(c + cmin), (double)(r + rmin), x, y, hom); if(BilinearInterpolation(&image2, x, y, rgb)) { stitchedImage.setPixel(c, r, qRgb((int) rgb[0], (int) rgb[1], (int) rgb[2])); } } } }