Beispiel #1
0
void minmax( const cv::Mat& src, cv::Mat& min, cv::Mat& max, int velikost )
{
  // velikost - musí být liché číslo, minimálně 3
  int stred = velikost/2;
  stred = MAX(1,stred);
  velikost = 2*stred+1;

  // zvětšíme obraz a okopírujeme krajní hodnoty do okrajů
  cv::Mat srcBorder;
  copyMakeBorder( src, srcBorder, stred, stred, stred, stred, cv::BORDER_REPLICATE );

  // připravíme výstupní obraz
  min = cv::Mat( src.size(), src.type() );
  max = cv::Mat( src.size(), src.type() );

  // připravíme vektor k řazení prvků
  std::vector<uchar> buff(velikost*velikost);
  for( int j = 0; j < src.rows; ++j ) {
    for( int i = 0; i < src.cols; ++i ) 
    {
      // připravíme vektor tak, aby jsme k němu mohli přistupovat jako k matici hodnot
      cv::Mat m(buff);

      // do matice nakopírujte hodnoty z okolí pro následné seřazení
      for(int y=0;y<velikost;++y) 
      for(int x=0;x<velikost;++x){
          buff[y*velikost+x] = srcBorder.at<uchar>(y+j,x+i);
      }
      
      // seřadíme hodnoty ve vektoru
      std::sort(buff.begin(), buff.end());

      // výslednou hodnotu uložte do výstupního obrazu
      min.at<uchar>(j,i) = buff[0];
      max.at<uchar>(j,i) = buff[velikost*velikost-1];
    }
  }

  return;
}
void MainWindow::on_actionLocal_threshold_triggered()
{

    if(!activeMdiChild()) return;
    CvGlWidget *actCV = activeMdiChild();
    cv::Mat paddedImage;
    int kSize = threshUI->kernelSize;
    int UIT = threshUI->localThresh;
    int top = kSize, bottom = kSize, left = kSize, right = kSize;
    int borderType = threshUI->borderType; //BORDER_REPLICATE BORDER_REFLECT101
    copyMakeBorder(actCV->cvImage, paddedImage, top, bottom, left, right, borderType, Scalar(0));
    int r = actCV->cvImage.rows;  int c = actCV->cvImage.cols;

    //    paddedImage.convertTo(paddedImage, CV_64FC1);
    //    actCV->cvImage.convertTo(actCV->cvImage, CV_64FC1);
    cv::Mat t_im = Mat::zeros(r, c, CV_8UC1);

    cv::Mat sum;
    integral(actCV->cvImage, sum, CV_64FC1);

    for(int i = 0; i < r; i++){
        for(int j = 0; j < c; j++){
            float sum = 0;
            //   int it = 0;
            //run the kernel now
            for(int u = -(kSize - 1)/2; u <= (kSize - 1)/2; u++)
                for(int v = -(kSize - 1)/2; v <=(kSize -1)/2; v++){
                    sum += (float)paddedImage.at<uchar>(i +kSize+ u,j +kSize+ v);
                }
            //threshold here; 7 is ok
            float t = (float)sum/(kSize*kSize) - 7;
            if((float)actCV->cvImage.at<uchar>(i, j) > t) t_im.at<uchar>(i, j) = 255;
            else t_im.at<uchar>(i, j) = 0;
        }
    }

    actCV->showImage(t_im);
    actCV->buildHistogram();
    makeHistogram();
}
Beispiel #3
0
/*
src:     input image
kernel:  filter kernel
return:  convolution result
*/
Mat Dip2::spatialConvolution(Mat& src, Mat& kernel){

   // TO DO !!
	Mat outputImage = src.clone();
	int border = kernel.cols / 2; //assume it is symmetry		
	Mat src_buf(src.rows + border*2, src.cols + border*2, src.depth()); //prepare for matrix with border
	copyMakeBorder(src, src_buf, border, border,border, border, BORDER_REPLICATE); //extend border by replicating rows and cols
	//flip kernel along x and y axis
	flip(kernel, kernel, -1);
	for (int y = border; y < src_buf.rows-border; y++){
		for (int x = border; x < src_buf.cols-border; x++){
			float convolution = 0.;
			for (int j = 0; j < kernel.rows; j++){
				for (int i = 0; i < kernel.cols; i++){
					convolution += src_buf.at<float>(y - (kernel.rows/2) + j, x - (kernel.cols/2) + i)*kernel.at<float>(j, i);
				}
			}
			outputImage.at<float>(y-border, x-border) = convolution;
		}
	}
	return outputImage;

}
Beispiel #4
0
void nnor::hierarchicCharactersPadding(vector<vector<vector<Mat>>> chars)
{
	int nnRows = 0;
	int nnCols = 0;
	for (int i = 0; i < chars.size(); i++)
	{
		for (int j = 0; j < chars[i].size(); j++)
		{
			for (int k = 0; k < chars[i][j].size(); k++)
			{
				chars[i][j][k] = autoCrop(chars[i][j][k]);
				if (chars[i][j][k].rows > nnRows)
					nnRows = chars[i][j][k].rows;
				if (chars[i][j][k].cols > nnCols)
					nnCols = chars[i][j][k].cols;
			}
		}
	}

	for (int i = 0; i < chars.size(); i++)
	{
		for (int j = 0; j < chars[i].size(); j++)
		{
			for (int k = 0; k < chars[i][j].size(); k++)
			{
				Mat character;
				chars[i][j][k].copyTo(character);
				int left = (nnCols - character.cols) / 2;
				int right = nnCols - left - character.cols;
				int top = (nnRows - character.rows) / 2;
				int bottom = nnRows - top - character.rows;
				copyMakeBorder(character, character, top, bottom, left, right, BORDER_CONSTANT, 255);
				chars[i][j][k] = character;
			}
		}
	}
}
Beispiel #5
0
int ImageProcessor::test(const string &filename)
{
    // Read the file
    Mat image = imread(filename, CV_LOAD_IMAGE_UNCHANGED);

    // Check for invalid input
    if(! image.data )
    {
        qDebug() <<  "Could not open or find the image";
        return -1;
    }

    Mat img_bin = cvtColorToBinary(image);
    copyMakeBorder( img_bin, img_bin, 1, 1, 1, 1, BORDER_CONSTANT, 0 );

    vector<vector<Point> > contours = traceOutline(img_bin);

    vector<Point> approxCurve = decimateVerticies(contours.front(), 3);

    // draw contour
    for (size_t idx = 0; idx < contours.size(); idx++) {
        drawContours(img_bin, contours, idx, 50);
    }

    foreach(Point x, approxCurve)
    {
        img_bin.data[x.y * img_bin.cols + x.x] = 255;
    }

    // show output
    cv::imshow("Contours", img_bin);

    cv::waitKey(0);

    // success!!
    return 0;
}
Beispiel #6
0
/**
	 * rotates an image by the given angle
	 *
	 * rotateImage (jstring imagePath, jint angle)
	 */
	JNIEXPORT jint JNICALL
	Java_fr_ensicaen_panandroid_stitcher_StitcherWrapper_setPadding
	(JNIEnv* env, jobject obj, jstring imageSrc,jstring imageDst, jint paddingL, jint paddingT, jint paddingR, jint paddingB)
	{
		Mat matSrc;
		Mat matDst;
		const char* src = env->GetStringUTFChars(imageSrc, 0);
		const char* dst = env->GetStringUTFChars(imageDst, 0);


		matSrc = imread(src, CV_LOAD_IMAGE_COLOR);
		if(! matSrc.data )                              // Check for invalid input
		{
			__android_log_print(ANDROID_LOG_ERROR, TAG, "Could not open or find the image %s", src);
			return -1;
		}

		/*if(strcmp(src, dst) == 0)
		{
			matDst = matSrc;
		}*/



	    copyMakeBorder( matSrc, matDst, paddingT, paddingB, paddingL, paddingR, BORDER_CONSTANT, 0 );


		imwrite(dst, matDst);

		env->ReleaseStringUTFChars(imageSrc, src);
		env->ReleaseStringUTFChars(imageDst, dst);

		matSrc.release();
		matDst.release();
		return 0;
	}
