Sunday, 30 March 2014

#9a. Hierarchical contour extraction

Contours are curves joining all the continuous points (along the boundary), having same color or intensity.


#include
#include
#include
using namespace std;
using namespace cv;

Mat img;
vector > contours;
vector heirarchy;
int levels=0;

void on_trackbar(int, void *){
	Mat img_show=img.clone();
	drawContours(img_show,contours,-1,Scalar(0,0,255),3,8,heirarchy,levels);
	imshow("Contours",img_show);
}

int main()
{
	img=imread("images/circles3.jpg");
	Mat imgb;
	cvtColor(img,imgb,CV_RGB2GRAY);
	Mat edges;
	Canny(imgb,edges,50,100);
	findContours(edges,contours,heirarchy,CV_RETR_TREE,CV_CHAIN_APPROX_NONE);

	namedWindow("Contours");
	createTrackbar("levels","Contours",&levels,15,on_trackbar);
	on_trackbar(0,0);
	while(char(waitKey(1))!='q'){}
	return 0;
}



Firstly, in Main(), the image is read, converted to gray scale, and edges are detected by Canny edge detection algorithm.

findContours() finds all the contours in the image.
You may look at the documentation here.

Now, the contours have a hierarchy, in the sense that, there are outermost contours and there are contours inside contours which may be noise.
You should have the concept of 'contours' clear.
You may go through the documentation here.

Then we created a trackbar by which we can change the level of hierarchy.
drawContours() simply draws the contours on the image.
Find the documentation of drawContours() here.
-------------------------------------
Input Image:


Output:
Level 1:


Level 5:



Level 11(Saturation Point, for this image):


Wednesday, 19 March 2014

#8c. Object Detection: Morphological Opening and Closing

In our Object Detection application, you may have noticed quite some amount of noise.
When it is supposed to detect red color, it also detects some noise, and gives wrong output,sometimes.


Opening is obtained by eroding an image followed by dilating it. It will have an effect of removing small white regions in the image. Closing is obtained by dilating an image followed by eroding it; this will have the opposite effect. Both these operations are used frequently to remove noise
from an image. Opening removes small white pixels while closing removes small black “holes.”

The OpenCV function morphologyEX()can be used to perform advanced morphological operations such as opening and closing on images. So we can open and close the output of the inRange() function to remove black and white dots by updating the 'main' function:

int main()
{

 VideoCapture cap(0);
 namedWindow("Video");
 namedWindow("Segmentation");

  createTrackbar("0.R\n1.G\n2.B","Segmentation",&rgb_slider, 2 ,on_rgb_trackbar);

 createTrackbar("Low threshold","Segmentation",&low_slider,255,on_low_thresh_trackbar);

 createTrackbar("High threshold","Segmentation",&high_slider,255,on_high_thresh_trackbar);

 while(char(waitKey(1)) != 'q') {
  cap>>frame;
  if(frame.empty())
   break;
  inRange(frame,Scalar(low_b,low_g,low_r),Scalar(high_b,high_g,high_r),frame_threshold);

//Morphological Opening and Closing
  Mat str_el=getStructuringElement(MORPH_RECT,Size(3,3));
  morphologyEx(frame_threshold,frame_threshold,MORPH_OPEN,str_el);
  morphologyEx(frame_threshold,frame_threshold,MORPH_CLOSE,str_el);


  imshow("Video",frame);
  imshow("Segmentation",frame_threshold);
 }

 return 0;
}
---------------------------------------------------------

Tuesday, 18 March 2014

Project 1.1. PaintBox 2.0

Lets create PaintBox version 2.0.
In this version, I have introduced trackbars for changing colors and size of the brush(:P).
Again, this code is self-explanatory.
You just need to know the concept of trackbars!

#include
#include
#include
#include
using namespace std;
using namespace cv;
Mat img;
Point pt;
int red,green,blue;
int slider=0, slider_max=255;
int size_min=4,size_max=40,size;
bool lup=false, ldown=false;
void on_trackbar_r(int pos, void *){
 red=pos;
}

