Esempio n. 1
0
File: dip3.cpp Progetto: hoijui/DIP
/*
Performes a convolution by multiplication in frequency domain
in		input image
kernel		filter kernel
return		output image
*/
Mat frequencyConvolution(Mat& in, Mat& kernel) {

	const int kw = kernel.cols;
	const int kh = kernel.rows;

	Mat kernelBig = Mat::zeros(in.size(), in.type());
	for (int x = 0; x < kw; ++x) {
		for (int y = 0; y < kh; ++y) {
			kernelBig.at<float>(x, y) = kernel.at<float>(x, y);
		}
	}
	Mat kernelBigShifted = circShift(kernelBig, -(kw/2), -(kh/2));

	// transform into frequency domain
	Mat freqIn = Mat(in.size(), CV_32FC2); // complex
	Mat freqKernel = Mat(kernelBigShifted.size(), CV_32FC2); // complex
	dft(in, freqIn);
	dft(kernelBigShifted, freqKernel);

	// multiply in frequency domain (-> convolute in spatial domain)
	Mat freqRes = Mat(kernelBig.size(), CV_32FC2); // complex
	mulSpectrums(freqIn, freqKernel, freqRes, 0);

	// transform back into spatial domain
	Mat res(in.size(), in.type());
	dft(freqRes, res, DFT_INVERSE | DFT_SCALE);

	return res;
}
Esempio n. 2
0
        static std::shared_ptr<FeatureChannels_> mulSpectrumsFeatures(const cv::Mat& Af,
                const std::shared_ptr<FeatureChannels_>& Bf,
                bool conjBf = false) {
            std::shared_ptr<FeatureChannels_> resf(new FeatureChannels_());

            for (int i = 0; i < NUMBER_OF_CHANNELS; ++i)
            { mulSpectrums(Af, Bf->channels[i], resf->channels[i], 0, conjBf); }

            return resf;
        }
Esempio n. 3
0
void ImageViewer::on_actionDFT_triggered()
{
    cv::Mat cvMat = ASM::QPixmapToCvMat(QPixmap::fromImage(*image));
    cv::Mat grayscaleMat (cvMat.size(), CV_8U);
    cv::cvtColor( cvMat, grayscaleMat, CV_BGR2GRAY );

    int width = grayscaleMat.cols;
    int height = grayscaleMat.rows;

    cv::Mat cvMat_dft =  computeDFT(grayscaleMat);
    cv::Mat magI;
    updateMag(cvMat_dft,magI);


    //Mat mask = createBoxMask(cvMat_dft.size(), cvMat_dft.cols/2, cvMat_dft.rows/2,cvMat_dft.cols/8,cvMat_dft.rows/8, true);
    Mat mask = createGausFilterMask(cvMat_dft.size(), cvMat_dft.cols/2, cvMat_dft.rows/2,cvMat_dft.cols/2,cvMat_dft.rows/2, true, true);
    std::cout << "before mul spect  " << grayscaleMat.size() << "   " << cvMat_dft.size() << "  " <<  "  " << mask.size() << std::endl;

    shift(mask);

    Mat planes[] = {Mat::zeros(cvMat_dft.size(), CV_32F), Mat::zeros(cvMat_dft.size(), CV_32F)};
    Mat kernel_spec;
    planes[0] = mask; // real
    planes[1] = mask; // imaginar

    merge(planes, 2, kernel_spec);

    mulSpectrums(cvMat_dft, kernel_spec, cvMat_dft , DFT_ROWS); // only DFT_ROWS accepted
    cv::Mat magI2;
    updateMag(cvMat_dft,magI2);		// show spectrum


    cv::Mat inverseTransform;
    cv::dft(cvMat_dft,inverseTransform,cv::DFT_INVERSE|cv::DFT_REAL_OUTPUT);
    normalize(inverseTransform, inverseTransform, 0, 255, CV_MINMAX);
    cv::Mat finalImage = inverseTransform;
    if(width <inverseTransform.cols || height<inverseTransform.rows) {
        finalImage = inverseTransform(Rect(0,0,width,height));
    }
    // Back to 8-bits
    cv::Mat finalImage2;
    finalImage.convertTo(finalImage2, CV_8U);

    if(!scene) scene = new QGraphicsScene;
    if(!view) view = new QGraphicsView(scene);
    if(item) {
        scene->clear();
        //delete item; item=0;
    }
    item = new QGraphicsPixmapItem(ASM::cvMatToQPixmap(finalImage2).copy());
    scene->addItem(item);
    view->adjustSize();
    view->show();

}
Esempio n. 4
0
        static T squaredNormFeaturesNoCcs(const std::shared_ptr<FeatureChannels_>& Af) {
            int n = Af->channels[0].rows * Af->channels[0].cols;
            T sum_ = 0;
            cv::Mat elemMul;

            for (int i = 0; i < NUMBER_OF_CHANNELS; ++i) {
                mulSpectrums(Af->channels[i], Af->channels[i], elemMul, 0, true);
                sum_ += static_cast<T>(cv::sum(elemMul)[0]);
            }

            return sum_ / n;
        }
