Thursday, 26 February 2015

Fourier Theory

The tool, which converts a spatial (real space) description of an
image into one in terms of its frequency components, is called the Fourier transform.
The new version is usually referred to as the Fourier space description of the image.
The corresponding inverse transformation which turns a Fourier space description back into a real space one is called the inverse Fourier transform.
1D Case:
Considering a continuous function f(x) of a single variable x representing distance. The Fourier transform of that function is denoted F(u), where u represents spatial frequency is defined by:

F ( u ) =<integrate from -∞ to ∞> f ( x ) exp(− j 2 π xu) dx

The meaning of this is that, not only is the magnitude of each frequency present important, but that its phase relationship is too.
The inverse Fourier transform for regenerating f(x) from F(u) is given by:

f ( x ) =<integrate from -∞ to ∞> F ( u ) exp(j 2 π xu) du


Some references:
http://homepages.inf.ed.ac.uk/rbf/HIPR2/fourier.htm
https://www.cs.unm.edu/~brayer/vision/fourier.html
http://cns-alumni.bu.edu/~slehar/fourier/fourier.html

Wednesday, 25 February 2015

Pixels

Neighbors of a Pixel

  •  Any pixel p(x, y) has two vertical and two horizontal neighbors, given by (x+1, y), (x-1, y), (x, y+1), (x, y-1)
  •  This set of pixels are called the 4-neighbors of P, and is denoted by N 4 (P). Each of them are at a unit distance from P.
  •  The four diagonal neighbors of p(x,y) are given by, (x+1, y+1), (x+1, y-1), (x-1, y+1), (x-1 ,y-1).This set is denoted by N D (P).
  • The points N D (P) and N 4 (P) are together known as 8-neighbors of the point P, denoted by N 8 (P).
  • Some of the points in the N 4 , N D and N 8 may fall outside image when P lies on the border of image.

  • (a) 4-adjacency. Two pixels p and q with values from V are 4-adjacent if q is in the set N 4 (p).
  • (b) 8-adjacency. Two pixels p and q with values from V are 8-adjacent if q is in the set N 8 (p). 
  • (c) m-adjacency (mixed adjacency). Two pixels p and q with values from V are m-adjacent if (i) q is in N 4 (p), or (ii) q is in N D (p) and the set N 4 (p)  ̈ N 4 (q) has no pixels whose values are from V.

Phase II

Hi guys!
Hope you have got your hand on some computer vision techniques.
If you implement it yourself you'll understand better.

I'll begin the next phase of the tutorials.
In this part, I'll cover some more advanced topics which would include some theoretical aspects of computer vision like Transforms, Histogram Equalization, Stereo Vision, Pixel Relations, Pattern Recognition, etc.

So stay tuned!

Sunday, 27 April 2014

Project 3. Painting in the air!

If you've followed all my tutorials till now, this project will seem very easy.
The only thing I've done is combine and interlink different concepts.
Object Detection, Circle Detection, Creating an Image Matrix, Video Rendering and Drawing Circles are included in this project.
With this, you've got quite a good exposure to Computer Vision and Image Processing.
You can play around with it and create your own applications.
Keep posting your doubts!

#include<iostream>
#include<highgui.h>
#include<cv.h>
using namespace std;
using namespace cv;

int main()
{
 VideoCapture cap(0);
 Mat frame;
 Mat img;

 namedWindow("video");
 namedWindow("shapes");
 namedWindow("paintbox");
 vector<Vec3f> circles;

 double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH);
 double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
 Mat paintbox=Mat(dHeight,dWidth,CV_8UC3,Scalar(255,255,255));
imshow("paintbox",paintbox);
 Mat pb_flipped;
 while(char(waitKey(1))!='q'){

  cap>>frame;

  cvtColor(frame,img,CV_RGB2GRAY);
  imshow("shapes",img);

  HoughCircles(img,circles,CV_HOUGH_GRADIENT,1,10,100,95,5);

  for(int i=0;i<circles.size();i++){

   Point center(cvRound(circles[i][0]),cvRound(circles[i][1]));
   int radius=cvRound(circles[i][2]);


   circle(frame,center,3,Scalar(0,0,255),-1);
   circle(frame,center,radius,Scalar(0,0,255),3,8,0);

 //  Mat img_local=paintbox.clone();
   circle(paintbox,center,3,Scalar(0,0,255),-1);
   flip(paintbox,pb_flipped,1);
   imshow("paintbox",pb_flipped);
  }
  imshow("video",frame);
 }
 return 0;
}



Monday, 14 April 2014

#12a. Hough Transform:Detecting lines


#include<iostream>
#include<cv.h>
#include<highgui.h>
using namespace cv;
using namespace std;
Mat img;
int thresh=100;

void on_trackbar(int, void *){
 Mat edges;
 Canny(img,edges,50,100);
 vector<Vec2f> lines;
 HoughLines(edges,lines,1,CV_PI/180.F,thresh);

 Mat img_show=img.clone();
 for(int i=0;i<lines.size();i++){
  float rho=lines[i][0];
  float theta=lines[i][1];
  double a=cos(theta), b=sin(theta);
  double x0=a*rho, y0=b*rho;
  Point pt1(cvRound(x0+1000*(-b)),cvRound(y0+1000*(a)));
  Point pt2(cvRound(x0-1000*(-b)),cvRound(y0-1000*(a)));
  line(img_show,pt1,pt2,Scalar(0,0,255));
 }
 imshow("shapes",img_show);
}
int main(){
 img=imread("images/linescircles.jpg");
 namedWindow("shapes");
 createTrackbar("Acc. thresh","shapes",&thresh,300,on_trackbar);
 on_trackbar(0,0);
 while(char(waitKey(0))!='q'){}

 return 0;
}