void on_trackbar_g(int pos, void *){
 green=pos;
}

void on_trackbar_b(int pos, void *){
 blue=pos;
}

void on_trackbar_size(int pos, void *){
 size=pos;
}
static void mouse_callback(int event, int x, int y,int, void *){
if(event==EVENT_LBUTTONDOWN){
 ldown=true;
 pt.x=x;
 pt.y=y;
 circle(img,pt,size,CV_RGB(red,green,blue),-3);
}

if(ldown==true && lup==false){
 pt.x=x;
 pt.y=y;
 Mat local_img=img.clone();
 circle(img,pt,size,CV_RGB(red,green,blue),-3);
 imshow("PaintBox",local_img);
}

if(event==EVENT_LBUTTONUP){
 lup=true;
}
if(ldown==true && lup==true){
 ldown=false;
 lup=false;
}
}
int main()
{

 img=Mat(550,1300,CV_8UC3,Scalar(255,255,255));
//Here, I've created a white image of 550x1300 size
// which has 3 channels(R,G,B)
// each R,G,B color represented in Unsigned Char in 8 Bits
//So the strength of each channel varies from 0 to 255.
// color of the image is white(255,255,255)

 namedWindow("PaintBox");
 imshow("PaintBox",img);
 createTrackbar("Size","PaintBox",&size_min,size_max,on_trackbar_size);
 createTrackbar("Red","PaintBox",&slider,slider_max,on_trackbar_r);
 createTrackbar("Green","PaintBox",&slider,slider_max,on_trackbar_g);
 createTrackbar("Blue","PaintBox",&slider,slider_max,on_trackbar_b);
 setMouseCallback("PaintBox",mouse_callback);
 while(char(waitKey(1))!='q'){}
 return 0;
}

---------------------------------------------------------------------------

The 'Blue' trackbar is not visible as the image was too large for the Cropping Program to handle.

Note: For an eraser, just set the RGB values to (255,255,255).

Also, I just figured out that you can even use this as an image editor.

Just set img to the image you wish to edit. e.g.

img=imread("images/attitude.jpg");



And now, that's my fb cover pic!

Project 1. Creating your own PaintBox!

Hi guys!
Lets take a look at how a simple Paint application can be implemented using OpenCV.
I shall combine the concepts of tutorial #1(MouseCallback) and tutorial #8, (circle).
The code is quite easy and self explanatory, provided, you are thorough with all the tutorials until now.
If you have any doubts, feel free to comment.
#include
#include
#include
#include
using namespace std;
using namespace cv;

Mat img;
Point pt;

bool lup=false, ldown=false;

static void mouse_callback(int event, int x, int y,int, void *){
if(event==EVENT_LBUTTONDOWN){
 ldown=true;
 pt.x=x;
 pt.y=y;
 circle(img,pt,4,CV_RGB(255,0,0),-3);
}

if(ldown==true && lup==false){
 pt.x=x;
 pt.y=y;
 Mat local_img=img.clone();
 circle(img,pt,4,CV_RGB(255,0,0),-3);
 imshow("PaintBox",local_img);
}

if(event==EVENT_LBUTTONUP){
 lup=true;
}
if(ldown==true && lup==true){
 ldown=false;
 lup=false;
}
}
int main()
{
 img=imread("images/white.png");
 namedWindow("PaintBox");
 imshow("PaintBox",img);
 setMouseCallback("PaintBox",mouse_callback);
 while(char(waitKey(1))!='q'){}
 return 0;
}



Monday, 17 March 2014

#8b. Object Detection version 0.1