Esempio n. 5
0
        static T squaredNormFeaturesCcs(const std::shared_ptr<FeatureChannels_>& Af) {
            // TODO: this is still slow and used frequently by gaussian
            // correlation => find an equivalent quicker formulation;
            // Note that reshaping and concatenating the mats first
            // and then multiplying them is slower than
            // this current approach!
            int n = Af->channels[0].rows * Af->channels[0].cols;
            T sum_ = 0;
            cv::Mat elemMul;

            for (int i = 0; i < NUMBER_OF_CHANNELS; ++i) {
                mulSpectrums(Af->channels[i], Af->channels[i], elemMul, 0, true);
                sum_ += static_cast<T>(sumRealOfSpectrum<T>(elemMul));
            }

            return sum_ / n;
        }
Esempio n. 6
0
File: Dip3.cpp Progetto: kziel1/dip
/*
in       input image
kernel   filter kernel
return   output image
*/
Mat Dip3::frequencyConvolution(Mat& in, Mat& kernel){

   Mat tempA = Mat::zeros(in.rows, in.cols, CV_32FC1);
   Mat tempB = Mat::zeros(in.rows, in.cols, CV_32FC1);
   
   for (int x = 0; x < kernel.rows; x++) for (int y = 0; y < kernel.cols; y++) {
      tempB.at<float>(x, y) = kernel.at<float>(x, y);
   }
   
   tempB = circShift(tempB, -1, -1);

   dft(in, tempA, 0);
   dft(tempB, tempB, 0);
   mulSpectrums(tempA, tempB, tempB, 0);
   dft(tempB, tempA, DFT_INVERSE + DFT_SCALE);

   return tempA;
}
Esempio n. 7
0
File: csk.cpp Progetto: foolwood/CSK
void DenseGaussKernel(float sigma, const Mat &x,const Mat &y, Mat &k){
  Mat xf, yf;
  dft(x, xf, DFT_COMPLEX_OUTPUT);
  dft(y, yf, DFT_COMPLEX_OUTPUT);
	double xx = norm(x);
	xx = xx*xx;
	double yy = norm(y);
	yy = yy*yy;

  Mat xyf;
  mulSpectrums(xf, yf, xyf, 0, true);

	Mat xy;
	cv::idft(xyf, xy, cv::DFT_SCALE | cv::DFT_REAL_OUTPUT); // Applying IDFT
  CircShift(xy, scale_size(x.size(),0.5));
	double numelx1 = x.cols*x.rows;
	//exp((-1 / (sigma*sigma)) * abs((xx + yy - 2 * xy) / numelx1), k); //thsi setting is fixed by version 2(KCF)
  exp((-1 / (sigma*sigma)) * max(0,(xx + yy - 2 * xy) / numelx1), k);
}
Esempio n. 8
0
/*
in       input image
kernel   filter kernel
return   output image
*/
Mat Dip3::frequencyConvolution(Mat& in, Mat& kernel){
     
    Mat freq_in, freq_kernel, result;
 
    //copy kernel to large matrix (the size of input image)
    cv::Rect roi(cv::Point(0,0),kernel.size());
    Mat destinationROI = Mat::zeros(in.size(), in.type());
    kernel.copyTo(destinationROI(roi));

    //perform circ shift on kernel 
    Mat circ_kernel = circShift(destinationROI, -kernel.cols/2, -kernel.rows/2);

    //convert to frequency domains
    dft(in, freq_in, 0);
    dft(circ_kernel, freq_kernel, 0);

    //multiplication in freq domains
    mulSpectrums(freq_in, freq_kernel, freq_in,0);
    
    //convert to spatial domain
    dft(freq_in, result, DFT_INVERSE + DFT_SCALE);

    return result;
}
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);

	}

}
Esempio n. 10
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);
                }
            }
        }
    }
}
Esempio n. 11
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;
}
Esempio n. 12
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;

}
Esempio n. 13
0
File: Dip4.cpp Progetto: kziel1/dip
/*
degraded :  degraded input image
filter   :  filter which caused degradation
return   :  restorated output image
*/
Mat Dip4::inverseFilter(Mat& degraded, Mat& filter){

  // be sure not to touch them
  degraded = degraded.clone();
  filter = filter.clone();

  Mat tempA = Mat::zeros(degraded.size(), CV_32FC1);
  
  Mat degradedFreq = degraded.clone();
  Mat filterFreq = Mat::zeros(degraded.size(), CV_32F);

  // add Border
  for (int x = 0; x < filter.rows; x++) for (int y = 0; y < filter.cols; y++) {
    filterFreq.at<float>(x, y) = filter.at<float>(x, y);
  }
   
  filterFreq = circShift(filterFreq, -1, -1);

  // transform to complex 
  Mat planes[] = {degradedFreq, Mat::zeros(degraded.size(), CV_32F)};
  Mat planesFilter[] = {filterFreq, Mat::zeros(filterFreq.size(), CV_32F)};
  
  merge(planes, 2, degradedFreq);
  merge(planesFilter, 2, filterFreq);

  // convert to frequency spectrum
  dft(degradedFreq, degradedFreq, DFT_COMPLEX_OUTPUT); // degradedFreq == S
  dft(filterFreq, filterFreq, DFT_COMPLEX_OUTPUT); // filterFreq == P

  // create Q

  split(filterFreq, planes);

  Mat Re = planes[0];
  Mat Im = planes[1];
  
  // calculate Threshold
  double thresholdFactor = 0.05, threshold;
  double max = 0;

  // find maximum
  for (int x = 0; x < filterFreq.rows; x++) for (int y = 0; y < filterFreq.cols; y++) {
    float resq = Re.at<float>(x, y) * Re.at<float>(x, y);
    float imsq = Im.at<float>(x, y) * Im.at<float>(x, y);

    float absreim = sqrt(resq + imsq);
    if (absreim > max) {
      max = absreim;
    }
  }
  
  threshold = thresholdFactor * max;

  for (int x = 0; x < filterFreq.rows; x++) for (int y = 0; y < filterFreq.cols; y++) {
    
    float resq = Re.at<float>(x, y) * Re.at<float>(x, y);
    float imsq = Im.at<float>(x, y) * Im.at<float>(x, y);

    float absreim = sqrt(resq + imsq);

    if (absreim >= threshold) {

      Re.at<float>(x, y) = Re.at<float>(x, y) / (resq + imsq);
      Im.at<float>(x, y) = Im.at<float>(x, y) / (resq + imsq);

    } else {
      Re.at<float>(x, y) = 0;
      Im.at<float>(x, y) = 0;
    }

  }
  
  Mat Q = Mat::zeros(filterFreq.size(), CV_32F);
  
  merge(planes, 2, Q);

  Mat original;

  mulSpectrums(degradedFreq, Q, original, 1);
  dft(original, original, DFT_INVERSE + DFT_SCALE);
  split(original, planes);

  original = planes[0];
  normalize(original, original, 0, 255, CV_MINMAX);
  original.convertTo(original, CV_8UC1);
 
  return original;
}
Esempio n. 14
0
File: dip4.cpp Progetto: hoijui/DIP
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;
}