If you've gone through the previous posts(#11x.), this would'nt need much explanation.

HoughLines(edges,lines,1,CV_PI/180.F,thresh);

Format & Explanation:

 HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=0, double stn=0 )

Parameters:
  • image – 8-bit, single-channel binary source image. The image may be modified by the function.
--> In our case: 'edges'

  • lines – Output vector of lines. Each line is represented by a two-element vector (\rho, \theta) . \rho is the distance from the coordinate origin (0,0)(top-left corner of the image). \theta is the line rotation angle in radians ( 0 \sim \textrm{vertical line}, \pi/2 \sim \textrm{horizontal line} ).
-->The above point is the gist of the program

  • rho – Distance resolution of the accumulator in pixels.
  • theta – Angle resolution of the accumulator in radians.
  • threshold – Accumulator threshold parameter. Only those lines are returned that get enough votes ( >\texttt{threshold} ).

The following may not be relevant to this tutorial.
  • srn – For the multi-scale Hough transform, it is a divisor for the distance resolution rho . The coarse accumulator distance resolution isrho and the accurate accumulator resolution is rho/srn . If both srn=0 and stn=0 , the classical Hough transform is used. Otherwise, both these parameters should be positive.
  • stn – For the multi-scale Hough transform, it is a divisor for the distance resolution theta.
  • method –
    One of the following Hough transform variants:
    • CV_HOUGH_STANDARD classical or standard Hough transform. Every line is represented by two floating-point numbers (\rho, \theta) , where\rho is a distance between (0,0) point and the line, and \theta is the angle between x-axis and the normal to the line. Thus, the matrix must be (the created sequence will be) of CV_32FC2 type
    • CV_HOUGH_PROBABILISTIC probabilistic Hough transform (more efficient in case if the picture contains a few long linear segments). It returns line segments rather than the whole line. Each segment is represented by starting and ending points, and the matrix must be (the created sequence will be) of the CV_32SC4 type.
    • CV_HOUGH_MULTI_SCALE multi-scale variant of the classical Hough transform. The lines are encoded the same way asCV_HOUGH_STANDARD.
  • param1 –
    First method-dependent parameter:
    • For the classical Hough transform, it is not used (0).
    • For the probabilistic Hough transform, it is the minimum line length.
    • For the multi-scale Hough transform, it is srn.
  • param2 –
    Second method-dependent parameter:
    • For the classical Hough transform, it is not used (0).
    • For the probabilistic Hough transform, it is the maximum gap between line segments lying on the same line to treat them as a single line segment (that is, to join them).
    • For the multi-scale Hough transform, it is stn.



You may go through the Documentation HERE.

circle() function

Draws a circle.
C++: void circle(Mat& img, Point center, int radius, const Scalar& color, int thickness=1, int lineType=8, int shift=0)

Parameters:
  • img – Image where the circle is drawn.
  • center – Center of the circle.
  • radius – Radius of the circle.
  • color – Circle color.
  • thickness – Thickness of the circle outline, if positive. Negative thickness means that a filled circle is to be drawn.
  • lineType – Type of the circle boundary. See the line() description.
  • shift – Number of fractional bits in the coordinates of the center and in the radius value.
The function circle draws a simple or filled circle with a given center and radius.

 circle(img_show,center,3,Scalar(0,0,255),-1);
radius: 3
thickness: -1, filled circle

 
 circle(img_show,center,radius,Scalar(0,0,255),3,8,0);
radius: as detected
thickness: 3
line type: 8 
  • 8 (or omitted) - 8-connected line.
  • 4 - 4-connected line.

    shift: 0



#11d. Application: Detecting number of circles in an image

This is actually a redundant post.
There was a problem which I came through in one of the OpenCV Hackathons.
It asked to detect number of circles in the given image.
This is very easily done by Hough Transform.

#include<iostream>
#include<highgui.h>
#include<cv.h>
using namespace std;
using namespace cv;
Mat img;

int thresh=100; 

void on_trackbar(int, void *){
    Mat img_gray;
    cvtColor(img,img_gray,CV_RGB2GRAY);
    vector<Vec3f> circles;
    HoughCircles(img_gray,circles,CV_HOUGH_GRADIENT,1,10,100,thresh,5);
    Mat img_show=img.clone();

    //the following line has to be added to count the number of circles 
    cout<<"Number of circles: "<<circles.size()<<endl;

    for(int i=0;i<circles.size();i++){
        Point center(cvRound(circles[i][0]),cvRound(circles[i][1]));
        int radius=cvRound(circles[i][2]);

        circle(img_show,center,3,Scalar(0,0,255),-1);

        circle(img_show,center,radius,Scalar(0,0,255),3,8,0);

    }
    imshow("Shapes",img_show);

}
int main()
{
    img =imread("images/linescircles.jpg");
    namedWindow("Shapes");
    imshow("Shapes",img);
    createTrackbar("Acc. threshold","Shapes",&thresh,300,on_trackbar);
    on_trackbar(0,0);
    while(char(waitKey(0))!='q'){}
    return 0;
}

cout<<"Number of circles: "<<circles.size()<<endl; 
prints out the number of circles.