Although the title is Object Detection, the following code won't actually detect objects.
This is just to focus on the use of 'inRange()' function.
#include
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
 Mat frame, frame_segmented;
 VideoCapture cap(0);
 namedWindow("Video");
 namedWindow("Video_Segmented");

 while(char(waitKey(1))!='q'){
  cap>>frame;

  inRange(frame, Scalar(30,30,30),Scalar(100,100,100),frame_segment);
  
                imshow("Video",frame);
  imshow("Video_Segmented",frame_segmented);
 }

 return 0;
}


Sunday, 16 March 2014

#8a. Object Detection version 1.0

Moving on to object detection, you will find this post very interesting, provided you understand it.
In this tutorial, I will show you how to detect an object based on difference in color of the object and that of the surroundings.

I hope you've read 'A piece of advice', my previous post.
Try it in this tutorial. See if you understand the program in one shot.


#include
#include
#include
#include
using namespace std;
using namespace cv;

Mat frame , frame_threshold;
//Refer Main

int rgb_slider=0;
int low_slider=30, high_slider=100;

int low_r=30, low_g=30, low_b=30, high_r=100, high_g=100, high_b=100;
//r g b r g b

void on_rgb_trackbar(int ,void *){
 switch(rgb_slider){
 case 0:
  setTrackbarPos("Low threshold","Segmentation",low_r);
  setTrackbarPos("High threshold","Segmentation",high_r);
  break;
 case 1:
  setTrackbarPos("Low threshold", "Segmentation", low_g);
  setTrackbarPos("High threshold","Segmentation", high_g);
  break;
 case 2:
  setTrackbarPos("Low threshold","Segmentation",low_b);
  setTrackbarPos("High threshold", "Segmentation",high_b);
  break;
 }
}

//go to Main again

void on_low_thresh_trackbar(int, void*){
 switch(rgb_slider){
 case 0:
  low_r=min(high_slider-1, low_slider);
  setTrackbarPos("Low threshold","Segmentation",low_r);
  break;
 case 1:
  low_g=min(high_slider-1,low_slider);
  setTrackbarPos("Low threshold","Segmentation",low_g);
  break;
 case 2:
  low_b=min(high_slider-1,low_slider);
  setTrackbarPos("Low threshold","Segmentation",low_b);
  break;
 }
}

//go to Main again

void on_high_thresh_trackbar(int, void*){
 switch(rgb_slider){
 case 0:
  high_r=max(high_slider, low_slider+1);
  setTrackbarPos("High threshold","Segmentation",high_r);
  break;
 case 1:
  high_g=max(high_slider,low_slider+1);
  setTrackbarPos("High threshold","Segmentation",high_g);
  break;
 case 2:
  high_b=max(high_slider,low_slider+1);
  setTrackbarPos("High threshold","Segmentation",high_b);
  break;
 }
}


int main()
{

 VideoCapture cap(0);
 namedWindow("Video");
 namedWindow("Segmentation");

  createTrackbar("0.R\n1.G\n2.B","Segmentation",&rgb_slider, 2 ,on_rgb_trackbar);
//observe the variables and callback function.
// go back to where you've left.

 createTrackbar("Low threshold","Segmentation",&low_slider,255,on_low_thresh_trackbar);
//observe the variables and callback function.
// go back to where you've left.

 createTrackbar("High threshold","Segmentation",&high_slider,255,on_high_thresh_trackbar);
//observe the variables and callback function.
// go back to where you've left.

 while(char(waitKey(1)) != 'q') {
  cap>>frame;
  if(frame.empty())
   break;
  inRange(frame,Scalar(low_b,low_g,low_r),Scalar(high_b,high_g,high_r),frame_threshold);

//inRange function, refer text.

  imshow("Video",frame);
  imshow("Segmentation",frame_threshold);
 }

 return 0;
}


