--- /dev/null
+#!/usr/bin/python
+"""
+ Tracking of rotating point.
+ Rotation speed is constant.
+ Both state and measurements vectors are 1D (a point angle),
+ Measurement is the real point angle + gaussian noise.
+ The real and the estimated points are connected with yellow line segment,
+ the real and the measured points are connected with red line segment.
+ (if Kalman filter works correctly,
+ the yellow segment should be shorter than the red one).
+ Pressing any key (except ESC) will reset the tracking with a different speed.
+ Pressing ESC will stop the program.
+"""
+from opencv.cv import *
+from opencv.highgui import *
+from math import cos, sin, sqrt
+
+if __name__ == "__main__":
+ A = [ [1, 1], [0, 1] ]
+
+ img = cvCreateImage( cvSize(500,500), 8, 3 )
+ kalman = cvCreateKalman( 2, 1, 0 )
+ state = cvCreateMat( 2, 1, CV_32FC1 ) # (phi, delta_phi)
+ process_noise = cvCreateMat( 2, 1, CV_32FC1 )
+ measurement = cvCreateMat( 1, 1, CV_32FC1 )
+ rng = cvRNG(-1)
+ code = -1L
+
+ cvZero( measurement )
+ cvNamedWindow( "Kalman", 1 )
+
+ while True:
+ cvRandArr( rng, state, CV_RAND_NORMAL, cvRealScalar(0), cvRealScalar(0.1) )
+
+ kalman.transition_matrix[:] = A
+ cvSetIdentity( kalman.measurement_matrix, cvRealScalar(1) )
+ cvSetIdentity( kalman.process_noise_cov, cvRealScalar(1e-5) )
+ cvSetIdentity( kalman.measurement_noise_cov, cvRealScalar(1e-1) )
+ cvSetIdentity( kalman.error_cov_post, cvRealScalar(1))
+ cvRandArr( rng, kalman.state_post, CV_RAND_NORMAL, cvRealScalar(0), cvRealScalar(0.1) )
+
+ while True:
+ def calc_point(angle):
+ return cvPoint( cvRound(img.width/2 + img.width/3*cos(angle)),
+ cvRound(img.height/2 - img.width/3*sin(angle)))
+
+ state_angle = state[0]
+ state_pt = calc_point(state_angle)
+
+ prediction = cvKalmanPredict( kalman )
+ predict_angle = prediction[0,0]
+ predict_pt = calc_point(predict_angle)
+
+ cvRandArr( rng, measurement, CV_RAND_NORMAL, cvRealScalar(0),
+ cvRealScalar(sqrt(kalman.measurement_noise_cov[0,0])) )
+
+ # generate measurement
+ cvMatMulAdd( kalman.measurement_matrix, state, measurement, measurement )
+
+ measurement_angle = measurement[0,0]
+ measurement_pt = calc_point(measurement_angle)
+
+ # plot points
+ def draw_cross( center, color, d ):
+ cvLine( img, cvPoint( center.x - d, center.y - d ),
+ cvPoint( center.x + d, center.y + d ), color, 1, CV_AA, 0)
+ cvLine( img, cvPoint( center.x + d, center.y - d ),
+ cvPoint( center.x - d, center.y + d ), color, 1, CV_AA, 0 )
+
+ cvZero( img )
+ draw_cross( state_pt, CV_RGB(255,255,255), 3 )
+ draw_cross( measurement_pt, CV_RGB(255,0,0), 3 )
+ draw_cross( predict_pt, CV_RGB(0,255,0), 3 )
+ cvLine( img, state_pt, measurement_pt, CV_RGB(255,0,0), 3, CV_AA, 0 )
+ cvLine( img, state_pt, predict_pt, CV_RGB(255,255,0), 3, CV_AA, 0 )
+
+ cvKalmanCorrect( kalman, measurement )
+
+ cvRandArr( rng, process_noise, CV_RAND_NORMAL, cvRealScalar(0),
+ cvRealScalar(sqrt(kalman.process_noise_cov[0,0])))
+ cvMatMulAdd( kalman.transition_matrix, state, process_noise, state )
+
+ cvShowImage( "Kalman", img )
+
+ code = str(cvWaitKey( 100 ))
+ if( code != '-1'):
+ break
+
+ if( code == '\x1b' or code == 'q' or code == 'Q' ):
+ break
+
+ cvDestroyWindow("Kalman")
--- /dev/null
+#!/usr/bin/python
+from opencv.cv import *
+from opencv.highgui import *
+from random import randint
+MAX_CLUSTERS = 5
+
+if __name__ == "__main__":
+
+ color_tab = [
+ CV_RGB(255,0,0),
+ CV_RGB(0,255,0),
+ CV_RGB(100,100,255),
+ CV_RGB(255,0,255),
+ CV_RGB(255,255,0)]
+ img = cvCreateImage( cvSize( 500, 500 ), 8, 3 )
+ rng = cvRNG(-1)
+
+ cvNamedWindow( "clusters", 1 )
+
+ while True:
+ cluster_count = randint(2, MAX_CLUSTERS)
+ sample_count = randint(1, 1000)
+ points = cvCreateMat( sample_count, 1, CV_32FC2 )
+ clusters = cvCreateMat( sample_count, 1, CV_32SC1 )
+
+ # generate random sample from multigaussian distribution
+ for k in range(cluster_count):
+ center = CvPoint()
+ center.x = cvRandInt(rng)%img.width
+ center.y = cvRandInt(rng)%img.height
+ first = k*sample_count/cluster_count
+ last = sample_count
+ if k != cluster_count:
+ last = (k+1)*sample_count/cluster_count
+
+ point_chunk = cvGetRows(points, first, last)
+
+ cvRandArr( rng, point_chunk, CV_RAND_NORMAL,
+ cvScalar(center.x,center.y,0,0),
+ cvScalar(img.width*0.1,img.height*0.1,0,0))
+
+
+ # shuffle samples
+ cvRandShuffle( points, rng )
+
+ cvKMeans2( points, cluster_count, clusters,
+ cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0 ))
+
+ cvZero( img )
+
+ for i in range(sample_count):
+ cluster_idx = clusters[i]
+ # a multi channel matrix access returns a scalar of
+ #dimension 4,0, which is not considerate a cvPoint
+ #we have to create a tuple with the first two elements
+ pt = (cvRound(points[i][0]), cvRound(points[i][1]))
+ cvCircle( img, pt, 2, color_tab[cluster_idx], CV_FILLED, CV_AA, 0 )
+
+ cvShowImage( "clusters", img )
+
+ key = cvWaitKey(0)
+ if( key == 27 or key == 'q' or key == 'Q' ): # 'ESC'
+ break
+
+
+ cvDestroyWindow( "clusters" )
--- /dev/null
+#!/usr/bin/python
+from opencv.cv import *
+from opencv.highgui import *
+import sys
+
+if __name__ == "__main__":
+ laplace = None
+ colorlaplace = None
+ planes = [ None, None, None ]
+ capture = None
+
+ if len(sys.argv)==1:
+ capture = cvCreateCameraCapture( 0 )
+ elif len(sys.argv)==2 and sys.argv[1].isdigit():
+ capture = cvCreateCameraCapture( int(sys.argv[1]) )
+ elif len(sys.argv)==2:
+ capture = cvCreateFileCapture( sys.argv[1] )
+
+ if not capture:
+ print "Could not initialize capturing..."
+ sys.exit(-1)
+
+ cvNamedWindow( "Laplacian", 1 )
+
+ while True:
+ frame = cvQueryFrame( capture )
+ if not frame:
+ cvWaitKey(0)
+ break
+
+ if not laplace:
+ for i in range( len(planes) ):
+ planes[i] = cvCreateImage( cvSize(frame.width,frame.height), 8, 1 )
+ laplace = cvCreateImage( cvSize(frame.width,frame.height), IPL_DEPTH_16S, 1 )
+ colorlaplace = cvCreateImage( cvSize(frame.width,frame.height), 8, 3 )
+
+ cvSplit( frame, planes[0], planes[1], planes[2], None )
+ for plane in planes:
+ cvLaplace( plane, laplace, 3 )
+ cvConvertScaleAbs( laplace, plane, 1, 0 )
+
+ cvMerge( planes[0], planes[1], planes[2], None, colorlaplace )
+
+ cvShowImage("Laplacian", colorlaplace )
+
+ if cvWaitKey(10) != -1:
+ break
+
+ cvDestroyWindow("Laplacian")
--- /dev/null
+#!/usr/bin/python
+import sys
+from opencv.cv import *
+from opencv.highgui import *
+
+src=None
+dst=None
+src2=None
+
+def on_mouse( event, x, y, flags, param ):
+
+ if( not src ):
+ return;
+
+ if event==CV_EVENT_LBUTTONDOWN:
+ cvLogPolar( src, dst, cvPoint2D32f(x,y), 40, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS );
+ cvLogPolar( dst, src2, cvPoint2D32f(x,y), 40, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS+CV_WARP_INVERSE_MAP );
+ cvShowImage( "log-polar", dst );
+ cvShowImage( "inverse log-polar", src2 );
+
+if __name__ == "__main__":
+
+ filename = "../c/fruits.jpg"
+ if len(sys.argv)>1:
+ filename=argv[1]
+
+ src = cvLoadImage(filename,1)
+ if not src:
+ print "Could not open %s" % filename
+ sys.exit(-1)
+
+ cvNamedWindow( "original",1 );
+ cvNamedWindow( "log-polar", 1 );
+ cvNamedWindow( "inverse log-polar", 1 );
+
+
+ dst = cvCreateImage( cvSize(256,256), 8, 3 );
+ src2 = cvCreateImage( cvGetSize(src), 8, 3 );
+
+ cvSetMouseCallback( "original", on_mouse );
+ on_mouse( CV_EVENT_LBUTTONDOWN, src.width/2, src.height/2, None, None)
+
+ cvShowImage( "original", src );
+ cvWaitKey();
--- /dev/null
+#!/usr/bin/python
+
+from opencv.cv import *
+from opencv.highgui import *
+from random import randint
+
+def minarea_array(img, count):
+ pointMat = cvCreateMat( count, 1, CV_32SC2 )
+ for i in range(count):
+ pointMat[i] = cvPoint( randint(img.width/4, img.width*3/4),
+ randint(img.height/4, img.height*3/4) )
+
+ box = cvMinAreaRect2( pointMat )
+ box_vtx = cvBoxPoints( box )
+ success, center, radius = cvMinEnclosingCircle( pointMat )
+ cvZero( img )
+ for i in range(count):
+ cvCircle( img, cvGet1D(pointMat,i), 2, CV_RGB( 255, 0, 0 ), CV_FILLED, CV_AA, 0 )
+
+ box_vtx = [cvPointFrom32f(box_vtx[0]),
+ cvPointFrom32f(box_vtx[1]),
+ cvPointFrom32f(box_vtx[2]),
+ cvPointFrom32f(box_vtx[3])]
+ cvCircle( img, cvPointFrom32f(center), cvRound(radius), CV_RGB(255, 255, 0), 1, CV_AA, 0 )
+ cvPolyLine( img, [box_vtx], 1, CV_RGB(0,255,255), 1, CV_AA )
+
+
+
+def minarea_seq(img, count, storage):
+ ptseq = cvCreateSeq( CV_SEQ_KIND_GENERIC | CV_32SC2, sizeof_CvContour, sizeof_CvPoint, storage )
+ ptseq = CvSeq_CvPoint.cast( ptseq )
+ for i in range(count):
+ pt0 = cvPoint( randint(img.width/4, img.width*3/4),
+ randint(img.height/4, img.height*3/4) )
+ cvSeqPush( ptseq, pt0 )
+ box = cvMinAreaRect2( ptseq )
+ box_vtx = cvBoxPoints( box )
+ success, center, radius = cvMinEnclosingCircle( ptseq )
+ cvZero( img )
+ for pt in ptseq:
+ cvCircle( img, pt, 2, CV_RGB( 255, 0, 0 ), CV_FILLED, CV_AA, 0 )
+
+ box_vtx = [cvPointFrom32f(box_vtx[0]),
+ cvPointFrom32f(box_vtx[1]),
+ cvPointFrom32f(box_vtx[2]),
+ cvPointFrom32f(box_vtx[3])]
+ cvCircle( img, cvPointFrom32f(center), cvRound(radius), CV_RGB(255, 255, 0), 1, CV_AA, 0 )
+ cvPolyLine( img, [box_vtx], 1, CV_RGB(0,255,255), 1, CV_AA )
+ cvClearMemStorage( storage )
+
+if __name__ == "__main__":
+ img = cvCreateImage( cvSize( 500, 500 ), 8, 3 );
+ storage = cvCreateMemStorage(0);
+
+ cvNamedWindow( "rect & circle", 1 );
+
+ use_seq=True
+
+ while True:
+ count = randint(1,100)
+ if use_seq:
+ minarea_seq(img, count, storage)
+ else:
+ minarea_array(img, count)
+
+ cvShowImage("rect & circle", img)
+ key = cvWaitKey()
+ if( key == '\x1b' ):
+ break;
+
+ use_seq = not use_seq
--- /dev/null
+#! /usr/bin/env python
+
+import opencv
+from opencv import highgui
+
+cap = highgui.cvCreateFileCapture("../c/tree.avi")
+img = highgui.cvQueryFrame(cap)
+print "Got frame of dimensions (", img.width, " x ", img.height, " )"
+
+highgui.cvNamedWindow("win", highgui.CV_WINDOW_AUTOSIZE)
+highgui.cvShowImage("win", img)
+highgui.cvMoveWindow("win", 200, 200)
+highgui.cvWaitKey(0)
+
--- /dev/null
+#!/usr/bin/python
+import sys
+from opencv.cv import *
+from opencv.highgui import *
+src = 0;
+image = 0;
+dest = 0;
+element = 0;
+element_shape = CV_SHAPE_RECT;
+global_pos = 0;
+
+def Opening(pos):
+ element = cvCreateStructuringElementEx( pos*2+1, pos*2+1, pos, pos, element_shape, None );
+ cvErode(src,image,element,1);
+ cvDilate(image,dest,element,1);
+ cvShowImage("Opening&Closing window",dest);
+def Closing(pos):
+ element = cvCreateStructuringElementEx( pos*2+1, pos*2+1, pos, pos, element_shape, None );
+ cvDilate(src,image,element,1);
+ cvErode(image,dest,element,1);
+ cvShowImage("Opening&Closing window",dest);
+def Erosion(pos):
+ element = cvCreateStructuringElementEx( pos*2+1, pos*2+1, pos, pos, element_shape, None );
+ cvErode(src,dest,element,1);
+ cvShowImage("Erosion&Dilation window",dest);
+def Dilation(pos):
+ element = cvCreateStructuringElementEx( pos*2+1, pos*2+1, pos, pos, element_shape, None );
+ cvDilate(src,dest,element,1);
+ cvShowImage("Erosion&Dilation window",dest);
+
+if __name__ == "__main__":
+ filename = "../c/baboon.jpg"
+ if len(sys.argv)==2:
+ filename = sys.argv[1]
+ src = cvLoadImage(filename,1)
+ if not src:
+ sys.exit(-1)
+ image = cvCloneImage(src);
+ dest = cvCloneImage(src);
+ cvNamedWindow("Opening&Closing window",1);
+ cvNamedWindow("Erosion&Dilation window",1);
+ cvShowImage("Opening&Closing window",src);
+ cvShowImage("Erosion&Dilation window",src);
+ cvCreateTrackbar("Open","Opening&Closing window",global_pos,10,Opening);
+ cvCreateTrackbar("Close","Opening&Closing window",global_pos,10,Closing);
+ cvCreateTrackbar("Dilate","Erosion&Dilation window",global_pos,10,Dilation);
+ cvCreateTrackbar("Erode","Erosion&Dilation window",global_pos,10,Erosion);
+ cvWaitKey(0);
+ cvDestroyWindow("Opening&Closing window");
+ cvDestroyWindow("Erosion&Dilation window");
--- /dev/null
+#!/usr/bin/python
+from opencv.cv import *
+from opencv.highgui import *
+import sys
+import time
+from math import cos,sin
+
+CLOCKS_PER_SEC = 1.0
+MHI_DURATION = 1
+MAX_TIME_DELTA = 0.5
+MIN_TIME_DELTA = 0.05
+N = 4
+buf = range(10)
+last = 0
+mhi = None # MHI
+orient = None # orientation
+mask = None # valid orientation mask
+segmask = None # motion segmentation map
+storage = None # temporary storage
+
+def update_mhi( img, dst, diff_threshold ):
+ global last
+ global mhi
+ global storage
+ global mask
+ global orient
+ global segmask
+ timestamp = time.clock()/CLOCKS_PER_SEC # get current time in seconds
+ size = cvSize(img.width,img.height) # get current frame size
+ idx1 = last
+ if not mhi or mhi.width != size.width or mhi.height != size.height:
+ for i in range( N ):
+ buf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 )
+ cvZero( buf[i] )
+ mhi = cvCreateImage( size, IPL_DEPTH_32F, 1 )
+ cvZero( mhi ) # clear MHI at the beginning
+ orient = cvCreateImage( size, IPL_DEPTH_32F, 1 )
+ segmask = cvCreateImage( size, IPL_DEPTH_32F, 1 )
+ mask = cvCreateImage( size, IPL_DEPTH_8U, 1 )
+
+ cvCvtColor( img, buf[last], CV_BGR2GRAY ) # convert frame to grayscale
+ idx2 = (last + 1) % N # index of (last - (N-1))th frame
+ last = idx2
+ silh = buf[idx2]
+ cvAbsDiff( buf[idx1], buf[idx2], silh ) # get difference between frames
+ cvThreshold( silh, silh, diff_threshold, 1, CV_THRESH_BINARY ) # and threshold it
+ cvUpdateMotionHistory( silh, mhi, timestamp, MHI_DURATION ) # update MHI
+ cvCvtScale( mhi, mask, 255./MHI_DURATION,
+ (MHI_DURATION - timestamp)*255./MHI_DURATION )
+ cvZero( dst )
+ cvMerge( mask, None, None, None, dst )
+ cvCalcMotionGradient( mhi, mask, orient, MAX_TIME_DELTA, MIN_TIME_DELTA, 3 )
+ if( not storage ):
+ storage = cvCreateMemStorage(0)
+ else:
+ cvClearMemStorage(storage)
+ seq = cvSegmentMotion( mhi, segmask, storage, timestamp, MAX_TIME_DELTA )
+ for i in range(-1, seq.total):
+ if( i < 0 ): # case of the whole image
+ comp_rect = cvRect( 0, 0, size.width, size.height )
+ color = CV_RGB(255,255,255)
+ magnitude = 100.
+ else: # i-th motion component
+ comp_rect = seq[i].rect
+ if( comp_rect.width + comp_rect.height < 100 ): # reject very small components
+ continue
+ color = CV_RGB(255,0,0)
+ magnitude = 30.
+ silh_roi = cvGetSubRect(silh, comp_rect)
+ mhi_roi = cvGetSubRect( mhi, comp_rect )
+ orient_roi = cvGetSubRect( orient, comp_rect )
+ mask_roi = cvGetSubRect( mask, comp_rect )
+ angle = cvCalcGlobalOrientation( orient_roi, mask_roi, mhi_roi, timestamp, MHI_DURATION)
+ angle = 360.0 - angle # adjust for images with top-left origin
+ count = cvNorm( silh_roi, None, CV_L1, None ) # calculate number of points within silhouette ROI
+ if( count < comp_rect.width * comp_rect.height * 0.05 ):
+ continue
+ center = cvPoint( (comp_rect.x + comp_rect.width/2),
+ (comp_rect.y + comp_rect.height/2) )
+ cvCircle( dst, center, cvRound(magnitude*1.2), color, 3, CV_AA, 0 )
+ cvLine( dst, center, cvPoint( cvRound( center.x + magnitude*cos(angle*CV_PI/180)),
+ cvRound( center.y - magnitude*sin(angle*CV_PI/180))), color, 3, CV_AA, 0 )
+
+if __name__ == "__main__":
+ motion = 0
+ capture = 0
+
+ if len(sys.argv)==1:
+ capture = cvCreateCameraCapture( 0 )
+ elif len(sys.argv)==2 and sys.argv[1].isdigit():
+ capture = cvCreateCameraCapture( int(sys.argv[1]) )
+ elif len(sys.argv)==2:
+ capture = cvCreateFileCapture( sys.argv[1] )
+
+ if not capture:
+ print "Could not initialize capturing..."
+ sys.exit(-1)
+
+ cvNamedWindow( "Motion", 1 )
+ while True:
+ image = cvQueryFrame( capture )
+ if( image ):
+ if( not motion ):
+ motion = cvCreateImage( cvSize(image.width,image.height), 8, 3 )
+ cvZero( motion )
+ #motion.origin = image.origin
+ update_mhi( image, motion, 30 )
+ cvShowImage( "Motion", motion )
+ if( cvWaitKey(10) != -1 ):
+ break
+ else:
+ break
+ cvDestroyWindow( "Motion" )
--- /dev/null
+#!/usr/bin/python
+import sys
+from opencv.cv import *
+from opencv.highgui import *
+image = [None, None]
+image0 = None
+image1 = None
+threshold1 = 255
+threshold2 = 30
+l = level = 4;
+block_size = 1000;
+filter = CV_GAUSSIAN_5x5;
+storage = None
+min_comp = CvConnectedComp()
+
+def set_thresh1( val ):
+ global threshold1
+ threshold1 = val
+ ON_SEGMENT()
+
+def set_thresh2( val ):
+ global threshold2
+ threshold2 = val
+ ON_SEGMENT()
+
+def ON_SEGMENT():
+ global storage
+ global min_comp
+ comp = cvPyrSegmentation(image0, image1, storage, level, threshold1+1, threshold2+1);
+ cvShowImage("Segmentation", image1);
+
+if __name__ == "__main__":
+ filename = "../c/fruits.jpg";
+ if len(sys.argv) == 2:
+ filename = sys.argv[1]
+ image[0] = cvLoadImage( filename, 1)
+ if not image[0]:
+ print "Error opening %s" % filename
+ sys.exit(-1)
+
+ cvNamedWindow("Source", 0);
+ cvShowImage("Source", image[0]);
+ cvNamedWindow("Segmentation", 0);
+ storage = cvCreateMemStorage ( block_size );
+ image[0].width &= -(1<<level);
+ image[0].height &= -(1<<level);
+ image0 = cvCloneImage( image[0] );
+ image1 = cvCloneImage( image[0] );
+ # segmentation of the color image
+ l = 1;
+ threshold1 =255;
+ threshold2 =30;
+ ON_SEGMENT();
+ sthreshold1 = cvCreateTrackbar("Threshold1", "Segmentation", threshold1, 255, set_thresh1);
+ sthreshold2 = cvCreateTrackbar("Threshold2", "Segmentation", threshold2, 255, set_thresh2);
+ cvShowImage("Segmentation", image1);
+ cvWaitKey(0);
+ cvDestroyWindow("Segmentation");
+ cvDestroyWindow("Source");
--- /dev/null
+#!/usr/bin/python
+#
+# The full "Square Detector" program.
+# It loads several images subsequentally and tries to find squares in
+# each image
+#
+
+from opencv.cv import *
+from opencv.highgui import *
+from math import sqrt
+
+thresh = 50;
+img = None;
+img0 = None;
+storage = None;
+wndname = "Square Detection Demo";
+
+def angle( pt1, pt2, pt0 ):
+ dx1 = pt1.x - pt0.x;
+ dy1 = pt1.y - pt0.y;
+ dx2 = pt2.x - pt0.x;
+ dy2 = pt2.y - pt0.y;
+ return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
+
+def findSquares4( img, storage ):
+ N = 11;
+ sz = cvSize( img.width & -2, img.height & -2 );
+ timg = cvCloneImage( img ); # make a copy of input image
+ gray = cvCreateImage( sz, 8, 1 );
+ pyr = cvCreateImage( cvSize(sz.width/2, sz.height/2), 8, 3 );
+ # create empty sequence that will contain points -
+ # 4 points per square (the square's vertices)
+ squares = cvCreateSeq( 0, sizeof_CvSeq, sizeof_CvPoint, storage );
+ squares = CvSeq_CvPoint.cast( squares )
+
+ # select the maximum ROI in the image
+ # with the width and height divisible by 2
+ subimage = cvGetSubRect( timg, cvRect( 0, 0, sz.width, sz.height ))
+
+ # down-scale and upscale the image to filter out the noise
+ cvPyrDown( subimage, pyr, 7 );
+ cvPyrUp( pyr, subimage, 7 );
+ tgray = cvCreateImage( sz, 8, 1 );
+ # find squares in every color plane of the image
+ for c in range(3):
+ # extract the c-th color plane
+ channels = [None, None, None]
+ channels[c] = tgray
+ cvSplit( subimage, channels[0], channels[1], channels[2], None )
+ for l in range(N):
+ # hack: use Canny instead of zero threshold level.
+ # Canny helps to catch squares with gradient shading
+ if( l == 0 ):
+ # apply Canny. Take the upper threshold from slider
+ # and set the lower to 0 (which forces edges merging)
+ cvCanny( tgray, gray, 0, thresh, 5 );
+ # dilate canny output to remove potential
+ # holes between edge segments
+ cvDilate( gray, gray, None, 1 );
+ else:
+ # apply threshold if l!=0:
+ # tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
+ cvThreshold( tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY );
+
+ # find contours and store them all as a list
+ count, contours = cvFindContours( gray, storage, sizeof_CvContour,
+ CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );
+
+ if not contours:
+ continue
+
+ # test each contour
+ for contour in contours.hrange():
+ # approximate contour with accuracy proportional
+ # to the contour perimeter
+ result = cvApproxPoly( contour, sizeof_CvContour, storage,
+ CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 );
+ # square contours should have 4 vertices after approximation
+ # relatively large area (to filter out noisy contours)
+ # and be convex.
+ # Note: absolute value of an area is used because
+ # area may be positive or negative - in accordance with the
+ # contour orientation
+ if( result.total == 4 and
+ abs(cvContourArea(result)) > 1000 and
+ cvCheckContourConvexity(result) ):
+ s = 0;
+ for i in range(5):
+ # find minimum angle between joint
+ # edges (maximum of cosine)
+ if( i >= 2 ):
+ t = abs(angle( result[i], result[i-2], result[i-1]))
+ if s<t:
+ s=t
+ # if cosines of all angles are small
+ # (all angles are ~90 degree) then write quandrange
+ # vertices to resultant sequence
+ if( s < 0.3 ):
+ for i in range(4):
+ squares.append( result[i] )
+
+ return squares;
+
+# the function draws all the squares in the image
+def drawSquares( img, squares ):
+ cpy = cvCloneImage( img );
+ # read 4 sequence elements at a time (all vertices of a square)
+ i=0
+ while i<squares.total:
+ pt = []
+ # read 4 vertices
+ pt.append( squares[i] )
+ pt.append( squares[i+1] )
+ pt.append( squares[i+2] )
+ pt.append( squares[i+3] )
+
+ # draw the square as a closed polyline
+ cvPolyLine( cpy, [pt], 1, CV_RGB(0,255,0), 3, CV_AA, 0 );
+ i+=4
+
+ # show the resultant image
+ cvShowImage( wndname, cpy );
+
+def on_trackbar( a ):
+ if( img ):
+ drawSquares( img, findSquares4( img, storage ) );
+
+names = ["../c/pic1.png", "../c/pic2.png", "../c/pic3.png",
+ "../c/pic4.png", "../c/pic5.png", "../c/pic6.png" ];
+
+if __name__ == "__main__":
+ # create memory storage that will contain all the dynamic data
+ storage = cvCreateMemStorage(0);
+ for name in names:
+ img0 = cvLoadImage( name, 1 );
+ if not img0:
+ print "Couldn't load %s" % name
+ continue;
+ img = cvCloneImage( img0 );
+ # create window and a trackbar (slider) with parent "image" and set callback
+ # (the slider regulates upper threshold, passed to Canny edge detector)
+ cvNamedWindow( wndname, 1 );
+ cvCreateTrackbar( "canny thresh", wndname, thresh, 1000, on_trackbar );
+ # force the image processing
+ on_trackbar(0);
+ # wait for key.
+ # Also the function cvWaitKey takes care of event processing
+ c = cvWaitKey(0);
+ # clear memory storage - reset free space position
+ cvClearMemStorage( storage );
+ if( c == '\x1b' ):
+ break;
+ cvDestroyWindow( wndname );
--- /dev/null
+#!/usr/bin/python
+from opencv.cv import *
+from opencv.highgui import *
+import sys
+
+marker_mask = None;
+markers = None;
+img0 = None
+img = None
+img_gray = None
+wshed = None
+prev_pt = cvPoint(-1,-1)
+
+def on_mouse( event, x, y, flags, param ):
+ global prev_pt
+ if( not img ):
+ return;
+ if( event == CV_EVENT_LBUTTONUP or not (flags & CV_EVENT_FLAG_LBUTTON) ):
+ prev_pt = cvPoint(-1,-1);
+ elif( event == CV_EVENT_LBUTTONDOWN ):
+ prev_pt = cvPoint(x,y);
+ elif( event == CV_EVENT_MOUSEMOVE and (flags & CV_EVENT_FLAG_LBUTTON) ):
+ pt = cvPoint(x,y);
+ if( prev_pt.x < 0 ):
+ prev_pt = pt;
+ cvLine( marker_mask, prev_pt, pt, cvScalarAll(255), 5, 8, 0 );
+ cvLine( img, prev_pt, pt, cvScalarAll(255), 5, 8, 0 );
+ prev_pt = pt;
+ cvShowImage( "image", img );
+
+if __name__ == "__main__":
+ filename = "../c/fruits.jpg"
+ if len(sys.argv)>1:
+ filename = sys.argv[1]
+
+ rng = cvRNG(-1);
+ img0 = cvLoadImage(filename,1)
+ if not img0:
+ print "Error opening image '%s'" % filename
+ sys.exit(-1)
+
+ print "Hot keys:"
+ print "\tESC - quit the program"
+ print "\tr - restore the original image"
+ print "\tw - run watershed algorithm"
+ print "\t (before that, roughly outline several markers on the image)"
+
+ cvNamedWindow( "image", 1 );
+ cvNamedWindow( "watershed transform", 1 );
+
+ img = cvCloneImage( img0 );
+ img_gray = cvCloneImage( img0 );
+ wshed = cvCloneImage( img0 );
+ marker_mask = cvCreateImage( cvGetSize(img), 8, 1 );
+ markers = cvCreateImage( cvGetSize(img), IPL_DEPTH_32S, 1 );
+
+ cvCvtColor( img, marker_mask, CV_BGR2GRAY );
+ cvCvtColor( marker_mask, img_gray, CV_GRAY2BGR );
+
+ cvZero( marker_mask );
+ cvZero( wshed );
+
+ cvShowImage( "image", img );
+ cvShowImage( "watershed transform", wshed );
+
+ cvSetMouseCallback( "image", on_mouse, None );
+ while True:
+ c = cvWaitKey(0);
+ if c=='\x1b':
+ break;
+ if c == 'r':
+ cvZero( marker_mask );
+ cvCopy( img0, img );
+ cvShowImage( "image", img );
+ if c == 'w':
+ storage = cvCreateMemStorage(0);
+ comp_count = 0;
+ #cvSaveImage( "wshed_mask.png", marker_mask );
+ #marker_mask = cvLoadImage( "wshed_mask.png", 0 );
+ nb_cont, contours = cvFindContours( marker_mask, storage, sizeof_CvContour,
+ CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
+ cvZero( markers );
+ while contours:
+ cvDrawContours( markers, contours, cvScalarAll(comp_count+1),
+ cvScalarAll(comp_count+1), -1, -1, 8, cvPoint(0,0) );
+ contours=contours.h_next
+ comp_count+=1
+ color_tab = cvCreateMat( comp_count, 1, CV_8UC3 );
+ for i in range(comp_count):
+ color_tab[i] = cvScalar( cvRandInt(rng)%180 + 50,
+ cvRandInt(rng)%180 + 50,
+ cvRandInt(rng)%180 + 50 );
+ t = cvGetTickCount();
+ cvWatershed( img0, markers );
+ t = cvGetTickCount() - t;
+ #print "exec time = %f" % t/(cvGetTickFrequency()*1000.)
+
+ cvSet( wshed, cvScalarAll(255) );
+
+ # paint the watershed image
+ for j in range(markers.height):
+ for i in range(markers.width):
+ idx = markers[j,i]
+ if idx==-1:
+ continue
+ idx = idx-1
+ wshed[j,i] = color_tab[idx,0]
+
+ cvAddWeighted( wshed, 0.5, img_gray, 0.5, 0, wshed );
+ cvShowImage( "watershed transform", wshed );
+ cvWaitKey();