void Match::calcHull() { float points[4][2] = { {0, 0}, {block_->s_, 0}, {block_->s_, block_->s_}, {0, block_->s_} }; hull_.verts.clear(); cv::Mat selection(t_.transformMat_, cv::Rect(0,0,3,2)); cv::Mat inverted; invertAffineTransform(selection, inverted); for(int i=0; i<4; i++ ) { cv::Mat p = (cv::Mat_<float>(3,1) << points[i][0], points[i][1], 1); cv::Mat a = inverted * p; Vector2f point; point.m_v[0] = a.at<float>(0,0); point.m_v[1] = a.at<float>(0,1); hull_.verts.push_back(point); } // flipped? correct orientation Vector2f v1 = hull_.verts[0]; Vector2f v2 = hull_.verts[1]; Vector2f v3 = hull_.verts[2]; float cross = ( (v2.m_v[0] - v1.m_v[0]) * (v3.m_v[1]-v2.m_v[1])) - ( (v2.m_v[1] - v1.m_v[1]) * (v3.m_v[0]-v2.m_v[0]) ); if (cross<0.0) std::reverse(hull_.verts.begin(), hull_.verts.end()); }
void ASiftDetector::affineSkew(double tilt, double phi, Mat& img, Mat& mask, Mat& Ai) { int h = img.rows; int w = img.cols; mask = Mat(h, w, CV_8UC1, Scalar(255)); Mat A = Mat::eye(2,3, CV_32F); if(phi != 0.0) { phi *= M_PI/180.; double s = sin(phi); double c = cos(phi); A = (Mat_<float>(2,2) << c, -s, s, c); Mat corners = (Mat_<float>(4,2) << 0, 0, w, 0, w, h, 0, h); Mat tcorners = corners*A.t(); Mat tcorners_x, tcorners_y; tcorners.col(0).copyTo(tcorners_x); tcorners.col(1).copyTo(tcorners_y); std::vector<Mat> channels; channels.push_back(tcorners_x); channels.push_back(tcorners_y); merge(channels, tcorners); Rect rect = boundingRect(tcorners); A = (Mat_<float>(2,3) << c, -s, -rect.x, s, c, -rect.y); warpAffine(img, img, A, Size(rect.width, rect.height), INTER_LINEAR, BORDER_REPLICATE); } if(tilt != 1.0) { double s = 0.8*sqrt(tilt*tilt-1); GaussianBlur(img, img, Size(0,0), s, 0.01); resize(img, img, Size(0,0), 1.0/tilt, 1.0, INTER_NEAREST); A.row(0) = A.row(0)/tilt; } if(tilt != 1.0 || phi != 0.0) { h = img.rows; w = img.cols; warpAffine(mask, mask, A, Size(w, h), INTER_NEAREST); } invertAffineTransform(A, Ai); }
//This method should be always called BEFORE any other method call. It is not called during constructor for efficiency. //It processes the original image to generate "processedImg" which is the actual image the class will work with. //It applies: rescaling, rotation, equalization, filtering and color transformations. //Should be called before extracCharacteristicPoints(). If not, it will be automatically called. inline bool Face::init () { Mat& img = this->originalImg; Mat gray, dstnImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 ); //Color conversion to grayscale. cvtColor( img, gray, CV_BGR2GRAY ); //Resizing with the given scale. resize( gray, dstnImg, dstnImg.size(), 0, 0, INTER_LINEAR ); //Equalizing the histogram. equalizeHist( dstnImg, dstnImg ); //Gaussian Filter to get rid of noise or excesive definition. Bluring. if (this->bluringEnabled) GaussianBlur( dstnImg, dstnImg, Size(3, 3), 2, 2); //Rotation of the image. this->rMat = getRotationMatrix2D(this->rotationCenter, this->rotationAngle, 1); Mat smallImg2; dstnImg.copyTo(smallImg2); warpAffine(smallImg2, dstnImg, this->rMat, dstnImg.size()); //Generation of inverse rotation matrix for future uses. See transformPoint(). invertAffineTransform(this->rMat,this->irMat); //Storing the final preprocessed image ready to be analized for face search and inspection. this->processedImg = dstnImg; //We indicate the object has been initialized so the rest of its API is available. this->faceFound = false; //We have to set this to false since the "processedImg" has changed. return (this->initialized = true); }
bool CalculationThread::singleStep(int x, int y) { if(!seedmap) init(); Patch* block = 0; if(x==-1) block = seedmap->matchNext(); else { int xlocal = ((float)x/400.0) * (seedmap->sourceImage_.size().width / blockSize_); int ylocal = ((float)y/400.0) * (seedmap->sourceImage_.size().height / blockSize_); block = seedmap->getPatch(xlocal,ylocal); seedmap->match(block); } if (!block) return false; if (!block->matches_) return true; cv::Mat tmpImage = base_.clone(); float colorScale = 255.0 / seedmap->crit_.maxError_; if(!block->finalMatch_) { for(uint i=0; i<block->matches_->size(); i++) { Match* match = block->matches_->at(i); Polygon hull = match->hull_; // highlight match for(int j=0; j<4; j++) cv::line(tmpImage, hull.verts[j], hull.verts[(j+1) % 4], cv::Scalar(0,255-match->error_*colorScale,match->error_*colorScale,100)); foreach(cv::Point2f p, block->pointsSrc_) cv::line(tmpImage, p+cv::Point2f(block->x_,block->y_), p+cv::Point2f(block->x_,block->y_), cv::Scalar(0,155,00,100)); } } if(block->finalMatch_) { // highlight match cv::Mat selection(block->finalMatch_->t_.transformMat_, cv::Rect(0,0,3,2)); cv::Mat inverted; invertAffineTransform(selection, inverted); for (int i=0; i<2; i++) for(int j=0; j<3; j++) std::cout << inverted.at<float>(i,j) << " "; for(int j=0; j<4; j++) std::cout << block->finalMatch_->hull_.verts[j].m_v[0] << " " << block->finalMatch_->hull_.verts[j].m_v[1] << std::endl; for(int j=0; j<4; j++) cv::line(tmpImage, block->finalMatch_->hull_.verts[j], block->finalMatch_->hull_.verts[(j+1) % 4], cv::Scalar(100,255,0,100)); } debugWidgetR->fromIpl( tmpImage, "preview" ); debugWidgetR->updateGL(); cv::Mat reconstruction(seedmap->debugReconstruction()); debugWidgetL->fromIpl( reconstruction, "reconstruction" ); debugWidgetL->updateGL(); return true; }