So, inRange function basically filters out an image based on the color channels.
  • The color channel sequence in opencv is B, G ,R  and not R,G,B.
  • Scalar(B,G,R) defines the strength of an image in terms of B, G, R.\
  • If you remember, we had done a tutorial on increasing brightness of an image using TrackBar(Tutorial #6). The same function was used. I hope you got the idea.
  • If you understood Scalar(), you've understood inRange.
  • If not, refer DOCUMENTATION.
----------------------------------------------------------
Screenshot of the input video:
(My room is completely messed up. So I cropped the screenshot. Ubuntu doesn't have a cropping utility, but, we know OpenCV now! First Tutorial, Cropping app!)

Output:
e.g. Red color detector
Wonderful, isn't it?

A piece of advice.

Hi guys! Hope you're doing well.
So you must have got some idea of what OpenCV is! (pun intended :P)
Before moving further, I would like to advise you on how you must understand or write a code for OpenCV.
Mostly, you look through the code from top to bottom, look at the variables and functions and then understand it.
Try this once:

1. Observe the libraries included
2. Go to 'MAIN' function and study it first before looking at the user-defined functions. Understand what the 'main' function basically does.

  • Creates a trackbar? what are the lowest and highest values? What is the response function for trackbar? Having observed these, go to where you've left before jumping to 'MAIN' function. Then study those variables and functions.
  • Then again come back to 'Main' function where you had left and then study further and repeat the process.
In this way, you study the program in a manner you understand it.
Hope this helps.
Cheers!

Saturday, 15 March 2014

#7b. Detecting Corners

Let us get our hands on Edge Detection Technique.
-------------------------------------------------------------
Input image:

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

Mat img,img_g;

int main()
{
img=imread("images/squares.jpg");
cvtColor(img,img_g,CV_RGB2GRAY);

vector<Point2d> corners;
//creates a 2D Vector

float quality=0.01;
int min_distance=10,max_corners=50;

goodFeaturesToTrack(img_g,corners,max_corners,quality,min_distance);
//tracks good features!
//img_g: target image
//corners: stores the position of corners
//max_corners: maximum number of corners; you can vary these
// quality, min_distance, refer documentation.

Mat img_corners=img.clone();

for(int i=0;i < corners.size();i++)
circle(img_corners,corners[i],4,CV_RGB(255,0,0),-1);
// draws circles
namedWindow("Image");
imshow("Image",img_corners);
while(char(waitKey(1)) != 'q') {}

return 0;
}
--------------------------------------------------
Result:
We are first converting the image to grayscale and then detecting the corners.

This algorithm was proposed by Shi and Tomasi.

Sources:



#7a. Detecting Edges with increased efficiency

Being Updated.

#6. User Interface: Creating a Trackbar

Now, I will deviate a bit from our image processing techniques and algorithms.
So far, we have seen how we can use 2D Convolution to process images.
In this post, I will show you how create a trackbar for user interface.

A simple example that increases brightness of the picture.
-----------------------------------------------------------------------------
Input image:


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

Mat img;
//STOP. Refer to 'main' function first.

int slider=0, slider_max=100;

// the following call back function takes two arguments
//first: the position of trackbar
// second: Null
// Refer documentation

void on_trackbar(int pos, void *){
Mat img_c;
img_c=img+Scalar(pos,pos,pos);
//This command varies brightness according to the position of trackbar.
imshow("Image",img_c);
}

int main()
{
img=imread("images/image.jpg",CV_LOAD_IMAGE_COLOR);
namedWindow("Image");
createTrackbar("Brightness","Image",&slider,slider_max,on_trackbar);

//createTrackbar creates a trackbar
//first argument "Brightness": Title of the Trackbar
//second argument "Image": The window name in which trackbar has to be created.
//third: minimum value of trackbar position
//NOTE: it has to be passed by reference. Refer documentation.
//fourth: maximum value
//fifth: the function which has to be called when the user interacts(i.e. Trackbar position is changed)

while(char(waitKey(0))!='q'){}
return 0;

}
-----------------------------------------------------------------
Result:

You can't see the trackbar here, but you've to believe in my code:P


Note: In previous tutorials, if you remember, I had commented against a variable that the value can be varied. You can actually try varying the values by creating a trackbar!
Do this as an exercise. In this way you can also go through all the tutorials until now, and believe me, your concepts will be more clear. Do comment if you have any doubts.

Friday, 14 March 2014

#5. Eroding and Dilating an Image

Now, continuing on the same concept of 2D Convolution, Eroding and Dilating works on the form and structure of the image.
In previous tutorials, we slid a kernel over an image and did operations like summing up all the element-wise multiplication pairs and storing it in an anchor point.

In this tutorial, what we are gonna do is to calculate the minimum(Eroding) and maximum(Dilating) values of the element-wise multiplication and store it the anchor point.

For simplicity, we take all the kernel elements as ones.
Try visualizing this.
Now, slide the kernel over your image(2D Convolution).
Because all kernel elements are ones, applying this kernel(in Eroding) means replacing each pixel value with the minimum value in a rectangular region surrounding the pixel. You can imagine that this will cause the black areas in the image to “encroach” into the white areas (because pixel value for white is higher than that for black).

Dilating the image is the same, the only difference being that the response if defined as the maximum of
element-wise multiplications instead of minimum. This will cause the white regions to encroach into black regions.
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
 Mat img=imread("images/j.jpg"),img2,img3;

 Mat st_elem=getStructuringElement(MORPH_RECT,Size(5,5));

//I am defining my own kernel matrix here
//MORPH_RECT: Rectangular Morphological Matrix
//Size(5,5): 5x5 size matrix
// You can vary the size and shape

 erode(img,img2,st_elem);

 dilate(img,img3,st_elem);


 namedWindow("Image");
 namedWindow("Image2");
        namedWindow("Image3");

 imshow("Image",img);
 imshow("Image2",img2);
 imshow("Image3",img3);

 while(char(waitKey(0))!='q'){}
 return 0;

}

Input image:



Result:
Eroding

Dilating




-------------------------------------------------
More sources:
FILTERING(Optional)

Thursday, 13 March 2014

#4. Blurring an Image

Blurring is built on the same concept of 2D Convolution, difference being the change in kernel matrix.
Blurring averages the pixel values around one particular pixel.
Looks simple, but blurring is much more than just Convolution, it requires some more concepts of variance, averaging, etc.

A very simple kernel is a box kernel:

1   1   1   1   1
1   1   1   1   1
1   1   1   1   1 
1   1   1   1   1 
1   1   1   1   1 


This kernel deems every pixel equally important. A better kernel would be one that decreases the effect of a pixel as its distance from the central pixel increases. The Gaussian kernel does this, and is the most commonly used blurring kernel:
 
1    4   6    4   1
4  16  24  16  4
6  24  36  24  6
4  16  24  16  4
1    4   6    4   1
------------------------------------------------------------------------
#include<iostream>
#include<cv.h>
#include<highgui.h>
using namespace std;
using namespace cv;
int main()
{

 Mat img_b,img=imread("images/image.jpg");

 float blur[5][5]={{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1}};
// simple box kernel

//float blur[5][5]={{1,4,6,4,1},{4,16,24,16,4},{6,24,36,24,6},{4,16,24,16,4},{1,4,6,4,1}};
// Guassian kernel

 Mat filter_b=Mat(5,5,CV_32FC1,blur);

 filter2D(img,img_b,-1,filter_b);

 namedWindow("Image");
 namedWindow("Image_B");
 imshow("Image",img);
 imshow("Image_B",img_b);
 while(char(waitKey(0))!='q'){}
 return 0;

}
-------------------------------------------------------------------------

Note: Blurring is more than just Convolution. If you want to go further, please visit THIS documentation. Following is the basic application of 'GaussianBlur()' function.
--------------------------------------------------------------------------
Input Image:
 


#include<iostream>
#include<cv.h>
#include<highgui.h>
using namespace std;
using namespace cv;
int main()
{

 Mat img_b,img=imread("images/image.jpg");
 
 int k=5;
//you can vary the value of 'k' from 1 to 5, in this case.

 int sigma = 0.3 * ((k - 1) * 0.5 - 1) + 0.8;
 GaussianBlur(img, img_b, Size(k, k), sigma);

 namedWindow("Image");
 namedWindow("Image_B");
 imshow("Image",img);
 imshow("Image_B",img_b);
 while(char(waitKey(0))!='q'){}
 return 0;

}
-------------------------------------------------------------

Result:



#3d. Further discussion of 'filter2D' and Convolution in 2D

Under construction.

Wednesday, 12 March 2014

#3c: Detecting any kind of edges: Canny Edge Detection Algorithm

Note: This tutorial is optional. Don't worry if you are unable to understand properly.
You may refer HERE for further insight of this algorithm.
The following is the code for your reference.
-----------------------------------------------------------------------------------
Input Image:




#include
#include
#include
using namespace std;
using namespace cv;

 Mat src, src_gray;
 Mat dst, detected_edges;

 int edgeThresh = 1;
 int lowThreshold;
 int const max_lowThreshold = 100;
 int ratio = 3;
 int kernel_size = 3;
 char* window_name = "Edge Map";

 /**
  * @function CannyThreshold
  * @brief Trackbar callback - Canny thresholds input with a ratio 1:3
  */
 void CannyThreshold(int, void*)
 {
   /// Reduce noise with a kernel 3x3
   blur( src_gray, detected_edges, Size(3,3) );

   /// Canny detector
   Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size );

   /// Using Canny's output as a mask, we display our result
   dst = Scalar::all(0);

   src.copyTo( dst, detected_edges);
   imshow( window_name, dst );
  }


 /** @function main */
 int main( int argc, char** argv )
 {
   /// Load an image
   src = imread("images/windows.jpg");

   if( !src.data )
   { return -1; }

   /// Create a matrix of the same type and size as src (for dst)
   dst.create( src.size(), src.type() );

   /// Convert the image to grayscale
   cvtColor( src, src_gray, CV_BGR2GRAY );

   /// Create a window
   namedWindow( window_name, CV_WINDOW_AUTOSIZE );

   /// Create a Trackbar for user to enter threshold
   createTrackbar( "Min Threshold:", window_name, &lowThreshold, max_lowThreshold, CannyThreshold );

   /// Show the image
   CannyThreshold(0, 0);

   /// Wait until user exit program by pressing a key

 while(char(waitKey(0))!='q'){}
 return 0;
}