Beispiel #7
0
// Agrega un borde de 1 px a la imagen binaria sólo si es necesario
// retorna true si agregó borde
bool Proxy::agregarBorde() {
    unsigned short y, x, xMax2;
    unsigned short yMax = imgBinaria.rows;
    unsigned short xMax = imgBinaria.cols;
    bool encontrado = false;
    uchar* fila;

    fila = imgBinaria.ptr<uchar>(0); // fila arriba
    for (x = 0 ; (x < xMax && !encontrado) ; ++x) {
        if (fila[x] == 0) encontrado = true;
    }
    if (!encontrado) {
        fila = imgBinaria.ptr<uchar>(yMax - 1); // fila abajo
        for (x = 0 ; (x < xMax && !encontrado) ; ++x) {
            if (fila[x] == 0) encontrado = true;
        }
    }
    if (!encontrado) {
        for (y = 1 ; (y < yMax && !encontrado) ; ++y) {
            if (imgBinaria.at<uchar>(y, 0) == 0) encontrado = true;
        }
    }
    if (!encontrado) {
        xMax2 = xMax - 1;
        for (y = 1 ; (y < yMax && !encontrado) ; ++y) {
            if (imgBinaria.at<uchar>(y, xMax2) == 0) encontrado = true;
        }
    }

    if (encontrado) {
        copyMakeBorder(imgBinaria, imgBinaria, 1, 1, 1, 1, BORDER_CONSTANT, 255); // agregamos borde de 1px para evitar errores
        iMapa->bordeAgregado = true;
    }

    return encontrado;
}
Beispiel #8
0
bool OCRTess::detectAndRecog() {
    UMat grey = UMat::zeros(this->img.rows + 2, this->img.cols + 2, CV_8UC1);
    cvtColor(this->img.clone(), grey, COLOR_RGB2GRAY);

    vector<UMat> channels;
    channels.clear();
    channels.push_back(grey);
    Mat m = 255 - grey.getMat(ACCESS_READ | ACCESS_WRITE);
    channels.push_back(m.getUMat(ACCESS_READ));

    vector<vector<ERStat>> regions(2);
    regions[0].clear();
    regions[1].clear();

    switch (this->REGION) {
        case REG_CSER: {
            parallel_for_(Range(0, (int) channels.size()), Parallel_extractCSER(channels, regions, this->erf1, this->erf2));
            break;
        }
        case REG_MSER: {
            vector<vector<Point> > contours;
            vector<Rect> bboxes;
            Ptr<MSER> mser = MSER::create(21, (int) (0.00002 * grey.cols * grey.rows), (int) (0.05 * grey.cols * grey.rows), 1, 0.7);
            mser->detectRegions(grey, contours, bboxes);
            if (contours.size() > 0)
                MSERsToERStats(grey, contours, regions);
            break;
        }
        default: {
            break;
        }
    }

    /*Text Recognition (OCR)*/
    vector<vector<Vec2i> > nm_region_groups;
    vector<Rect> nm_boxes;
    switch (this->GROUP) {
        case 0:
            erGrouping(this->img, channels, regions, nm_region_groups, nm_boxes, ERGROUPING_ORIENTATION_HORIZ);
            break;
        case 1:
        default:
            erGrouping(this->img, channels, regions, nm_region_groups, nm_boxes, ERGROUPING_ORIENTATION_ANY, DIR + TR_GRP, 0.5);
            break;
    }

    if (!nm_boxes.size() || nm_boxes.size() > 1) return false;

    vector<string> words_detection;
    float min_confidence1 = 51.f, min_confidence2 = 60.f;

    vector<UMat> detections;
    for (int i = 0; i < (int) nm_boxes.size(); i++) {
//        rectangle(this->out, nm_boxes[i].tl(), nm_boxes[i].br(), Scalar(255, 255, 0), 3);
        UMat group_img = UMat::zeros(this->img.rows + 2, this->img.cols + 2, CV_8UC1);
        er_draw(channels, regions, nm_region_groups[i], group_img);
        group_img = group_img(nm_boxes[i]);
        copyMakeBorder(group_img.clone(), group_img, 15, 15, 15, 15, BORDER_CONSTANT, Scalar(0));
        detections.push_back(group_img);
    }
    vector<string> outputs((int) detections.size());
    vector<vector<Rect> > boxes((int) detections.size());
    vector<vector<string> > words((int) detections.size());
    vector<vector<float> > confidences((int) detections.size());

    if (!detections.size() || detections.size() > 1) return false;

    for (int i = 0; i < (int) detections.size(); i = i + this->num) {
        Range r;
        if (i + this->num <= (int) detections.size()) r = Range(i, i + this->num);
        else r = Range(i, (int) detections.size());
        parallel_for_(r, Parallel_OCR<OCRTesseract>(detections, outputs, boxes, words, confidences, this->ocrs));
    }

    for (int i = 0; i < (int) detections.size(); i++) {
        outputs[i].erase(remove(outputs[i].begin(), outputs[i].end(), '\n'), outputs[i].end());
        if (outputs[i].size() < 3) {
            continue;
        }
        for (int j = 0; j < (int) boxes[i].size(); j++) {
            boxes[i][j].x += nm_boxes[i].x - 15;
            boxes[i][j].y += nm_boxes[i].y - 15;
            if ((words[i][j].size() < 2) || (confidences[i][j] < min_confidence1) ||
                ((words[i][j].size() == 2) && (words[i][j][0] == words[i][j][1])) ||
                ((words[i][j].size() < 4) && (confidences[i][j] < min_confidence2)) ||
                isRepetitive(words[i][j]))
                continue;
            words_detection.push_back(words[i][j]);
//            rectangle(this->out, boxes[i][j].tl(), boxes[i][j].br(), Scalar(255, 0, 255), 3);
//            Size word_size = getTextSize(words[i][j], FONT_HERSHEY_SIMPLEX, (double) scale_font, (int) (3 * scale_font), NULL);
//            rectangle(this->out, boxes[i][j].tl() - Point(3, word_size.height + 3), boxes[i][j].tl() + Point(word_size.width, 0), Scalar(255, 0, 255), -1);
//            putText(this->out, words[i][j], boxes[i][j].tl() - Point(1, 1), FONT_HERSHEY_SIMPLEX, scale_font, Scalar(255, 255, 255), (int) (3 * scale_font));
        }
    }

    if (!words_detection.size() || words_detection.size() > 1) return false;
    return (words_detection[0].compare(WORD) == 0);
}
Beispiel #9
0
// Fill the new column of node existence matrix using the last tau_w permutation and
// cost matrices. Starting from the last permutation matrix, each new segment is connected
// to one of the previous segments where pairwise segment matching cost is below the tau_m.
// For each new segment, optimum match with previous segments defined by permutation matrix
// and new segment is connected to the latest segment for which matching cost is below tau_m
float SegmentTrack::fillNodeMap(const vector<vector<NodeSig> >& ns_vec)
{
    int N = ns_vec.size(); //Number of the permutation matrices
    float matching_cost = 0;
    float smallest_matching_cost = 9999999;
    vector<Mat> P(N-1), C(N-1);

    //Create pairwise P and C matrices
    //Last frame is matched with each of last tau_w frames
    //and associated P and C matrices inserted into a vector
    //This step is requied for matching any nonmatched nodes
    for(int i = 2; i <= N; i++)
    {
        float match_score = gm->matchTwoImages(ns_vec[N-i], ns_vec.back(), P[N-i], C[N-i]);
    }


    //Expand M(node existence matrix) to fit new column
    copyMakeBorder(M,M,0,0,0,1,BORDER_CONSTANT,-1);

    //Place each segment into M matrix
    for(int s = 0; s < ns_vec.back().size(); s++)
    {
        int node_id = -1; //Node id represents new segment's id in existence map

        //Check last N frames(associated permutation matrices)
        //Find if any of previous segments matches with segment(i.e. matching cost
        // is below threshold)
        for(int i = 2; i <= N; i++)
        {
            int j = getPermuted(P[N-i],s);

            //Check matching cost
            if(j != -1 && C[N-i].at<float>(j,s) < params->seg_track_params.tau_m)
            {
                //return index of jth node in node existence map
                node_id = getIndexByCol(M, M.size().width-i, j);
                matching_cost = matching_cost + C[N-i].at<float>(j,s);
                break;
            }

            //If no matches are found, add smallest matching cost to total
            //matching cost
            if(j != -1 && smallest_matching_cost > C[N-i].at<float>(j,s))
            {
                smallest_matching_cost = C[N-i].at<float>(j,s);
            }
        }

        // If there is no match
        if(node_id == -1)
        {
            //Add new row to M matrix and set last element with new id
            copyMakeBorder(M,M,0,1,0,0,BORDER_CONSTANT,-1);
            M.at<int>(M.size().height-1, M.size().width-1) = s;
            matching_cost = matching_cost + smallest_matching_cost;

            //Add new empty node to M_ns
            pair<NodeSig, int> new_node(ns_vec.back()[s], 1);
            M_ns.push_back(new_node);
        }
        else
        {
            M.at<int>(node_id, M.size().width-1) = s;

            //Update average node signatures
            SSGProc::updateNodeSig(M_ns[node_id], ns_vec.back()[s]);
        }
    }

    return matching_cost;
}
Beispiel #10
0
Mat make_dft(const Mat& IRGB) {
  Mat I;
  cvtColor(IRGB, I, CV_RGB2GRAY);
  Mat padded;                            //expand input image to optimal size
  int m = getOptimalDFTSize(I.rows);
  int n = getOptimalDFTSize(I.cols); // on the border add zero values
  copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));

  Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };
  Mat complexI;
  merge(planes, 2, complexI);         // Add to the expanded another plane with zeros

  dft(complexI, complexI);            // this way the result may fit in the source matrix

  // compute the magnitude and switch to logarithmic scale
  // => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))
  split(complexI, planes);                   // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))
  magnitude(planes[0], planes[1], planes[0]);                   // planes[0] = magnitude
  Mat magI = planes[0];

  magI += Scalar::all(1);                    // switch to logarithmic scale
  log(magI, magI);

  // crop the spectrum, if it has an odd number of rows or columns
  magI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2));

  // rearrange the quadrants of Fourier image  so that the origin is at the image center
  int cx = magI.cols / 2;
  int cy = magI.rows / 2;

  Mat q0(magI, Rect(0, 0, cx, cy));   // Top-Left - Create a ROI per quadrant
  Mat q1(magI, Rect(cx, 0, cx, cy));  // Top-Right
  Mat q2(magI, Rect(0, cy, cx, cy));  // Bottom-Left
  Mat q3(magI, Rect(cx, cy, cx, cy)); // Bottom-Right

  Mat tmp;                           // swap quadrants (Top-Left with Bottom-Right)
  q0.copyTo(tmp);
  q3.copyTo(q0);
  tmp.copyTo(q3);

  q1.copyTo(tmp);                    // swap quadrant (Top-Right with Bottom-Left)
  q2.copyTo(q1);
  tmp.copyTo(q2);

  normalize(magI, magI, 0, 1, CV_MINMAX);
