mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
4.5 KiB
115 lines
4.5 KiB
#!/usr/bin/env python |
|
|
|
import cv |
|
|
|
def is_rect_nonzero(r): |
|
(_,_,w,h) = r |
|
return (w > 0) and (h > 0) |
|
|
|
class CamShiftDemo: |
|
|
|
def __init__(self): |
|
self.capture = cv.CaptureFromCAM(0) |
|
cv.NamedWindow( "CamShiftDemo", 1 ) |
|
cv.NamedWindow( "Histogram", 1 ) |
|
cv.SetMouseCallback( "CamShiftDemo", self.on_mouse) |
|
|
|
self.drag_start = None # Set to (x,y) when mouse starts drag |
|
self.track_window = None # Set to rect when the mouse drag finishes |
|
|
|
print( "Keys:\n" |
|
" ESC - quit the program\n" |
|
" b - switch to/from backprojection view\n" |
|
"To initialize tracking, drag across the object with the mouse\n" ) |
|
|
|
def hue_histogram_as_image(self, hist): |
|
""" Returns a nice representation of a hue histogram """ |
|
|
|
histimg_hsv = cv.CreateImage( (320,200), 8, 3) |
|
|
|
mybins = cv.CloneMatND(hist.bins) |
|
cv.Log(mybins, mybins) |
|
(_, hi, _, _) = cv.MinMaxLoc(mybins) |
|
cv.ConvertScale(mybins, mybins, 255. / hi) |
|
|
|
w,h = cv.GetSize(histimg_hsv) |
|
hdims = cv.GetDims(mybins)[0] |
|
for x in range(w): |
|
xh = (180 * x) / (w - 1) # hue sweeps from 0-180 across the image |
|
val = int(mybins[int(hdims * x / w)] * h / 255) |
|
cv.Rectangle( histimg_hsv, (x, 0), (x, h-val), (xh,255,64), -1) |
|
cv.Rectangle( histimg_hsv, (x, h-val), (x, h), (xh,255,255), -1) |
|
|
|
histimg = cv.CreateImage( (320,200), 8, 3) |
|
cv.CvtColor(histimg_hsv, histimg, cv.CV_HSV2BGR) |
|
return histimg |
|
|
|
def on_mouse(self, event, x, y, flags, param): |
|
if event == cv.CV_EVENT_LBUTTONDOWN: |
|
self.drag_start = (x, y) |
|
if event == cv.CV_EVENT_LBUTTONUP: |
|
self.drag_start = None |
|
self.track_window = self.selection |
|
if self.drag_start: |
|
xmin = min(x, self.drag_start[0]) |
|
ymin = min(y, self.drag_start[1]) |
|
xmax = max(x, self.drag_start[0]) |
|
ymax = max(y, self.drag_start[1]) |
|
self.selection = (xmin, ymin, xmax - xmin, ymax - ymin) |
|
|
|
def run(self): |
|
hist = cv.CreateHist([180], cv.CV_HIST_ARRAY, [(0,180)], 1 ) |
|
backproject_mode = False |
|
while True: |
|
frame = cv.QueryFrame( self.capture ) |
|
|
|
# Convert to HSV and keep the hue |
|
hsv = cv.CreateImage(cv.GetSize(frame), 8, 3) |
|
cv.CvtColor(frame, hsv, cv.CV_BGR2HSV) |
|
self.hue = cv.CreateImage(cv.GetSize(frame), 8, 1) |
|
cv.Split(hsv, self.hue, None, None, None) |
|
|
|
# Compute back projection |
|
backproject = cv.CreateImage(cv.GetSize(frame), 8, 1) |
|
|
|
# Run the cam-shift |
|
cv.CalcArrBackProject( [self.hue], backproject, hist ) |
|
if self.track_window and is_rect_nonzero(self.track_window): |
|
crit = ( cv.CV_TERMCRIT_EPS | cv.CV_TERMCRIT_ITER, 10, 1) |
|
(iters, (area, value, rect), track_box) = cv.CamShift(backproject, self.track_window, crit) |
|
self.track_window = rect |
|
|
|
# If mouse is pressed, highlight the current selected rectangle |
|
# and recompute the histogram |
|
|
|
if self.drag_start and is_rect_nonzero(self.selection): |
|
sub = cv.GetSubRect(frame, self.selection) |
|
save = cv.CloneMat(sub) |
|
cv.ConvertScale(frame, frame, 0.5) |
|
cv.Copy(save, sub) |
|
x,y,w,h = self.selection |
|
cv.Rectangle(frame, (x,y), (x+w,y+h), (255,255,255)) |
|
|
|
sel = cv.GetSubRect(self.hue, self.selection ) |
|
cv.CalcArrHist( [sel], hist, 0) |
|
(_, max_val, _, _) = cv.GetMinMaxHistValue( hist) |
|
if max_val != 0: |
|
cv.ConvertScale(hist.bins, hist.bins, 255. / max_val) |
|
elif self.track_window and is_rect_nonzero(self.track_window): |
|
cv.EllipseBox( frame, track_box, cv.CV_RGB(255,0,0), 3, cv.CV_AA, 0 ) |
|
|
|
if not backproject_mode: |
|
cv.ShowImage( "CamShiftDemo", frame ) |
|
else: |
|
cv.ShowImage( "CamShiftDemo", backproject) |
|
cv.ShowImage( "Histogram", self.hue_histogram_as_image(hist)) |
|
|
|
c = cv.WaitKey(7) % 0x100 |
|
if c == 27: |
|
break |
|
elif c == ord("b"): |
|
backproject_mode = not backproject_mode |
|
|
|
if __name__=="__main__": |
|
demo = CamShiftDemo() |
|
demo.run()
|
|
|