Result:



#3b: Detecting Vertical and Horizontal Edges

Prerequisites:
---------------------------------------------------------------------------------------



#include
#include
#include
using namespace std;
using namespace cv;
int main()
{

 Mat img_v, img_h,img=imread("images/black.jpg");

 float vertical_fk[5][5]={{0,0,0,0,0},{0,0,0,0,0},{-1,-2,6,-2,-1},{0,0,0,0,0},{0,0,0,0,0}};
 float horizontal_fk[5][5]={{0,0,-1,0,0},{0,0,-2,0,0},{0,0,6,0,0},{0,0,-2,0,0},{0,0,-1,0,0}};
 Mat filter_v=Mat(5,5,CV_32FC1, vertical_fk);
 Mat filter_h=Mat(5,5,CV_32FC1, horizontal_fk);


 filter2D(img,img_v,-1,filter_v);
 filter2D(img,img_h,-1,filter_h);

 namedWindow("Image");
 namedWindow("Image_V");
 namedWindow("Image_H");

 imshow("Image",img);
 imshow("Image_V",img_v);
 imshow("Image_H",img_h);
 while(char(waitKey(0))!='q'){}
 return 0;

}
Results:

Cool, isn't it?

It would be more clear if go through the documentation of the functions you've learnt.
Still, if you have any doubts, feel free to comment.