/*
  int lowThreshold = 100;
  int ratio = 3;
  int kernel_size = 3;

  Mat detected_edges;
  Mat gray;
  Mat sharpened;
  magI.convertTo(gray, CV_8U);

  cv::GaussianBlur(gray, sharpened, cv::Size(0, 0), 3);
  cv::addWeighted(gray, 1.5, sharpened, -0.5, 0, sharpened);
  sharpened.convertTo(magI, CV_32F);*/

  return magI;
}
Beispiel #11
0
template <typename PointT> double
pcl::people::PersonClassifier<PointT>::evaluate (float height_person,
              float xc,
              float yc,
              PointCloudPtr& image)
{
  if (SVM_weights_.empty ())
  {
  PCL_ERROR ("[pcl::people::PersonClassifier::evaluate] SVM has not been set!\n");
  return (-1000);
  }

  int height = floor((height_person * window_height_) / (0.75 * window_height_) + 0.5);  // floor(i+0.5) = round(i)
  int width = floor((height_person * window_width_) / (0.75 * window_height_) + 0.5);
  int xmin = floor(xc - width / 2 + 0.5);
  int ymin = floor(yc - height / 2 + 0.5);
  double confidence;

  if (height > 0)
  {
    // If near the border, fill with black:
    PointCloudPtr box(new PointCloud);
    copyMakeBorder(image, box, xmin, ymin, width, height);

    // Make the image match the correct size (used in the training stage):
    PointCloudPtr sample(new PointCloud);
    resize(box, sample, window_width_, window_height_);

    // Convert the image to array of float:
    float* sample_float = new float[sample->width * sample->height * 3]; 
    int delta = sample->height * sample->width;
    for (uint32_t row = 0; row < sample->height; row++)
    {
      for (uint32_t col = 0; col < sample->width; col++)
      {
        sample_float[row + sample->height * col] = ((float) ((*sample)(col, row).r))/255; //ptr[col * 3 + 2];
        sample_float[row + sample->height * col + delta] = ((float) ((*sample)(col, row).g))/255; //ptr[col * 3 + 1];
        sample_float[row + sample->height * col + delta * 2] = (float) (((*sample)(col, row).b))/255; //ptr[col * 3];
      }
    }

    // Calculate HOG descriptor:
    pcl::people::HOG hog;
    float *descriptor = (float*) calloc(SVM_weights_.size(), sizeof(float));
    hog.compute(sample_float, descriptor);
 
    // Calculate confidence value by dot product:
    confidence = 0.0;
    for(size_t i = 0; i < SVM_weights_.size(); i++)
    { 
      confidence += SVM_weights_[i] * descriptor[i];
    }
    // Confidence correction:
    confidence -= SVM_offset_;  

    delete[] descriptor;
    delete[] sample_float;
  }
  else
  {
    confidence = std::numeric_limits<double>::quiet_NaN();
  } 

  return confidence;
}
void PhaseCorrelation::controller(const sensor_msgs::ImageConstPtr& msg) {

	//Transform the image to opencv format
   cv_bridge::CvImagePtr cv_ptr;
    try
    {
      cv_ptr = cv_bridge::toCvCopy(msg, enc::BGR8);
    }
    catch (cv_bridge::Exception& e)
    {
      ROS_ERROR("cv_bridge exception: %s", e.what());
      return;
    }
	
	Mat image = cv_ptr->image; 
	
	imshow("image", image);
	waitKey(1);

	//Transform image to grayscale
	cvtColor(image, image2_in, CV_RGB2GRAY); //Image2 is the newest image, the one we get from this callback

	//image1 is the image2 from the last callback (we use the one that already has the dft applied. 
	Mat image1_dft = last_image_dft;

	//Image2, preparation and dft
	 Mat padded2;                            //expand input image to optimal size
	 int m2 = getOptimalDFTSize( image2_in.rows );
	 int n2 = getOptimalDFTSize( image2_in.cols ); // on the border add zero values
	 copyMakeBorder(image2_in, padded2, 0, m2 - image2_in.rows, 0, n2 - image2_in.cols, BORDER_CONSTANT, Scalar::all(0));

	 Mat planes2[] = {Mat_<float>(padded2), Mat::zeros(padded2.size(), CV_32F)};
	 Mat image2,image2_dft;
	 merge(planes2, 2, image2);         // Add to the expanded another plane with zeros

	 dft(image2, image2_dft); 	


	//Image2 will be image1 on next iteration
	last_image_dft=image2_dft;

	if( !first){
	 	//obtain the cross power spectrum  c(u,v)=F(u,v)·G*(u,v)/abs(F(u,v)·G*(u,v))
		Mat divident, divisor, cross_power_spec, trans_mat;
		mulSpectrums(image1_dft, image2_dft, divident, 0, true); 	
																		//=F(u,v)·G*(u,v) --> multiply the result of a dft //divident-> where it stores the result.
																		// flags=0. conj=true, because i want the image2 to be the complex conjugate.
		divisor=abs(divident);

		divide(divident, divisor, cross_power_spec, 1);	

		//dft of the cross_power_spec
	 	dft(cross_power_spec, trans_mat, DFT_INVERSE);

		//Normalize the trans_mat so that all the values are between 0 and 1
		normalize(trans_mat, trans_mat, NORM_INF);

		//Split trans_mat in it's real and imaginary parts
		vector<Mat> trans_mat_vector;
		split(trans_mat, trans_mat_vector);
		Mat trans_mat_real = trans_mat_vector.at(0); 
		Mat trans_mat_im = trans_mat_vector.at(1); 

		imshow("trans_mat_real", trans_mat_real);
		waitKey(1);

		//Look for maximum value and it's location on the trans_mat_real matrix
		double* max_value;
		Point* max_location;

		double max_val;
		Point max_loc; 
		max_value = &max_val;
		max_location = &max_loc;
	
		minMaxLoc(trans_mat_real, NULL, max_value, NULL, max_location);

		ROS_INFO_STREAM("max_value: " << max_val << "  -  " << "max_location: " << max_loc);			

		int pixel_x, pixel_y;

		if(max_loc.x < (image2.cols/2) && max_loc.y < (image2.rows/2)){  // top-left quadrant
			ROS_INFO_STREAM(" top - left quadrant");
			pixel_x = max_loc.x;
			pixel_y = - max_loc.y;
		}
		if(max_loc.x > (image2.cols/2) && max_loc.y > (image2.rows/2)){  // lower-right quadrant
			ROS_INFO_STREAM(" lower - right quadrant");
			pixel_x = - image2.cols + max_loc.x;
			pixel_y = + image2.rows - max_loc.y;
		}
		if(max_loc.x > (image2.cols/2) && max_loc.y < (image2.rows/2)){  // top-right quadrant
			ROS_INFO_STREAM(" top - right quadrant");
			pixel_x = - image2.cols + max_loc.x;
			pixel_y = - max_loc.y;
		}
		if(max_loc.x < (image2.cols/2) && max_loc.y > (image2.rows/2)){  // lower-left quadrant  
			ROS_INFO_STREAM(" lower - left quadrant");
			pixel_x = max_loc.x;
			pixel_y = image2.rows - max_loc.y;
		}


		//Add the new displacement to the accumulated
		pixels_x = pixels_x + pixel_x;
		pixels_y = pixels_y + pixel_y;
		ROS_INFO_STREAM("pixels_x: " << pixels_x << "  -  " << "pixel_y: " << pixels_y);		

		//------ transform pixels to mm ---------
 
		//To get the focal lenght:
		if (first){	

			Mat cameraMatrix(3, 3, CV_32F);
			cameraMatrix.at<float>(0,0)= 672.03175; //Values from the camera matrix are from the visp calibration
			cameraMatrix.at<float>(0,1) = 0.00000;
			cameraMatrix.at<float>(0,2) = 309.39349;
			cameraMatrix.at<float>(1,0) = 0.00000;
			cameraMatrix.at<float>(1,1) = 673.05595;
			cameraMatrix.at<float>(1,2) = 166.52006; 
			cameraMatrix.at<float>(2,0) = 0.00000;
			cameraMatrix.at<float>(2,1) = 0.00000;
			cameraMatrix.at<float>(2,2) = 1.00000;

			double apertureWidth, apertureHeight, fovx, fovy, focalLength, aspectRatio;
			Point2d principalPoint;
 
 			calibrationMatrixValues(cameraMatrix, image.size(), apertureWidth, apertureHeight, fovx, fovy, focalLength,  principalPoint, aspectRatio);
	
			ROS_INFO_STREAM("focalLength: " << focalLength);
			fl = focalLength;

			first=false;
		}
		
		float mov_x = pixel_x/fl*h;
		float mov_y = pixel_y/fl*h;
		mov_x_acc =	mov_x_acc + mov_x;
		mov_y_acc = mov_y_acc + mov_y;

		ROS_INFO_STREAM("mov_x:  " << mov_x << " - mov_y:  " << mov_y);
		ROS_INFO_STREAM("mov_x_acc:  " << mov_x_acc << " - mov_y_acc:  " << mov_y_acc);

	}

}
char detectBlueBlock(Mat image)
{
	int T=15; //面积与边长之比的阈值
	ColorHistogram hc;	
	MatND colorhist = hc.getHueHistogram(image);
	//遍历直方图数据
	//hc.getHistogramStat(colorhist);
	/*
	Mat histImg = hc.getHistogramImage(colorhist);
	namedWindow("BlueBlockHistogram");
	imshow("BlueBlockHistogram", histImg);*/

	Mat thresholded, thresholded1, thresholded2, thresholded3;
	threshold(hc.v[0], thresholded1, 100, 255, 1);
	threshold(hc.v[0], thresholded2, 124, 255, 0); 
	threshold(hc.v[1], thresholded3, 125, 255, 1); //变成黑色
	thresholded = thresholded1+thresholded2+thresholded3;
	//imshow("1", thresholded1);
	//imshow("2", thresholded2);
	//imshow("3", thresholded3);

	//namedWindow("BlueBlockBinary");
	//imshow("BlueBlockBinary", thresholded);
	int top = (int) (0.05*thresholded.rows); 
	int bottom = (int) (0.05*thresholded.rows);
    int left = (int) (0.05*thresholded.cols); 
	int right = (int) (0.05*thresholded.cols);
	Scalar value = Scalar( 255 );
    copyMakeBorder( thresholded, thresholded, top, bottom, left, right, 0, value );
	
	/*
	Mat eroded;
	erode(thresholded, eroded, Mat());
	namedWindow("ErodedImage");
	imshow("ErodedImage", eroded);

	Mat dilated;
	erode(thresholded, dilated, Mat());
	namedWindow("DilatedImage");
	imshow("DilatedImage", dilated);*/

	//闭运算
	Mat closed;
	morphologyEx(thresholded, closed, MORPH_CLOSE,  Mat());
	//namedWindow("ClosedImage");
	//imshow("ClosedImage", closed);

	vector<vector<Point>>contours;
	findContours(closed, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
	//筛选不合格轮廓
	int cmin = 100; //最小轮廓长度
	vector<vector<Point>>::const_iterator itc = contours.begin();
	while (itc != contours.end())	
	{
		if (itc->size()<cmin)
			itc = contours.erase(itc);
		else
			itc++;
	}

	Mat result(closed.size(), CV_8U, Scalar(255));
	double area, length, p;
	double a[2] = {0,0}; 
	cout << "Size=" << contours.size() << endl;
	for ( int i=0; i<contours.size(); i++)
	{
		area = abs(contourArea( contours[i] ));
		length = abs(arcLength( contours[i], true ));
		p = area/length;
		if (p > a[0]) 
		{
			a[1] = a[0];
			a[0] = p;
		}
		else if (p > a[1]) a[1] = p; 
 		cout << "Area=" << area << "   " << "Length=" << length << "  " << "Property=" << p << endl;
	}
	drawContours(result, contours, -1, Scalar(0), 1);
	//namedWindow("DrawContours");
	//imshow("DrawContours", result);
	cout << "Property=" << a[1] << endl;
	//waitKey();
	
	if (a[1] > T) return BLUEBLOCK;
			  else return NOTHING;
}
Beispiel #14
0
void VideoCorrect::correctImage(Mat& inputFrame, Mat& outputFrame, bool developerMode){
	
	resize(inputFrame, inputFrame, CAMERA_RESOLUTION);
	inputFrame.copyTo(img);

	//Convert to YCbCr color space
	cvtColor(img, ycbcr, CV_BGR2YCrCb);

	//Skin color thresholding
	inRange(ycbcr, Scalar(0, 150 - Cr, 100 - Cb), Scalar(255, 150 + Cr, 100 + Cb), bw);

	if(IS_INITIAL_FRAME){
		face = detectFaces(img);
		if(face.x != 0){
			lastFace = face;
		}
		else{
			outputFrame = img;
			return;
		}
		prevSize = Size(face.width/2, face.height/2);
		head = Mat::zeros(bw.rows, bw.cols, bw.type());
		ellipse(head, Point(face.x + face.width/2, face.y + face.height/2), prevSize, 0, 0, 360, Scalar(255,255,255,0), -1, 8, 0);
		if(face.x > 0 && face.y > 0 && face.width > 0 && face.height > 0 
			&& (face.x + face.width) < img.cols && (face.y + face.height) < img.rows){
			img(face).copyTo(bestImg);
		}
		putText(img, "Give your best pose!", Point(face.x, face.y), CV_FONT_HERSHEY_SIMPLEX, 0.4, Scalar(255,255,255,0), 1, CV_AA);
	}

	firstFrameCounter--;

	if(face.x == 0) //missing face prevention
		face = lastFace;

	//Mask the background out
	bw &= head;

	//Compute more accurate image moments after background removal
	m = moments(bw, true);
	angle = (atan((2*m.nu11)/(m.nu20-m.nu02))/2)*180/PI;
	center = Point(m.m10/m.m00,m.m01/m.m00);

	//Smooth rotation (running average)
	bufferCounter++;
	rotationBuffer[ bufferCounter % SMOOTHER_SIZE ] = angle;
	smoothAngle += (angle - rotationBuffer[(bufferCounter + 1) % SMOOTHER_SIZE]) / SMOOTHER_SIZE;

	//Expand borders
	copyMakeBorder( img, img, BORDER_EXPAND, BORDER_EXPAND, BORDER_EXPAND, BORDER_EXPAND, 
					BORDER_REPLICATE, Scalar(255,255,255,0));

	if(!IS_INITIAL_FRAME){
		//Rotate the image to correct the leaning angle
		rotateImage(img, smoothAngle);
	
		//After rotation detect faces
		face = detectFaces(img);
		if(face.x != 0)
			lastFace = face;

		//Create background mask around the face
		head = Mat::zeros(bw.rows, bw.cols, bw.type());
		ellipse(head, Point(face.x - BORDER_EXPAND + face.width/2, face.y -BORDER_EXPAND + face.height/2),
					  prevSize, 0, 0, 360, Scalar(255,255,255,0), -1, 8, 0);

		//Draw a rectangle around the face
		//rectangle(img, face, Scalar(255,255,255,0), 1, 8, 0);

		//Overlay the ideal pose
		if(replaceFace && center.x > 0 && center.y > 0){
			center = Point(face.x + face.width/2, face.y + face.width/2);
			overlayImage(img, bestImg, center, smoothSize);
		}

	} else{
		face.x += BORDER_EXPAND; //position alignment after border expansion (not necessary if we detect the face after expansion)
		face.y += BORDER_EXPAND;
	}
	
	//Smooth ideal image size (running average)
	sizeBuffer[ bufferCounter % SMOOTHER_SIZE ] = face.width;
	smoothSize += (face.width - sizeBuffer[(bufferCounter + 1) % SMOOTHER_SIZE]) / SMOOTHER_SIZE;

	//Get ROI
	center = Point(face.x + face.width/2, face.y + face.width/2);
	roi = getROI(img, center);
	if(roi.x > 0 && roi.y > 0 && roi.width > 0 && roi.height > 0 
		&& (roi.x + roi.width) < img.cols && (roi.y + roi.height) < img.rows){
		img = img(roi);
	}

	//Resize the final image
	resize(img, img, CAMERA_RESOLUTION);

	if(developerMode){

		Mat developerScreen(img.rows, 
							img.cols + 
							inputFrame.cols +
							bw.cols, CV_8UC3);

		Mat left(developerScreen, Rect(0, 0, img.size().width, img.size().height));
		img.copyTo(left);

		Mat center(developerScreen, Rect(img.cols, 0, inputFrame.cols, inputFrame.rows));
		inputFrame.copyTo(center);

		cvtColor(bw, bw, CV_GRAY2BGR);
		Mat right(developerScreen, Rect(img.size().width + inputFrame.size().width, 0, bw.size().width, bw.size().height));
		bw.copyTo(right);

		Mat rightmost(developerScreen, Rect(img.size().width + inputFrame.size().width + bw.size().width - bestImg.size().width, 0,
											bestImg.size().width, bestImg.size().height));
		bestImg.copyTo(rightmost);

		outputFrame = developerScreen;
	}
	else{
		outputFrame = img;
	}
}
Beispiel #15
0
    void CV_BilateralFilterTest::reference_bilateral_filter(const Mat &src, Mat &dst, int d,
        double sigma_color, double sigma_space, int borderType)
    {
        int cn = src.channels();
        int i, j, k, maxk, radius;
        double minValSrc = -1, maxValSrc = 1;
        const int kExpNumBinsPerChannel = 1 << 12;
        int kExpNumBins = 0;
        float lastExpVal = 1.f;
        float len, scale_index;
        Size size = src.size();

        dst.create(size, src.type());

        CV_Assert( (src.type() == CV_32FC1 || src.type() == CV_32FC3) &&
            src.type() == dst.type() && src.size() == dst.size() &&
            src.data != dst.data );

        if( sigma_color <= 0 )
            sigma_color = 1;
        if( sigma_space <= 0 )
            sigma_space = 1;

        double gauss_color_coeff = -0.5/(sigma_color*sigma_color);
        double gauss_space_coeff = -0.5/(sigma_space*sigma_space);

        if( d <= 0 )
            radius = cvRound(sigma_space*1.5);
        else
            radius = d/2;
        radius = MAX(radius, 1);
        d = radius*2 + 1;
        // compute the min/max range for the input image (even if multichannel)

        minMaxLoc( src.reshape(1), &minValSrc, &maxValSrc );
        if(std::abs(minValSrc - maxValSrc) < FLT_EPSILON)
        {
            src.copyTo(dst);
            return;
        }

        // temporary copy of the image with borders for easy processing
        Mat temp;
        copyMakeBorder( src, temp, radius, radius, radius, radius, borderType );
        patchNaNs(temp);

        // allocate lookup tables
        vector<float> _space_weight(d*d);
        vector<int> _space_ofs(d*d);
        float* space_weight = &_space_weight[0];
        int* space_ofs = &_space_ofs[0];

        // assign a length which is slightly more than needed
        len = (float)(maxValSrc - minValSrc) * cn;
        kExpNumBins = kExpNumBinsPerChannel * cn;
        vector<float> _expLUT(kExpNumBins+2);
        float* expLUT = &_expLUT[0];

        scale_index = kExpNumBins/len;

        // initialize the exp LUT
        for( i = 0; i < kExpNumBins+2; i++ )
        {
            if( lastExpVal > 0.f )
            {
                double val =  i / scale_index;
                expLUT[i] = (float)std::exp(val * val * gauss_color_coeff);
                lastExpVal = expLUT[i];
            }
            else
                expLUT[i] = 0.f;
        }

        // initialize space-related bilateral filter coefficients
        for( i = -radius, maxk = 0; i <= radius; i++ )
            for( j = -radius; j <= radius; j++ )
            {
                double r = std::sqrt((double)i*i + (double)j*j);
                if( r > radius )
                    continue;
                space_weight[maxk] = (float)std::exp(r*r*gauss_space_coeff);
                space_ofs[maxk++] = (int)(i*(temp.step/sizeof(float)) + j*cn);
            }

        for( i = 0; i < size.height; i++ )
        {
            const float* sptr = (const float*)(temp.data + (i+radius)*temp.step) + radius*cn;
            float* dptr = (float*)(dst.data + i*dst.step);

            if( cn == 1 )
            {
                for( j = 0; j < size.width; j++ )
                {
                    float sum = 0, wsum = 0;
                    float val0 = sptr[j];
                    for( k = 0; k < maxk; k++ )
                    {
                        float val = sptr[j + space_ofs[k]];
                        float alpha = (float)(std::abs(val - val0)*scale_index);
                        int idx = cvFloor(alpha);
                        alpha -= idx;
                        float w = space_weight[k]*(expLUT[idx] + alpha*(expLUT[idx+1] - expLUT[idx]));
                        sum += val*w;
                        wsum += w;
                    }
                    dptr[j] = (float)(sum/wsum);
                }
            }
            else
            {
                assert( cn == 3 );
                for( j = 0; j < size.width*3; j += 3 )
                {
                    float sum_b = 0, sum_g = 0, sum_r = 0, wsum = 0;
                    float b0 = sptr[j], g0 = sptr[j+1], r0 = sptr[j+2];
                    for( k = 0; k < maxk; k++ )
                    {
                        const float* sptr_k = sptr + j + space_ofs[k];
                        float b = sptr_k[0], g = sptr_k[1], r = sptr_k[2];
                        float alpha = (float)((std::abs(b - b0) +
                            std::abs(g - g0) + std::abs(r - r0))*scale_index);
                        int idx = cvFloor(alpha);
                        alpha -= idx;
                        float w = space_weight[k]*(expLUT[idx] + alpha*(expLUT[idx+1] - expLUT[idx]));
                        sum_b += b*w; sum_g += g*w; sum_r += r*w;
                        wsum += w;
                    }
                    wsum = 1.f/wsum;
                    b0 = sum_b*wsum;
                    g0 = sum_g*wsum;
                    r0 = sum_r*wsum;
                    dptr[j] = b0; dptr[j+1] = g0; dptr[j+2] = r0;
                }
            }
        }
    }
    /**
     * The predicted sharp edge gradient ∇I^s is used as a spatial prior to guide
     * the recovery of a coarse version of the latent image.
     * Objective function: E(I) = ||I ⊗ k - B||² + λ||∇I - ∇I^s||²
     * 
     * @param blurred        blurred grayvalue image (B)
     * @param kernel         energy presserving kernel (k)
     * @param selectionGrads gradients of selected edges (x and y direction) (∇I^s)
     * @param latent         resulting image (I)
     * @param weight         λ, default is 2.0e-3 (weight from paper)
     */
    void coarseImageEstimation(Mat blurred, const Mat& kernel,
                               const array<Mat,2>& selectionGrads, Mat& latent,
                               const float weight = 2.0e-3) {

        assert(kernel.type() == CV_32F && "works with energy preserving float kernel");
        assert(blurred.type() == CV_8U && "works with gray valued blurred image");

        // convert grayvalue image to float and normalize it to [0,1]
        blurred.convertTo(blurred, CV_32F);
        blurred /= 255.0;

        // fill kernel with zeros to get to the blurred image size
        // it's important to use BORDER_ISOLATED flag if the kernel is an ROI of a greater image!
        Mat pkernel;
        copyMakeBorder(kernel, pkernel, 0,
                       blurred.rows - kernel.rows, 0,
                       blurred.cols - kernel.cols,
                       BORDER_CONSTANT, Scalar::all(0));

        // using sobel filter as gradients dx and dy
        Mat sobelx = Mat::zeros(blurred.size(), CV_32F);
        sobelx.at<float>(0,0) = -1;
        sobelx.at<float>(0,1) = 1;
        Mat sobely = Mat::zeros(blurred.size(), CV_32F);
        sobely.at<float>(0,0) = -1;
        sobely.at<float>(1,0) = 1;


        //                ____               ______                ______
        //             (  F(k) * F(B) + λ * (F(∂_x) * F(∂_x I^s) + F(∂_y) * F(∂_y I^s)) )
        // I = F^-1 * ( ---------------------------------------------------------------  )
        //            (     ____               ______            ______                  )
        //             (    F(k) * F(k) + λ * (F(∂_x) * F(∂_x) + F(∂_y) * F(∂_y))       )
        // where * is pointwise multiplication
        // 
        // here: F(k)       = k
        //       F(∂_x I^s) = xS
        //       F(∂_y I^s) = yS
        //       F(∂_x)     = dx
        //       F(∂_y)     = dy
        //       F(B)       = B

        // compute DFT (withoud padding)
        // the result are stored as 2 channel matrices: Re(FFT(I)), Im(FFT(I))
        Mat K, xS, yS, B, Dx, Dy;
        deblur::dft(pkernel, K);
        deblur::dft(selectionGrads[0], xS);
        deblur::dft(selectionGrads[1], yS);
        deblur::dft(blurred, B);
        deblur::dft(sobelx, Dx);
        deblur::dft(sobely, Dy);

        // weight from paper
        complex<float> we(weight, 0.0);

        // latent image in fourier domain
        Mat I = Mat::zeros(xS.size(), xS.type());

        // pointwise computation of I
        for (int x = 0; x < xS.cols; x++) {
            for (int y = 0; y < xS.rows; y++) {
                // complex entries at the current position
                complex<float> b(B.at<Vec2f>(y, x)[0], B.at<Vec2f>(y, x)[1]);
                complex<float> k(K.at<Vec2f>(y, x)[0], K.at<Vec2f>(y, x)[1]);

                complex<float> xs(xS.at<Vec2f>(y, x)[0], xS.at<Vec2f>(y, x)[1]);
                complex<float> ys(yS.at<Vec2f>(y, x)[0], yS.at<Vec2f>(y, x)[1]);

                complex<float> dx(Dx.at<Vec2f>(y, x)[0], Dx.at<Vec2f>(y, x)[1]);
                complex<float> dy(Dy.at<Vec2f>(y, x)[0], Dy.at<Vec2f>(y, x)[1]);

                // compute current point of latent image in fourier domain
                complex<float> i = (conj(k) * b + we * (conj(dx) * xs + conj(dy) * ys)) /
                                   (conj(k) * k + we * (conj(dx) * dx + conj(dy) * dy));
                
                I.at<Vec2f>(y, x) = { real(i), imag(i) };
            }
        }

        // compute inverse DFT of the latent image
        dft(I, latent, DFT_INVERSE | DFT_REAL_OUTPUT);


        // threshold the result because it has large negative and positive values
        // which would result in a very grayish image
        threshold(latent, latent, 0.0, -1, THRESH_TOZERO);


        // swap slices of the result
        // because the image is shifted to the upper-left corner (why??)
        int x = latent.cols;
        int y = latent.rows;
        int hs1 = (kernel.cols - 1) / 2;
        int hs2 = (kernel.rows - 1) / 2;

        // create rects per image slice
        //  __________
        // |      |   |
        // |   0  | 1 |
        // |      |   |
        // |------|---|
        // |   2  | 3 |
        // |______|___|
        // 
        // rect gets the coordinates of the top-left corner, width and height
        Mat q0(latent, Rect(0, 0, x - hs1, y - hs2));      // Top-Left
        Mat q1(latent, Rect(x - hs1, 0, hs1, y - hs2));    // Top-Right
        Mat q2(latent, Rect(0, y - hs2, x - hs1, hs2));    // Bottom-Left
        Mat q3(latent, Rect(x - hs1, y - hs2, hs1, hs2));  // Bottom-Right

        Mat latentSwap;
        cv::hconcat(q3, q2, latentSwap);
        Mat tmp;
        cv::hconcat(q1, q0, tmp);
        cv::vconcat(latentSwap, tmp, latentSwap);


        // convert result to uchar image
        convertFloatToUchar(latentSwap, latent);

        assert(blurred.size() == latent.size()
               && "Something went wrong - latent and blurred size has to be equal");
    }
bool SpatialAverageSpotter::train(string dirPath)
{
    
    int count=0;
    vector<vector<tuple<int,Point2f> > > features;
    featureAverages.resize(codebook->size());
    for (int i =0; i<codebook->size(); i++)
        featureAverages[i]=Mat(BASE_SIZE,BASE_SIZE,CV_32F,Scalar(0));
    
    DIR *dir;
    struct dirent *ent;
    if ((dir = opendir (dirPath.c_str())) != NULL) {
      /* print all the files and directories within directory */
//      Mat img;
      while ((ent = readdir (dir)) != NULL) {
          
          string fileName(ent->d_name);
//          cout << "examining " << fileName << endl;
          if (fileName[0] == '.' || fileName[fileName.size()-1]!='G')
              continue;
          
          Mat img = imread(dirPath+fileName, CV_LOAD_IMAGE_GRAYSCALE);
//          resize(img,img,Size(0,0),2,2);
          threshold(img,img,120.0,255,THRESH_BINARY);
//          windowWidth += img.cols;
//          windowHeight += img.rows;
//          int avg=0;
//          for (int x=0; x<img.cols; x++)
//              for (int  y=0; y<img.rows; y++)
//                  avg += (int)img.at<unsigned char>(y,x);
////          cout << "avg="<<avg<<"/"<<img.cols*img.rows<<" = "<<avg/(img.cols*img.rows)<<endl;
//          avg /= img.cols*img.rows;
          
          resize(img,img,Size(PRE_BASE_SIZE,PRE_BASE_SIZE*((0.0+img.rows)/img.cols)));
          
          
          copyMakeBorder( img, img, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_CONSTANT, 255 );
          assert(img.cols > 1 && img.rows > 1);
          adjustedTrainingImages.push_back(img.clone());
          
          Point2f centerOfMass = findCenterOfMass(img);
          int offsetx=(img.cols/2)-centerOfMass.x;
          int offsety=(img.rows/2)-centerOfMass.y;
          translateImg(img,offsetx,offsety);
          
        
          vector<KeyPoint> keypoints;
          Mat desc;
          detectKeypoints( img,keypoints, desc);
          Mat out;
          cvtColor(img,out,CV_GRAY2RGB);
          circle(out,centerOfMass,1,Scalar(0,0,255));
          
          features.resize(count+1);
          //double scaling = BASE_SIZE/img
          for (int r=0; r<desc.rows; r++)
          {
              int f = codebook->quantize(desc.row(r));
              Point2f offsetPoint(keypoints[r].pt.x - centerOfMass.x, keypoints[r].pt.y - centerOfMass.y);
              features[count].push_back(make_tuple(f,offsetPoint));//we're ignoring the keypoint scale.. 
              
              
//              circle(out,keypoints[r].pt,keypoints[r].size,Scalar(colorTable[f]));
              Rect rec(keypoints[r].pt.x-(keypoints[r].size/2),keypoints[r].pt.y-(keypoints[r].size/2),keypoints[r].size,keypoints[r].size);
              rectangle(out,rec,Scalar(colorTable[f]));
              
          }
          guassColorIn(features[count]);
          
          
          imshow("learning keypoints",out);
          cout << "image "<<count<<endl;
          waitKey(5);
          
          count++;
//          img.release();
      }
      closedir (dir);
    } else {
      /* could not open directory */
      perror ("");
      return false;
    }
    
    //We now step through adjusting the scales of the various images so the guass coloring is maximized
    //But we may still want to look at tfidf to see which ones should be weighted more, etc.
    maximizeAlignment(features);
    
    float max=0;
    float min =99999;
    float avg_max=0;
    
    int firstx=9999;
    int lastx=0;
    int firsty=9999;
    int lasty=0;
    
    for (int f=0; f<codebook->size(); f++)
    {
        float local_max=0;
        
        bool hitFirst=false;
        
        for (int x=0; x<featureAverages[f].cols; x++)
            for (int y=0; y<featureAverages[f].rows; y++)
            {
                float val = featureAverages[f].at<float>(y,x);
                if (val > 300 || val < -300)
                    cout << "val (" << x <<","<<y<<") " << val << endl;
                if (val>max) max=val;
                if (val<min) min=val;
                if (val>local_max) local_max=val;
                
                if (val>WINDOW_THRESH)
                {
                    if (!hitFirst)
                    {
                        hitFirst=true;
                        if (x<firstx) firstx=x;
                        if (y<firsty) firsty=y;
                    }
                    if (x>lastx) lastx=x;
                    if (y>lasty) lasty=y;
                }
            }
        avg_max+=local_max;
    }
//    penalty=min+(max-min)*.2;
    avg_max /= codebook->size();
    penalty=avg_max*.15;//.2
    
//    windowWidth/=count;
//    windowHeight/=count;
    windowWidth = lastx-firstx;
    windowHeight = lasty-firsty;
    cout << "window size is "<<windowWidth<<"x"<<windowHeight<<endl;
    
    //show averages
    showAverages();
    
    return true;
}
Beispiel #18
0
int main(int argc, char **argv){

  int opcion;	//Opcion para el getopt
  int vflag=0, rflag=0, nflag=0, glfag=0, iflag=0, mflag=0, oflag=0;  //Flags para el getopt
  float r=0.5, g=1.0;
  int n=2;
  string nombreImagen;
  string nombreMascara;
  string nombreSalida = "output.png";
  Mat imagen, padded, complexImg, filter, filterAux, imagenSalida, filterSalida, imagenFrecuencias, imagenFrecuenciasSinOrden, imagenHSV;
  Mat complexAux;
  Mat salida;
  Mat imagenPasoBaja;
  Mat mascara;
  vector<Mat> canales;

  while((opcion=getopt(argc, argv, "vr:n:g:i:o:m:")) !=-1 ){

    switch(opcion){

      case 'v':
        vflag=1;
      break;

      case 'r':
        rflag=1;
        r=atof(optarg);
        if(r<0 || r>1){
          cout << "Valor de 'r' introducido invalido" << endl;
          exit(-1);
        }
      break;

      case 'n':
        nflag=1;
        n = atoi(optarg);
        if(n<0 || n>10){
          cout << "Valor de 'n' introducido invalido" << endl;
          exit(-1);
        }
      break;

      case 'g':
        glfag=1;
        g = atof(optarg);
        if(g<0.0 || g>5.0){
          cout << "Valor de 'g' introducido invalido" << endl;
          exit(-1);
        }
      break;

      case 'i':
        iflag=1;
        nombreImagen = optarg;
      break;

      case 'm':
        mflag=1;
        nombreMascara=optarg;
      break;

      case 'o':
        oflag=1;
        nombreSalida=optarg;
      break;
    	
    	
    	case '?':
     	   //Algo ha ido mal
     	   help();
     	   exit(-1);
        break;

    	default:
    		help();
     		exit(-1);
        break;
      }

   }

   //Primero cargaremos la imagen



   if(iflag==1){
    imagen = imread(nombreImagen, CV_LOAD_IMAGE_ANYDEPTH);
    if(imagen.empty()){
      cout << "Imagen especificada invalida" << endl;
      exit(-1);
    }else{
      cout << "Imagen cargada con exito" << endl;
      if(vflag==1){
        namedWindow("Imagen", CV_WINDOW_AUTOSIZE);
        imshow("Imagen", imagen);
        waitKey(0);
        destroyWindow("Imagen");
      }
    }
  }else{
    cout << "La imagen es necesaria" << endl;
    exit(-1);
   }

   //Calculamos r
   r=(r)*(sqrt(pow((imagen.rows),2.0)+pow((imagen.cols),2.0))/2);

   int M = getOptimalDFTSize(imagen.rows);
   int N = getOptimalDFTSize(imagen.cols);


   //Miramos si tiene mascara para cargarla
  if(mflag==1){
    //Cargamos la mascara
    mascara = imread(nombreMascara, 0);
    if(mascara.empty()){
      cout << "Mascara especificada invalida" << endl;
      exit(-1);
    }else{
	cout << "Mascara cargada con exito" << endl;
	   }
  }


   //Ahora miramos los canales para hacer cosas distintas dependiendo

   if(imagen.channels()==1){
    //Imagen monocromatica

    imagen.convertTo(imagenPasoBaja,CV_32F, 1.0/255.0);
    copyMakeBorder(imagenPasoBaja, padded, 0, M-imagenPasoBaja.rows, 0, N - imagenPasoBaja.cols, BORDER_CONSTANT, Scalar::all(0));
    Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
    merge(planes, 2, complexImg);

    dft(complexImg, complexImg);
    filter = complexImg.clone();
    filterAux = complexImg.clone();
    complexAux = complexImg.clone();
    shiftDFT(complexImg);
    shiftDFT(complexAux);

    butterworth(filter, r, n);
    butterworth(filterAux, r, 0);
    mulSpectrums(complexImg, filter, complexImg, 0);
    mulSpectrums(complexAux, filterAux, complexAux, 0);
    shiftDFT(complexImg);
    shiftDFT(complexAux);

    //Falta hacer lo de poder mostrarla
    imagenFrecuencias = create_spectrum(complexImg);
    imagenFrecuenciasSinOrden = create_spectrum(complexAux);

    //Hacemos la inversa
    idft(complexImg, complexImg, DFT_SCALE);
    split(complexImg, planes);
    normalize(planes[0], imagenSalida, 0, 1, CV_MINMAX);
    split(filter, planes);
    normalize(planes[0], filterSalida, 0, 1, CV_MINMAX);

   salida = imagenPasoBaja.clone();
    if(mflag==1){
      //Con mascara procesaremos pixel por pixel
      //Recorremos la imagen
      for(int i=0; i<imagen.rows; i++){
        for(int j=0; j<imagen.cols;j++){
          if(mascara.at<uchar>(i,j)!=0){
            salida.at<float>(i,j) = (g+1)*(imagenPasoBaja.at<float>(i,j)) - (g*imagenSalida.at<float>(i,j));
          }
        }
      }
    }else{
      //Sin mascara lo haremos de forma inmediata
      for(int i=0; i<imagen.rows; i++){
        for(int j=0; j<imagen.cols;j++){
            salida.at<float>(i,j) = ((g+1)*imagenPasoBaja.at<float>(i,j)) - (g*imagenSalida.at<float>(i,j));
        }
      }
    }

    salida.convertTo(salida, CV_8U, 255.0, 0.0);

    if(vflag==1){
      imshow("Imagen final", salida);
      imshow("Filtro Butterworth", filterSalida);
      imshow("Espectro", imagenFrecuencias);
      imshow("Espectro de imagen sin orden", imagenFrecuenciasSinOrden);
      waitKey(0);
    }

   }else{
    //Spliteamos la imagen en canales
    cvtColor(imagen, imagenHSV, CV_BGR2HSV);
    split(imagenHSV, canales);
    Mat temporal;
    canales[2].convertTo(imagenPasoBaja, CV_32F, 1.0/255.0);
    copyMakeBorder(imagenPasoBaja, padded, 0, M-imagenPasoBaja.rows, 0, N - imagenPasoBaja.cols, BORDER_CONSTANT, Scalar::all(0));
    Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
    merge(planes, 2, complexImg);

    dft(complexImg, complexImg);

    filter = complexImg.clone();

    shiftDFT(complexImg);

    butterworth(filter, r, n);
    mulSpectrums(complexImg, filter, complexImg, 0);
    shiftDFT(complexImg);

    //Falta hacer lo de poder mostrarla
    imagenFrecuencias = create_spectrum(complexImg);

    //Hacemos la inversa
    idft(complexImg, complexImg, DFT_SCALE);
    split(complexImg, planes);
    normalize(planes[0], imagenSalida, 0, 1, CV_MINMAX);
    split(filter, planes);
    normalize(planes[0], filterSalida, 0, 1, CV_MINMAX);

    Mat salida = imagen.clone();
    canales[2] = imagenPasoBaja.clone();
    if(mflag==1){
      //Con mascara
      for(int i=0; i<canales[2].rows; i++){
        for(int j=0; j<canales[2].cols;j++){
          if(mascara.at<uchar>(i,j)!=0){
            canales[2].at<float>(i,j) = ((g+1)*imagenPasoBaja.at<float>(i,j)) - (g*imagenSalida.at<float>(i,j));
          }
        }
      }
    }else{
      //Sin mascara
      for(int i=0; i<canales[2].rows; i++){
        for(int j=0; j<canales[2].cols;j++){
            canales[2].at<float>(i,j) = ((g+1)*imagenPasoBaja.at<float>(i,j)) - (g*imagenSalida.at<float>(i,j));
        }
      }
    }

    canales[2].convertTo(canales[2], CV_8U, 255.0, 0.0);
    merge(canales, salida);
    cvtColor(salida, salida, CV_HSV2BGR);

    salida.convertTo(salida, CV_8U, 255.0, 0.0);

    if(vflag==1){
      imshow("Imagen final", salida);
      imshow("Filtro Butterworth", filterSalida);
      imshow("Espectro", imagenFrecuencias);
      imshow("Espectro de imagen sin orden", imagenFrecuenciasSinOrden);
      waitKey(0);
    }


   }
   //Y escribimos la imagen a fichero
   imwrite(nombreSalida, salida);

return 0;

}
Beispiel #19
0
int main()
{
  // A gray image
  cv::Mat_<float> img = cv::imread("Image4_1.png", CV_LOAD_IMAGE_GRAYSCALE);
  // Load image
  //     cv::Mat_<float> img = cv::imread(argv[1], cv::IMREAD_GRAYSCALE);
  
  // Get original size
  int wxOrig = img.cols;
  int wyOrig = img.rows;
  
  
  int m = cv::getOptimalDFTSize( 2*wyOrig );
  int n = cv::getOptimalDFTSize( 2*wxOrig );
  
  copyMakeBorder(img, img, 0, m - wyOrig, 0, n - wxOrig, cv::BORDER_CONSTANT, cv::Scalar::all(0));
  
  // Get padded image size
  const int wx = img.cols, wy = img.rows;
  const int cx = wx/2, cy = wy/2;
  
  std::cout << wxOrig << " " << wyOrig << std::endl;
  std::cout << wx << " " << wy << std::endl;
  std::cout << cx << " " << cy << std::endl;
  
  // Compute DFT of image
  cv::Mat_<float> imgs[] = {img.clone(), cv::Mat_<float>::zeros(wy, wx)};
  cv::Mat_<cv::Vec2f> img_dft;
  cv::merge(imgs, 2, img_dft);
  cv::dft(img_dft, img_dft);
  
  // Shift to center
  dftshift(img_dft);
  
  // Used for visualization only
  cv::Mat_<float> magnitude, phase;
  cv::split(img_dft, imgs);
  cv::cartToPolar(imgs[0], imgs[1], magnitude, phase);
  magnitude = magnitude + 1.0f;
  cv::log(magnitude, magnitude);
  cv::normalize(magnitude, magnitude, 0, 1, CV_MINMAX);
  cv::imwrite("img_dft.png", magnitude * 255);
  //             cv::imshow("img_dft", magnitude);
  
  // Create a Butterworth low-pass filter of order n and diameter d0 in the frequency domain
  cv::Mat lpf = BLPF(100, 2, wy, wx, cx, cy);
  cv::Mat bsf = BBSF(2, wy, wx, cx, cy);
  cv::Mat nf = BNF(2, wy, wx, cx, cy);
  // Multiply and shift back
  cv::mulSpectrums(nf, img_dft, img_dft, cv::DFT_ROWS);

  dftshift(img_dft);
  
  //Display high pass filter
  cv::Mat realImg[2];
  cv::split(nf,realImg);
  cv::Mat realNF = realImg[0];
  cv::normalize(realNF, realNF, 0.0, 1.0, CV_MINMAX);
  // 	namedWindow("", cv::WINDOW_NORMAL);
  cv::imwrite("NF.png", realNF);
  
  
  
  //----- Compute IDFT of HPF filtered image
  
  //you can do this
  //cv::idft(img_dft, img_dft); //the result is a 2 channel image
  //Mat output;
  // therefore you split it and get the real one
  //split(img_dft, imgs);
  //normalize(imgs[0], output, 0, 1, CV_MINMAX);
  
  //or you can do like this, then you dont need to split
  cv::Mat_<float> output;
  cv::dft(img_dft, output, cv::DFT_INVERSE| cv::DFT_REAL_OUTPUT);
  cv::Mat_<float> croppedOutput(output,cv::Rect(0,0,wxOrig,wyOrig));
  
  cv::normalize(output, output, 0, 1, CV_MINMAX);
  cv::normalize(img, img, 0.0, 1.0, CV_MINMAX);
  
  // 	namedWindow("", cv::WINDOW_NORMAL);
  //     cv::imshow("Input", img);
  cv::imwrite("out.png", croppedOutput * 255);
  // 	namedWindow("", cv::WINDOW_NORMAL);
  //     cv::imshow("High-pass filtered input", croppedOutput);
  cv::waitKey();
  return 0;
  return 0;
}
void jointColorDepthFillOcclusion_(const Mat& src, const Mat& guide, Mat& dest, const Size ksize, T threshold)
{
	if(dest.empty())dest.create(src.size(),src.type());
	Mat sim,gim;
	const int radiusw = ksize.width/2;
	const int radiush = ksize.height/2;;
	copyMakeBorder(src, sim, radiush, radiush, radiusw, radiusw,cv::BORDER_DEFAULT);
	copyMakeBorder(guide, gim, radiush, radiush, radiusw, radiusw,cv::BORDER_DEFAULT);

	vector<int> _space_ofs_before(ksize.area());
	int* space_ofs_before = &_space_ofs_before[0];

	int maxk=0;
	for(int i = -radiush; i <= radiush; i++ )
	{
		for(int j = -radiusw; j <= radiusw; j++ )
		{
			double r = std::sqrt((double)i*i + (double)j*j);
			if( r > radiusw )
				continue;

			space_ofs_before[maxk++] = (int)(i*sim.cols + j);
		}
	}
	const int steps = sim.cols;
	const int step = dest.cols;

	T* sptr = sim.ptr<T>(radiush);sptr+=radiusw;
	uchar* jptr = gim.ptr<uchar>(radiush);jptr+=radiusw;

	T* dst = dest.ptr<T>(0);

	T th2 = threshold*threshold;
	for(int i = 0; i < src.rows; i++ )
	{
		for(int j = 0; j < src.cols; j++ )
		{
			const T val0j = jptr[j];

			int minv=INT_MAX;
			T mind=0;
			if(sptr[j]==0)
			{
				for(int k = 0; k < maxk; k++ )
				{
					if(sptr[j + space_ofs_before[k]]==0) continue;

					const T valj = jptr[j + space_ofs_before[k]];
					int ab=(int)((valj-val0j)*(valj-val0j));
					if(ab<minv)
					{
						minv=ab;
						mind= sptr[j + space_ofs_before[k]];
					}
				}
				if(minv<th2)
				{
					dst[j]=mind;
				}
			}
		}
		sptr+=steps;
		jptr+=steps;
		dst+=step;
	}
}
Beispiel #21
0
static bool convolve_dft(InputArray _image, InputArray _templ, OutputArray _result)
{
    ConvolveBuf buf;
    CV_Assert(_image.type() == CV_32F);
    CV_Assert(_templ.type() == CV_32F);

    buf.create(_image.size(), _templ.size());
    _result.create(buf.result_size, CV_32F);

    UMat image  = _image.getUMat();
    UMat templ  = _templ.getUMat();

    UMat result = _result.getUMat();

    Size& block_size = buf.block_size;
    Size& dft_size = buf.dft_size;

    UMat& image_block = buf.image_block;
    UMat& templ_block = buf.templ_block;
    UMat& result_data = buf.result_data;

    UMat& image_spect = buf.image_spect;
    UMat& templ_spect = buf.templ_spect;
    UMat& result_spect = buf.result_spect;

    UMat templ_roi = templ;
    copyMakeBorder(templ_roi, templ_block, 0, templ_block.rows - templ_roi.rows, 0,
                   templ_block.cols - templ_roi.cols, BORDER_ISOLATED);

    dft(templ_block, templ_spect, 0, templ.rows);

    // Process all blocks of the result matrix
    for (int y = 0; y < result.rows; y += block_size.height)
    {
        for (int x = 0; x < result.cols; x += block_size.width)
        {
            Size image_roi_size(std::min(x + dft_size.width, image.cols) - x,
                                std::min(y + dft_size.height, image.rows) - y);
            Rect roi0(x, y, image_roi_size.width, image_roi_size.height);

            UMat image_roi(image, roi0);

            copyMakeBorder(image_roi, image_block, 0, image_block.rows - image_roi.rows,
                           0, image_block.cols - image_roi.cols, BORDER_ISOLATED);

            dft(image_block, image_spect, 0);

            mulSpectrums(image_spect, templ_spect, result_spect, 0, true);

            dft(result_spect, result_data, cv::DFT_INVERSE | cv::DFT_REAL_OUTPUT | cv::DFT_SCALE);

            Size result_roi_size(std::min(x + block_size.width, result.cols) - x,
                                 std::min(y + block_size.height, result.rows) - y);

            Rect roi1(x, y, result_roi_size.width, result_roi_size.height);
            Rect roi2(0, 0, result_roi_size.width, result_roi_size.height);

            UMat result_roi(result, roi1);
            UMat result_block(result_data, roi2);

            result_block.copyTo(result_roi);
        }
    }
    return true;
}
Beispiel #22
0
/*----------------------------
 * 功能 : 基于 BM 算法计算视差
 *----------------------------
 * 函数 : StereoMatch::bmMatch
 * 访问 : public 
 * 返回 : 0 - 失败,1 - 成功
 *
 * 参数 : frameLeft		[in]	左摄像机帧图
 * 参数 : frameRight		[in]	右摄像机帧图
 * 参数 : disparity		[out]	视差图
 * 参数 : imageLeft		[out]	处理后的左视图,用于显示
 * 参数 : imageRight		[out]	处理后的右视图,用于显示
 */
int StereoMatch::bmMatch(cv::Mat& frameLeft, cv::Mat& frameRight, cv::Mat& disparity, cv::Mat& imageLeft, cv::Mat& imageRight)
{
	// 输入检查
	if (frameLeft.empty() || frameRight.empty())
	{
		disparity = cv::Scalar(0);
		return 0;
	}
	if (m_frameWidth == 0 || m_frameHeight == 0)
	{
		if (init(frameLeft.cols, frameLeft.rows, "calib_paras.xml"/*待改为由本地设置文件确定*/) == 0)	//执行类初始化
		{
			return 0;
		}
	}

	// 转换为灰度图
	cv::Mat img1proc, img2proc;
	cvtColor(frameLeft, img1proc, CV_BGR2GRAY);
	cvtColor(frameRight, img2proc, CV_BGR2GRAY);

	// 校正图像,使左右视图行对齐	
	cv::Mat img1remap, img2remap;
	if (m_Calib_Data_Loaded)
	{
		remap(img1proc, img1remap, m_Calib_Mat_Remap_X_L, m_Calib_Mat_Remap_Y_L, cv::INTER_LINEAR);		// 对用于视差计算的画面进行校正
		remap(img2proc, img2remap, m_Calib_Mat_Remap_X_R, m_Calib_Mat_Remap_Y_R, cv::INTER_LINEAR);
	} 
	else
	{
		img1remap = img1proc;
		img2remap = img2proc;
	}

	// 对左右视图的左边进行边界延拓,以获取与原始视图相同大小的有效视差区域
	cv::Mat img1border, img2border;
	if (m_numberOfDisparies != m_BM.state->numberOfDisparities)
		m_numberOfDisparies = m_BM.state->numberOfDisparities;
	copyMakeBorder(img1remap, img1border, 0, 0, m_BM.state->numberOfDisparities, 0, IPL_BORDER_REPLICATE);
	copyMakeBorder(img2remap, img2border, 0, 0, m_BM.state->numberOfDisparities, 0, IPL_BORDER_REPLICATE);

	// 计算视差
	cv::Mat dispBorder;
	m_BM(img1border, img2border, dispBorder);

	// 截取与原始画面对应的视差区域(舍去加宽的部分)
	cv::Mat disp;
	disp = dispBorder.colRange(m_BM.state->numberOfDisparities, img1border.cols);	
	disp.copyTo(disparity, m_Calib_Mat_Mask_Roi);

	// 输出处理后的图像
	if (m_Calib_Data_Loaded)
		remap(frameLeft, imageLeft, m_Calib_Mat_Remap_X_L, m_Calib_Mat_Remap_Y_L, cv::INTER_LINEAR);
	else
		frameLeft.copyTo(imageLeft);
	rectangle(imageLeft, m_Calib_Roi_L, CV_RGB(0,0,255), 3);

	if (m_Calib_Data_Loaded)
		remap(frameRight, imageRight, m_Calib_Mat_Remap_X_R, m_Calib_Mat_Remap_Y_R, cv::INTER_LINEAR);
	else
		frameRight.copyTo(imageRight);
	rectangle(imageRight, m_Calib_Roi_R, CV_RGB(0,0,255), 3);

	return 1;
}
Beispiel #23
0
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);
                }
            }
        }
    }
}
Beispiel #24
0
Point2d phaseCorrelate(InputArray _src1, InputArray _src2, InputArray _window, double* response)
{
    Mat src1 = _src1.getMat();
    Mat src2 = _src2.getMat();
    Mat window = _window.getMat();

    CV_Assert( src1.type() == src2.type());
    CV_Assert( src1.type() == CV_32FC1 || src1.type() == CV_64FC1 );
    CV_Assert( src1.size == src2.size);

    if(!window.empty())
    {
        CV_Assert( src1.type() == window.type());
        CV_Assert( src1.size == window.size);
    }

    int M = getOptimalDFTSize(src1.rows);
    int N = getOptimalDFTSize(src1.cols);

    Mat padded1, padded2, paddedWin;

    if(M != src1.rows || N != src1.cols)
    {
        copyMakeBorder(src1, padded1, 0, M - src1.rows, 0, N - src1.cols, BORDER_CONSTANT, Scalar::all(0));
        copyMakeBorder(src2, padded2, 0, M - src2.rows, 0, N - src2.cols, BORDER_CONSTANT, Scalar::all(0));

        if(!window.empty())
        {
            copyMakeBorder(window, paddedWin, 0, M - window.rows, 0, N - window.cols, BORDER_CONSTANT, Scalar::all(0));
        }
    }
    else
    {
        padded1 = src1;
        padded2 = src2;
        paddedWin = window;
    }



    // perform window multiplication if available
    if(!paddedWin.empty())
    {
        // apply window to both images before proceeding...
        multiply(paddedWin, padded1, padded1);
        multiply(paddedWin, padded2, padded2);
    }

    // execute phase correlation equation
    // Reference: http://en.wikipedia.org/wiki/Phase_correlation
    cv::Mat FFT1, FFT2;
    dft(padded1, FFT1, DFT_COMPLEX_OUTPUT);
    dft(padded2, FFT2, DFT_COMPLEX_OUTPUT);

//    // high-pass filter
//    cv::Mat hpFilter = 1-paddedWin;
//    phasecorrelation::fftShift(hpFilter);
//    for(int i=0; i<paddedWin.rows; i++){
//        for(int j=0; j<paddedWin.cols; j++){
//            FFT1.at<cv::Vec2f>(i,j) *= hpFilter.at<float>(i,j);
//            FFT2.at<cv::Vec2f>(i,j) *= hpFilter.at<float>(i,j);
//        }
//    }

    cv::Mat P;
    cv::mulSpectrums(FFT1, FFT2, P, DFT_COMPLEX_OUTPUT, true);

    cv::Mat Pm(P.size(), CV_32F);
    // NOTE: memleak in magSpectrums when using it with complex output!
    //phasecorrelation::magSpectrums(P, Pm);
    for(int i=0; i<P.rows; i++){
        for(int j=0; j<P.cols; j++){
            cv::Vec2f e = P.at<cv::Vec2f>(i, j);
            Pm.at<float>(i, j) = cv::sqrt(e[0]*e[0] + e[1]*e[1]);
        }
    }

    //phasecorrelation::divSpectrums(P, Pm, C, 0, false); // FF* / |FF*| (phase correlation equation completed here...)
    for(int i=0; i<P.rows; i++){
        for(int j=0; j<P.cols; j++){
            P.at<cv::Vec2f>(i, j) /= (Pm.at<float>(i, j) + DBL_EPSILON);
        }
    }

    cv::Mat C(P.size(), CV_32F);
    cv::dft(P, C, cv::DFT_INVERSE + cv::DFT_REAL_OUTPUT);

    phasecorrelation::fftShift(C); // shift the energy to the center of the frame.

 //cvtools::writeMat(C, "C.mat", "C");

    // locate the highest peak
    Point peakLoc;
    minMaxLoc(C, NULL, NULL, NULL, &peakLoc);

    // get the phase shift with sub-pixel accuracy, 5x5 window seems about right here...
    Point2d t = phasecorrelation::weightedCentroid(C, peakLoc, Size(3, 3), response);

    // max response is M*N (not exactly, might be slightly larger due to rounding errors)
    if(response)
        *response /= M*N;

    // adjust shift relative to image center...
    Point2d center((double)padded1.cols / 2.0, (double)padded1.rows / 2.0);


    return (center - t);
}
Beispiel #25
0
void MultiBandBlender::feed(InputArray _img, InputArray mask, Point tl)
{
#if ENABLE_LOG
    int64 t = getTickCount();
#endif

    UMat img = _img.getUMat();
    CV_Assert(img.type() == CV_16SC3 || img.type() == CV_8UC3);
    CV_Assert(mask.type() == CV_8U);

    // Keep source image in memory with small border
    int gap = 3 * (1 << num_bands_);
    Point tl_new(std::max(dst_roi_.x, tl.x - gap),
                 std::max(dst_roi_.y, tl.y - gap));
    Point br_new(std::min(dst_roi_.br().x, tl.x + img.cols + gap),
                 std::min(dst_roi_.br().y, tl.y + img.rows + gap));

    // Ensure coordinates of top-left, bottom-right corners are divided by (1 << num_bands_).
    // After that scale between layers is exactly 2.
    //
    // We do it to avoid interpolation problems when keeping sub-images only. There is no such problem when
    // image is bordered to have size equal to the final image size, but this is too memory hungry approach.
    tl_new.x = dst_roi_.x + (((tl_new.x - dst_roi_.x) >> num_bands_) << num_bands_);
    tl_new.y = dst_roi_.y + (((tl_new.y - dst_roi_.y) >> num_bands_) << num_bands_);
    int width = br_new.x - tl_new.x;
    int height = br_new.y - tl_new.y;
    width += ((1 << num_bands_) - width % (1 << num_bands_)) % (1 << num_bands_);
    height += ((1 << num_bands_) - height % (1 << num_bands_)) % (1 << num_bands_);
    br_new.x = tl_new.x + width;
    br_new.y = tl_new.y + height;
    int dy = std::max(br_new.y - dst_roi_.br().y, 0);
    int dx = std::max(br_new.x - dst_roi_.br().x, 0);
    tl_new.x -= dx; br_new.x -= dx;
    tl_new.y -= dy; br_new.y -= dy;

    int top = tl.y - tl_new.y;
    int left = tl.x - tl_new.x;
    int bottom = br_new.y - tl.y - img.rows;
    int right = br_new.x - tl.x - img.cols;

    // Create the source image Laplacian pyramid
    UMat img_with_border;
    copyMakeBorder(_img, img_with_border, top, bottom, left, right,
                   BORDER_REFLECT);
    LOGLN("  Add border to the source image, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
#if ENABLE_LOG
    t = getTickCount();
#endif

    std::vector<UMat> src_pyr_laplace;
    if (can_use_gpu_ && img_with_border.depth() == CV_16S)
        createLaplacePyrGpu(img_with_border, num_bands_, src_pyr_laplace);
    else
        createLaplacePyr(img_with_border, num_bands_, src_pyr_laplace);

    LOGLN("  Create the source image Laplacian pyramid, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
#if ENABLE_LOG
    t = getTickCount();
#endif

    // Create the weight map Gaussian pyramid
    UMat weight_map;
    std::vector<UMat> weight_pyr_gauss(num_bands_ + 1);

    if(weight_type_ == CV_32F)
    {
        mask.getUMat().convertTo(weight_map, CV_32F, 1./255.);
    }
    else // weight_type_ == CV_16S
    {
        mask.getUMat().convertTo(weight_map, CV_16S);
        UMat add_mask;
        compare(mask, 0, add_mask, CMP_NE);
        add(weight_map, Scalar::all(1), weight_map, add_mask);
    }

    copyMakeBorder(weight_map, weight_pyr_gauss[0], top, bottom, left, right, BORDER_CONSTANT);

    for (int i = 0; i < num_bands_; ++i)
        pyrDown(weight_pyr_gauss[i], weight_pyr_gauss[i + 1]);

    LOGLN("  Create the weight map Gaussian pyramid, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
#if ENABLE_LOG
    t = getTickCount();
#endif

    int y_tl = tl_new.y - dst_roi_.y;
    int y_br = br_new.y - dst_roi_.y;
    int x_tl = tl_new.x - dst_roi_.x;
    int x_br = br_new.x - dst_roi_.x;

    // Add weighted layer of the source image to the final Laplacian pyramid layer
    for (int i = 0; i <= num_bands_; ++i)
    {
        Rect rc(x_tl, y_tl, x_br - x_tl, y_br - y_tl);
#ifdef HAVE_OPENCL
        if ( !cv::ocl::useOpenCL() ||
             !ocl_MultiBandBlender_feed(src_pyr_laplace[i], weight_pyr_gauss[i],
                    dst_pyr_laplace_[i](rc), dst_band_weights_[i](rc)) )
#endif
        {
            Mat _src_pyr_laplace = src_pyr_laplace[i].getMat(ACCESS_READ);
            Mat _dst_pyr_laplace = dst_pyr_laplace_[i](rc).getMat(ACCESS_RW);
            Mat _weight_pyr_gauss = weight_pyr_gauss[i].getMat(ACCESS_READ);
            Mat _dst_band_weights = dst_band_weights_[i](rc).getMat(ACCESS_RW);
            if(weight_type_ == CV_32F)
            {
                for (int y = 0; y < rc.height; ++y)
                {
                    const Point3_<short>* src_row = _src_pyr_laplace.ptr<Point3_<short> >(y);
                    Point3_<short>* dst_row = _dst_pyr_laplace.ptr<Point3_<short> >(y);
                    const float* weight_row = _weight_pyr_gauss.ptr<float>(y);
                    float* dst_weight_row = _dst_band_weights.ptr<float>(y);

                    for (int x = 0; x < rc.width; ++x)
                    {
                        dst_row[x].x += static_cast<short>(src_row[x].x * weight_row[x]);
                        dst_row[x].y += static_cast<short>(src_row[x].y * weight_row[x]);
                        dst_row[x].z += static_cast<short>(src_row[x].z * weight_row[x]);
                        dst_weight_row[x] += weight_row[x];
                    }
                }
            }
            else // weight_type_ == CV_16S
            {
                for (int y = 0; y < y_br - y_tl; ++y)
                {
                    const Point3_<short>* src_row = _src_pyr_laplace.ptr<Point3_<short> >(y);
                    Point3_<short>* dst_row = _dst_pyr_laplace.ptr<Point3_<short> >(y);
                    const short* weight_row = _weight_pyr_gauss.ptr<short>(y);
                    short* dst_weight_row = _dst_band_weights.ptr<short>(y);

                    for (int x = 0; x < x_br - x_tl; ++x)
                    {
                        dst_row[x].x += short((src_row[x].x * weight_row[x]) >> 8);
                        dst_row[x].y += short((src_row[x].y * weight_row[x]) >> 8);
                        dst_row[x].z += short((src_row[x].z * weight_row[x]) >> 8);
                        dst_weight_row[x] += weight_row[x];
                    }
                }
            }
        }
#ifdef HAVE_OPENCL
        else
        {
Beispiel #26
0
// ============================================================================
//for drawing examples see
//  http://opencvexamples.blogspot.com/2013/10/basic-drawing-examples.html
void VideoReader::nextFrame() {
  //
  if (!playingOptions.playing) {
    return;
  }

  Mat inputFrame;
  if (!capture.read(inputFrame)) {
    emit finished() ;
    return;
  }

  int gfw = inputFrame.cols;
  int gfh = inputFrame.rows;
  float scaleFactor =1;
  if ( (inputFrame.cols>playingOptions.guiFrameWidth) ||
       (inputFrame.rows>playingOptions.guiFrameHeight) ) {
    if (playingOptions.guiFrameWidth > playingOptions.guiFrameHeight) {
      gfw = playingOptions.guiFrameWidth ;
      scaleFactor = (playingOptions.guiFrameWidth*1.0)/inputFrame.cols ;
      gfh = (int)round(inputFrame.rows*scaleFactor) ;
    }
    else {
      gfh = playingOptions.guiFrameHeight ;
      scaleFactor = (playingOptions.guiFrameHeight*1.0)/inputFrame.rows ;
      gfw = (int)round(inputFrame.cols*scaleFactor) ;
    }
  }

//  c5d(c5, QString("Calculated scale from %1x%2 to %3x%4 (%5)")
//                 .arg(inputFrame.cols).arg(inputFrame.rows)
//                 .arg(playingOptions.guiFrameWidth).arg(playingOptions.guiFrameHeight)
//                 .arg(scaleFactor) ) ;

  resize(inputFrame, frame, Size(gfw, gfh) );
  drawCornerCircles();

  switch (playingOptions.crosshairType) {
  case 0 :
    drawCrosshairType1(scaleFactor);
    break;
  case 1 :
    drawCrosshairType2(scaleFactor);
    break;
  case 2 :
    drawCrosshairType3(scaleFactor);
    break;
  }

  //
  drawSelectorRectangle(scaleFactor);
  drawFilename(scaleFactor);

  Mat fullFrame = Mat::zeros(playingOptions.guiFrameWidth, playingOptions.guiFrameHeight, CV_8UC3);  
  const int topShift = (playingOptions.guiFrameHeight-frame.rows) /2 ;
  const int lowShift = playingOptions.guiFrameHeight - topShift - frame.rows;  
//  copyMakeBorder(frame, fullFrame, topShift, lowShift, 0,0,BORDER_REPLICATE );
  copyMakeBorder(frame, fullFrame, topShift, lowShift, 0,0,BORDER_CONSTANT, Scalar( 128, 128, 0 ) );
  frame =  fullFrame;

  if (frame.channels()== 3){
    cv::cvtColor(frame, RGBframe, CV_BGR2RGB);
    img = QImage((const unsigned char*)(RGBframe.data),
                 RGBframe.cols,RGBframe.rows, RGBframe.step, QImage::Format_RGB888);
    }
    else {
      img = QImage((const unsigned char*)(frame.data),
                   frame.cols,frame.rows,QImage::Format_Indexed8);
    }

  emit processedImage(img);
}
Beispiel #27
0
static Mat inverseAndWiener(Mat& s, Mat& p, double snr, bool inverse) {

	const bool wiener = !inverse;

	// Pad input image to avoid ringing artifacts along image borders.
	int bH = p.cols;
	int bV = p.rows;
	Mat sBorder;
	copyMakeBorder(s, sBorder, bV, bV, bH, bH, BORDER_REPLICATE);

	// Allocate some memory like it is going out of style.
	Mat pBigShifted = Mat::zeros(sBorder.size(), CV_32F);
	Mat P = Mat::zeros(sBorder.size(), CV_32F);
	Mat S = Mat::zeros(sBorder.size(), CV_32F);
	Mat OApprox = Mat::zeros(sBorder.size(), CV_32F);
	Mat oApprox = Mat::zeros(sBorder.size(), CV_32F);

	// Shift kernel.
	const int pHalf = p.rows / 2;
	circShiftXXX(p, pBigShifted, -pHalf, -pHalf);

	// Transform shifted kernel and degrated input image into frequency domain.
	// Note: DFT_COMPLEX_OUTPUT means that we want the complex result to be stored
	//       in a two-channel matrix as opposed to the default compressed output.
	dft(pBigShifted, P, DFT_COMPLEX_OUTPUT);
	dft(sBorder, S, DFT_COMPLEX_OUTPUT);

	if (inverse) {
		const double epsilon = 0.05f;

		// Remove frequencies whose magnitude is below epsilon * max(freqKernel magnitude).
		double maxMagnitude;
		minMaxLoc(abs(P), 0, &maxMagnitude);

		const double threshold =  maxMagnitude * epsilon;
		for (int ri = 0; ri < P.rows; ri++) {
			for (int ci = 0; ci < P.cols; ci++) {
				if (norm(P.at<Vec2f>(ri, ci)) < threshold) {
					P.at<Vec2f>(ri, ci) = threshold;
				}
			}
		}
	}

	// OpenCV only provides a multiplication operation for complex matrices, so we need
	// to calculate the inverse (1/H) of our filter spectrum first. Since it is complex
	// we need to compute 1/H = H*/(HH*) = H*/(Re(H)^2+Im(H)^2), where H* -> complex conjugate of H.

	// Multiply spectrum of the degrated image with the complex conjugate of the frequency spectrum
	// of the filter.
	const bool conjFreqKernel = true;
	mulSpectrums(S, P, OApprox, DFT_COMPLEX_OUTPUT, conjFreqKernel); // I * H*

	// Split kernel spectrum into real and imaginary parts.
	Mat PChannels[] = {Mat::zeros(sBorder.size(), CV_32F), Mat::zeros(sBorder.size(), CV_32F)};
	split(P, PChannels); // 0:real, 1:imaginary

	// Calculate squared magnitude (Re(H)^2 + Im(H)^2) of filter spectrum.
	Mat freqKernelSqMagnitude = Mat::zeros(sBorder.rows, sBorder.cols, CV_32F);
	magnitude(PChannels[0], PChannels[1], freqKernelSqMagnitude); // freqKernelSqMagnitude = magnitude
	pow(PChannels[0], 2, freqKernelSqMagnitude); // freqKernelSqMagnitude = magnitude^2 = Re(H)^2 + Im(H)^2

	if (wiener) {
		// Add 1 / SNR^2 to the squared filter kernel magnitude.
		freqKernelSqMagnitude += 1 / pow(snr, 2.0);
	}

	// Split frequency spectrum of degradedPadded image into real and imaginary parts.
	Mat OApproxChannels[] = {Mat::zeros(sBorder.size(), CV_32FC1), Mat::zeros(sBorder.size(), CV_32F)};
	split(OApprox, OApproxChannels);

	// Divide each plane by the squared magnitude of the kernel frequency spectrum.
	// What we have done up to this point: (I * H*) / (Re(H)^2 + Im(H)^2) = I/H
	divide(OApproxChannels[0], freqKernelSqMagnitude, OApproxChannels[0]); // Re(I) / (Re(H)^2 + Im(H)^2)
	divide(OApproxChannels[1], freqKernelSqMagnitude, OApproxChannels[1]); // Im(I) / (Re(H)^2 + Im(H)^2)

	// Merge real and imaginary parts of the image frequency spectrum.
	merge(OApproxChannels, 2, OApprox);

	// Inverse DFT.
	// Note: DFT_REAL_OUTPUT means that we want the output to be a one-channel matrix again.
	dft(OApprox, oApprox, DFT_INVERSE | DFT_SCALE | DFT_REAL_OUTPUT);

	// Crop output image to original size.
	oApprox = oApprox(Rect(bH, bV, oApprox.cols - (bH * 2), oApprox.rows - (bV * 2)));

	return oApprox;
}
Beispiel #28
0
void MultiBandBlender::feed(const Mat &img, const Mat &mask, Point tl)
{
    CV_Assert(img.type() == CV_16SC3 || img.type() == CV_8UC3);
    CV_Assert(mask.type() == CV_8U);

    // Keep source image in memory with small border
    int gap = 3 * (1 << num_bands_);
    Point tl_new(std::max(dst_roi_.x, tl.x - gap),
                 std::max(dst_roi_.y, tl.y - gap));
    Point br_new(std::min(dst_roi_.br().x, tl.x + img.cols + gap),
                 std::min(dst_roi_.br().y, tl.y + img.rows + gap));

    // Ensure coordinates of top-left, bottom-right corners are divided by (1 << num_bands_).
    // After that scale between layers is exactly 2.
    //
    // We do it to avoid interpolation problems when keeping sub-images only. There is no such problem when
    // image is bordered to have size equal to the final image size, but this is too memory hungry approach.
    tl_new.x = dst_roi_.x + (((tl_new.x - dst_roi_.x) >> num_bands_) << num_bands_);
    tl_new.y = dst_roi_.y + (((tl_new.y - dst_roi_.y) >> num_bands_) << num_bands_);
    int width = br_new.x - tl_new.x;
    int height = br_new.y - tl_new.y;
    width += ((1 << num_bands_) - width % (1 << num_bands_)) % (1 << num_bands_);
    height += ((1 << num_bands_) - height % (1 << num_bands_)) % (1 << num_bands_);
    br_new.x = tl_new.x + width;
    br_new.y = tl_new.y + height;
    int dy = std::max(br_new.y - dst_roi_.br().y, 0);
    int dx = std::max(br_new.x - dst_roi_.br().x, 0);
    tl_new.x -= dx; br_new.x -= dx;
    tl_new.y -= dy; br_new.y -= dy;

    int top = tl.y - tl_new.y;
    int left = tl.x - tl_new.x;
    int bottom = br_new.y - tl.y - img.rows;
    int right = br_new.x - tl.x - img.cols;

    // Create the source image Laplacian pyramid
    Mat img_with_border;
    copyMakeBorder(img, img_with_border, top, bottom, left, right,
                   BORDER_REFLECT);
    std::vector<Mat> src_pyr_laplace;
    if (can_use_gpu_ && img_with_border.depth() == CV_16S)
        createLaplacePyrGpu(img_with_border, num_bands_, src_pyr_laplace);
    else
        createLaplacePyr(img_with_border, num_bands_, src_pyr_laplace);

    // Create the weight map Gaussian pyramid
    Mat weight_map;
    std::vector<Mat> weight_pyr_gauss(num_bands_ + 1);

    if(weight_type_ == CV_32F)
    {
        mask.convertTo(weight_map, CV_32F, 1./255.);
    }
    else// weight_type_ == CV_16S
    {
        mask.convertTo(weight_map, CV_16S);
        add(weight_map, 1, weight_map, mask != 0);
    }

    copyMakeBorder(weight_map, weight_pyr_gauss[0], top, bottom, left, right, BORDER_CONSTANT);

    for (int i = 0; i < num_bands_; ++i)
        pyrDown(weight_pyr_gauss[i], weight_pyr_gauss[i + 1]);

    int y_tl = tl_new.y - dst_roi_.y;
    int y_br = br_new.y - dst_roi_.y;
    int x_tl = tl_new.x - dst_roi_.x;
    int x_br = br_new.x - dst_roi_.x;

    // Add weighted layer of the source image to the final Laplacian pyramid layer
    if(weight_type_ == CV_32F)
    {
        for (int i = 0; i <= num_bands_; ++i)
        {
            for (int y = y_tl; y < y_br; ++y)
            {
                int y_ = y - y_tl;
                const Point3_<short>* src_row = src_pyr_laplace[i].ptr<Point3_<short> >(y_);
                Point3_<short>* dst_row = dst_pyr_laplace_[i].ptr<Point3_<short> >(y);
                const float* weight_row = weight_pyr_gauss[i].ptr<float>(y_);
                float* dst_weight_row = dst_band_weights_[i].ptr<float>(y);

                for (int x = x_tl; x < x_br; ++x)
                {
                    int x_ = x - x_tl;
                    dst_row[x].x += static_cast<short>(src_row[x_].x * weight_row[x_]);
                    dst_row[x].y += static_cast<short>(src_row[x_].y * weight_row[x_]);
                    dst_row[x].z += static_cast<short>(src_row[x_].z * weight_row[x_]);
                    dst_weight_row[x] += weight_row[x_];
                }
            }
            x_tl /= 2; y_tl /= 2;
            x_br /= 2; y_br /= 2;
        }
    }
    else// weight_type_ == CV_16S
    {
        for (int i = 0; i <= num_bands_; ++i)
        {
            for (int y = y_tl; y < y_br; ++y)
            {
                int y_ = y - y_tl;
                const Point3_<short>* src_row = src_pyr_laplace[i].ptr<Point3_<short> >(y_);
                Point3_<short>* dst_row = dst_pyr_laplace_[i].ptr<Point3_<short> >(y);
                const short* weight_row = weight_pyr_gauss[i].ptr<short>(y_);
                short* dst_weight_row = dst_band_weights_[i].ptr<short>(y);

                for (int x = x_tl; x < x_br; ++x)
                {
                    int x_ = x - x_tl;
                    dst_row[x].x += short((src_row[x_].x * weight_row[x_]) >> 8);
                    dst_row[x].y += short((src_row[x_].y * weight_row[x_]) >> 8);
                    dst_row[x].z += short((src_row[x_].z * weight_row[x_]) >> 8);
                    dst_weight_row[x] += weight_row[x_];
                }
            }
            x_tl /= 2; y_tl /= 2;
            x_br /= 2; y_br /= 2;
        }
    }
}