#3a. Create your own image Matrix


#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
 Mat img=Mat(5,5,CV_32FC3,Scalar(300,400,500));
 namedWindow("Image");
 imshow("Image",img);
 while(char(waitKey(0))!='q'){}
 return 0;
}

Expanation:
'Mat' is basically a structure definition in OpenCV.

Mat img=Mat(5,5,CV_32FC3,Scalar(300,400,500));

So, now, this command creates a 5x5 matrix image.

CV_32FC3 : tells that each pixel has 3 Channel(e.g. R,G,B) and each channel is of 32 bits(e.g 010100...) and each of 32 bits represents a Floating Character.

32FC: 32bit Floating Character
8UC: 8bit Unsigned Character etc.

__FC1: 1 channel
__FC 5: 5 channels etc.

Look here for more explanation.

Monday, 10 March 2014

#2. Display feed from your webcam


#include
#include
#include
using namespace std;
using namespace cv;

int main()
{
 Mat frame;
//create a Mat object
 VideoCapture cap(0);
//creates a VideoCapture object that links to the default device(number 0) on your computer
 
        namedWindow("Video");
 while(char(waitKey(1))!='q'){

  cap >> frame;
//extracts a frame from the input device 'cap' to 'frame'
  imshow("Video",frame);
 }
 return 0;
}

Tweak:
You can also play a video from a file.
create a VideoCapture object as:

VideoCapture cap("video.mp4");

Sunday, 9 March 2014

#1. Crop an Image


//including libraries
#include
#include
#include
using namespace std;
using namespace cv;

Mat img;

//Advice:Refer 'main()' function first.

//create boolean variables
bool lup=false, ldown=false;

//opencv allows to create 'Point' variables, which stores the x,y coordinates
//think of the point as an Object and coordinates as its Property.
Point corner1, corner2;
Rect box;

//self-explanatory
static void mouse_callback(int event, int x,int y, int, void *){
 if(event==EVENT_LBUTTONDOWN){
  ldown=true;
  corner1.x=x;
  corner1.y=y;
 }
 if(event==EVENT_LBUTTONUP){
  lup=true;
  corner2.x=x;
  corner2.y=y;
 }
 if(ldown==true && lup==false){
  Point pt;
  pt.x=x;
  pt.y=y;
//clone the original image
  Mat local_img=img.clone();
  rectangle(local_img, corner1,pt, Scalar(0,0,255));
  imshow("Image",local_img);
 }

 if(ldown==true && lup==true){
  box.width = abs(corner1.x - corner2.x);
  box.height = abs(corner1.y - corner2.y);
  box.x = min(corner1.x, corner2.x);
  box.y = min(corner1.y, corner2.y);
  
//the 'crop' function crops the image 'img' in the dimensions of 'box'
                Mat crop(img,box);
  namedWindow("Crop");
  imshow("Crop",crop);
  ldown=false;
  lup=false;
 }
}

int main()
{
       //read an image in Mat variable 'img'
 img=imread("images/image.jpg");
 namedWindow("Image");
 imshow("Image",img);

       //setMouseCallback is a function which, in simple language, records the mouse events, namely,
          // clicks and position of clicks.
 setMouseCallback("Image",mouse_callback);

 while(char(waitKey(0))!='q'){ }
 return 0;
}

Introduction

Hi guys!
Frankly, I don't know much about OpenCV.
I have just started learning Visual Computing.
I feel the best way to learn is by teaching.
So, I'll be posting here stuff(on OpenCV, ofcourse) which I have learnt.

I'll be using OpenCV in Ubuntu, and I would suggest you to do the same(i.e. use CV in a Unix environment).
I'll be writing the programs in C++. You may write in whichever language you want, but make sure you understand the gist of the program.

So, hold up your sleeves, tighten up your belts, and get ready to plunge into this wonderful technology.
Cheers!
Feel free to comment your doubts(in further posts, of course!), we'll solve it together!