|
|
Line 12: |
Line 12: |
| | | |
| Jian Li | | Jian Li |
− |
| |
− | ==Code==
| |
− | OpenCV (C++)
| |
− |
| |
− | === void loadTemplateImage() ===
| |
− | Get the color of the hand, so that we can track the movement of the hand automatically.
| |
− | <pre>
| |
− | {
| |
− |
| |
− | IplImage *tempimage = cvLoadImage("/home/dica/workspace/cvex1/sshou.bmp",1);
| |
− |
| |
− | cvCvtColor( tempimage, hsv, CV_BGR2HSV );
| |
− |
| |
− | int _vmin = vmin, _vmax = vmax;
| |
− |
| |
− | cvInRangeS( hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0),
| |
− | cvScalar(180,256,MAX(_vmin,_vmax),0), mask );
| |
− |
| |
− | cvSplit( hsv, hue, 0, 0, 0 );
| |
− |
| |
− | selection.x = 1;
| |
− |
| |
− | selection.y = 1;
| |
− |
| |
− | selection.width = 320-1;
| |
− |
| |
− | selection.height= 240-1;
| |
− |
| |
− | cvSetImageROI( hue, selection );
| |
− |
| |
− | cvSetImageROI( mask, selection );
| |
− |
| |
− | cvCalcHist( &hue, hist, 0, mask );
| |
− |
| |
− | float max_val = 0.f;
| |
− |
| |
− | cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );
| |
− |
| |
− | cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 );
| |
− |
| |
− | cvResetImageROI( hue );
| |
− |
| |
− | cvResetImageROI( mask );
| |
− |
| |
− | track_window = selection;
| |
− |
| |
− | track_object = 1;
| |
− |
| |
− |
| |
− | cvZero( histimg );
| |
− |
| |
− | int bin_w = histimg->width / hdims;
| |
− |
| |
− | for(int i = 0; i < hdims; i++ )
| |
− |
| |
− |
| |
− | {
| |
− |
| |
− | int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 );
| |
− |
| |
− | CvScalar color = hsv2rgb(i*180.f/hdims);
| |
− |
| |
− | cvRectangle( histimg, cvPoint(i*bin_w,histimg->height),
| |
− |
| |
− | cvPoint((i+1)*bin_w,histimg->height - val),
| |
− |
| |
− | color, -1, 8, 0 );
| |
− |
| |
− | }
| |
− |
| |
− | cvReleaseImage(&tempimage);
| |
− |
| |
− | }
| |
− | </pre>
| |
− |
| |
− |
| |
− |
| |
− |
| |
− | === int main( int argc, char** argv ) ===
| |
− | create window, get the color of the hand and then track the movement of the hand
| |
− | <pre>
| |
− | {
| |
− | CvCapture* capture = 0;
| |
− |
| |
− | if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
| |
− | capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
| |
− | else if( argc == 2 )
| |
− | capture = cvCaptureFromAVI( argv[1] );
| |
− |
| |
− | if( !capture )
| |
− | {
| |
− | fprintf(stderr,"Could not initialize capturing...\n");
| |
− | return -1;
| |
− | }
| |
− |
| |
− | cvNamedWindow( "CamShiftDemo", 1 );
| |
− | cvNamedWindow( "Histogram", 1 );
| |
− |
| |
− | for(;;)
| |
− | {
| |
− | IplImage* frame = 0;
| |
− | int i, bin_w, c;
| |
− |
| |
− | frame = cvQueryFrame( capture );
| |
− | if( !frame )
| |
− | break;
| |
− |
| |
− | if( !image )
| |
− | {
| |
− | /* allocate all the buffers */
| |
− | image = cvCreateImage( cvGetSize(frame), 8, 3 );
| |
− | image->origin = frame->origin;
| |
− | hsv = cvCreateImage( cvGetSize(frame), 8, 3 );
| |
− | hue = cvCreateImage( cvGetSize(frame), 8, 1 );
| |
− | mask = cvCreateImage( cvGetSize(frame), 8, 1 );
| |
− | backproject = cvCreateImage( cvGetSize(frame), 8, 1 );
| |
− | hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 );
| |
− | histimg = cvCreateImage( cvSize(320,200), 8, 3 );
| |
− | cvZero( histimg );
| |
− | loadTemplateImage();
| |
− | }
| |
− |
| |
− | cvCopy( frame, image, 0 );
| |
− | cvCvtColor( image, hsv, CV_BGR2HSV );
| |
− |
| |
− | if( track_object )
| |
− | {
| |
− | int _vmin = vmin, _vmax = vmax;
| |
− |
| |
− | cvInRangeS( hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0),
| |
− | cvScalar(180,256,MAX(_vmin,_vmax),0), mask );
| |
− | cvSplit( hsv, hue, 0, 0, 0 );
| |
− |
| |
− | if( track_object < 0 )
| |
− | {
| |
− | float max_val = 0.f;
| |
− | cvSetImageROI( hue, selection );
| |
− | cvSetImageROI( mask, selection );
| |
− | cvCalcHist( &hue, hist, 0, mask );
| |
− | cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );
| |
− | cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 );
| |
− | cvResetImageROI( hue );
| |
− | cvResetImageROI( mask );
| |
− | track_window = selection;
| |
− | track_object = 1;
| |
− |
| |
− | cvZero( histimg );
| |
− | bin_w = histimg->width / hdims;
| |
− | for( i = 0; i < hdims; i++ )
| |
− | {
| |
− | int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 );
| |
− | CvScalar color = hsv2rgb(i*180.f/hdims);
| |
− | cvRectangle( histimg, cvPoint(i*bin_w,histimg->height),
| |
− | cvPoint((i+1)*bin_w,histimg->height - val),
| |
− | color, -1, 8, 0 );
| |
− | }
| |
− | }
| |
− |
| |
− | cvCalcBackProject( &hue, backproject, hist );
| |
− | cvAnd( backproject, mask, backproject, 0 );
| |
− | cvCamShift( backproject, track_window,
| |
− | cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),
| |
− | &track_comp, &track_box );
| |
− | track_window = track_comp.rect;
| |
− |
| |
− | if( backproject_mode )
| |
− | cvCvtColor( backproject, image, CV_GRAY2BGR );
| |
− | if( !image->origin )
| |
− | track_box.angle = -track_box.angle;
| |
− | cvEllipseBox( image, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 );
| |
− | }
| |
− |
| |
− | if( select_object && selection.width > 0 && selection.height > 0 )
| |
− | {
| |
− | cvSetImageROI( image, selection );
| |
− | cvXorS( image, cvScalarAll(255), image, 0 );
| |
− | cvResetImageROI( image );
| |
− | }
| |
− |
| |
− | cvShowImage( "CamShiftDemo", image );
| |
− | cvShowImage( "Histogram", histimg );
| |
− |
| |
− | }
| |
− | }
| |
− |
| |
− | return 0;
| |
− | }
| |
− |
| |
− | </pre>
| |
− | ===PyPong.py===
| |
− | <pre>
| |
− | #! /usr/bin/env python
| |
− |
| |
− |
| |
− |
| |
− | # PyPong - an arcade Pong game programmed in Python
| |
− |
| |
− | # Created by pymike, released to the Public Domain
| |
− |
| |
− | import sys, os
| |
− | import random
| |
− |
| |
− | import pygame
| |
− | from pygame.locals import *
| |
− |
| |
− | HUMAN = 1
| |
− | COM = 2
| |
− |
| |
− | class Player(pygame.sprite.Sprite):
| |
− |
| |
− | def __init__(self):
| |
− | pygame.sprite.Sprite.__init__(self, self.containers)
| |
− | self.image = pygame.Surface((16, 64))
| |
− | self.image.fill((255, 255, 255), (2, 0, 12, 64))
| |
− | self.image.fill((255, 255, 255), (0, 2, 16, 60))
| |
− | self.rect = self.image.get_rect(midleft = (16, 240))
| |
− | self._rect = Rect(self.rect)
| |
− |
| |
− | def update(self):
| |
− | self._rect = Rect(self.rect)
| |
− |
| |
− | key = pygame.key.get_pressed()
| |
− | if key[K_UP]:
| |
− | self.rect.move_ip(0, -5)
| |
− | if key[K_DOWN]:
| |
− | self.rect.move_ip(0, 5)
| |
− |
| |
− | if self.rect.bottom > 480:
| |
− | self.rect.bottom = 480
| |
− | if self.rect.top < 0:
| |
− | self.rect.top = 0
| |
− |
| |
− | class Computer(pygame.sprite.Sprite):
| |
− |
| |
− | def __init__(self, ball):
| |
− | pygame.sprite.Sprite.__init__(self, self.containers)
| |
− | self.image = pygame.Surface((16, 64))
| |
− | self.image.fill((255, 255, 255), (2, 0, 12, 64))
| |
− | self.image.fill((255, 255, 255), (0, 2, 16, 60))
| |
− | self.rect = self.image.get_rect(midleft = (640-32, 240))
| |
− | self._rect = Rect(self.rect)
| |
− | self.ball = ball
| |
− | self.speed = 4
| |
− | self.max_speed = self.speed
| |
− |
| |
− | def update(self):
| |
− | self._rect = Rect(self.rect)
| |
− |
| |
− | if abs(self.ball.vy) < self.max_speed:
| |
− | self.speed = abs(self.ball.vy)
| |
− | else:
| |
− | self.speed = self.max_speed
| |
− |
| |
− | if self.ball.rect.centery > self.rect.centery:
| |
− | self.rect.move_ip(0, self.speed)
| |
− | if self.ball.rect.centery < self.rect.centery:
| |
− | self.rect.move_ip(0, -self.speed)
| |
− |
| |
− | if self.rect.bottom > 480:
| |
− | self.rect.bottom = 480
| |
− | if self.rect.top < 0:
| |
− | self.rect.top = 0
| |
− |
| |
− | def set_ball(self, ball):
| |
− | self.ball = ball
| |
− |
| |
− | class Ball(pygame.sprite.Sprite):
| |
− |
| |
− | def __init__(self):
| |
− | pygame.sprite.Sprite.__init__(self, self.containers)
| |
− | self.image = pygame.Surface((12, 12))
| |
− | self.image.fill((255, 255, 255), (2, 0, 8, 12))
| |
− | self.image.fill((255, 255, 255), (0, 2, 12, 8))
| |
− | self.rect = self.image.get_rect(midleft = (320, 240))
| |
− | self._rect = Rect(self.rect)
| |
− | self.vx = random.choice([5, -5])
| |
− | self.vy = random.choice([-2, -1, 1, 2])
| |
− | self.scored = 0
| |
− |
| |
− | def update(self):
| |
− | self._rect = Rect(self.rect)
| |
− | self.rect.move_ip(self.vx, self.vy)
| |
− |
| |
− | if self.rect.bottom > 480:
| |
− | self.rect.bottom = 480
| |
− | self.vy = -self.vy
| |
− | if self.rect.top < 0:
| |
− | self.rect.top = 0
| |
− | self.vy = -self.vy
| |
− | if self.rect.left < 0:
| |
− | self.kill()
| |
− | self.scored = COM
| |
− | if self.rect.right > 640:
| |
− | self.kill()
| |
− | self.scored = HUMAN
| |
− |
| |
− | def collide(self, bat):
| |
− | if self.rect.colliderect(bat.rect) and not self._rect.colliderect(bat._rect):
| |
− | if self._rect.right <= bat._rect.left and self.rect.right > bat.rect.left:
| |
− | self.rect.right = bat.rect.left
| |
− | self.vx = -self.vx
| |
− | if self._rect.left >= bat._rect.right and self.rect.left < bat.rect.right:
| |
− | self.rect.left = bat.rect.right
| |
− | self.vx = -self.vx
| |
− | self.vx += 1
| |
− | if self.rect.centery < bat.rect.centery:
| |
− | self.vy = ((self.rect.centery-bat.rect.centery)/(bat.rect.height/2))*4.5
| |
− | if self.vy >= -1:
| |
− | self.vy = -1
| |
− | if self.rect.centery > bat.rect.centery:
| |
− | self.vy = ((self.rect.centery-bat.rect.centery)/(bat.rect.height/2))*4.5
| |
− | if self.vy <= 1:
| |
− | self.vy = 1
| |
− | if self._rect.bottom <= bat._rect.top and self.rect.bottom > bat.rect.top:
| |
− | self.rect.bottom = bat.rect.top
| |
− | self.vy = -self.vy
| |
− | if self._rect.top >= bat._rect.bottom and self.rect.top < bat.rect.bottom:
| |
− | self.rect.top = bat.rect.bottom
| |
− | self.vy = -self.vy
| |
− |
| |
− | class Menu:
| |
− |
| |
− | def __init__(self, screen):
| |
− | self.screen = screen
| |
− | self.font = pygame.font.SysFont("Comic Sans MS", 100)
| |
− | self.font2 = pygame.font.SysFont("Comic Sans MS", 50)
| |
− | self.font3 = pygame.font.SysFont("Comic Sans MS", 25)
| |
− |
| |
− | self.all = pygame.sprite.RenderUpdates()
| |
− | Computer.containers = self.all
| |
− | Ball.containers = self.all
| |
− |
| |
− | self.ball = Ball()
| |
− | self.com1 = Computer(self.ball)
| |
− | self.com2 = Computer(self.ball)
| |
− | self.com1.rect.left = 16
| |
− | self.clock = pygame.time.Clock()
| |
− | self.timer = 0
| |
− |
| |
− | def loop(self):
| |
− | while 1:
| |
− |
| |
− | self.clock.tick(60)
| |
− | self.all.update()
| |
− | self.timer += 1
| |
− | if self.timer >= 50:
| |
− | self.timer = 0
| |
− |
| |
− | for e in pygame.event.get():
| |
− | if e.type == QUIT:
| |
− | pygame.quit()
| |
− | sys.exit()
| |
− | if e.type == KEYDOWN:
| |
− | if e.key == K_ESCAPE:
| |
− | pygame.quit()
| |
− | sys.exit()
| |
− | if e.key == K_SPACE:
| |
− | game = Game(self.screen)
| |
− | game.loop()
| |
− |
| |
− | self.screen.fill((0, 0, 0))
| |
− | self.ball.collide(self.com1)
| |
− | self.ball.collide(self.com2)
| |
− | self.all.draw(self.screen)
| |
− | ren = self.font.render("PyPong", 1, (255, 255, 255))
| |
− | self.screen.blit(ren, (320-ren.get_width()/2, 20))
| |
− | ren = self.font3.render("March 2008", 1, (255, 255, 255))
| |
− | self.screen.blit(ren, (320-ren.get_width()/2, 220))
| |
− | ren = self.font3.render("by PyMike", 1, (255, 255, 255))
| |
− | self.screen.blit(ren, (320-ren.get_width()/2, 250))
| |
− | ren = self.font2.render("Press Space", 1, (255, 255, 255))
| |
− | if self.timer <= 25:
| |
− | self.screen.blit(ren, (320-ren.get_width()/2, 350))
| |
− | pygame.display.flip()
| |
− |
| |
− | class Game:
| |
− |
| |
− | def __init__(self, screen):
| |
− | self.screen = screen
| |
− |
| |
− | self.all = pygame.sprite.RenderUpdates()
| |
− | Player.containers = self.all
| |
− | Computer.containers = self.all
| |
− | Ball.containers = self.all
| |
− |
| |
− | self.ball = Ball()
| |
− | self.player = Player()
| |
− | self.com = Computer(self.ball)
| |
− | self.clock = pygame.time.Clock()
| |
− |
| |
− | self.p1score = 0
| |
− | self.p2score = 0
| |
− | self.win_score = 21
| |
− | self.font = pygame.font.SysFont("Comic Sans MS", 50)
| |
− | self.font2 = pygame.font.SysFont("Comic Sans MS", 30)
| |
− | self.won = False
| |
− | self.served = False
| |
− | self.done = False
| |
− |
| |
− | def handle_input(self):
| |
− | for e in pygame.event.get():
| |
− | if e.type == QUIT:
| |
− | self.pygame.quit()
| |
− | sys.exit()
| |
− | if e.type == KEYDOWN:
| |
− | if e.key == K_ESCAPE:
| |
− | self.done = True
| |
− | if e.key == K_SPACE:
| |
− | self.served = True
| |
− | self.ball = Ball()
| |
− | self.com.set_ball(self.ball)
| |
− |
| |
− | def render(self):
| |
− | self.screen.fill((0, 0, 0))
| |
− | self.all.draw(self.screen)
| |
− | ren = self.font.render("%s:%s" % (self.p1score, self.p2score), 1, (255, 255, 255))
| |
− | self.screen.blit(ren, (320-ren.get_width()/2, 10))
| |
− | if self.won == HUMAN:
| |
− | ren = self.font.render("Player 1 won!", 1, (255, 255, 255))
| |
− | self.screen.blit(ren, (320-ren.get_width()/2, 240-ren.get_height()/2))
| |
− | if self.won == COM:
| |
− | ren = self.font.render("Com won!", 1, (255, 255, 255))
| |
− | self.screen.blit(ren, (320-ren.get_width()/2, 240-ren.get_height()/2))
| |
− | if not self.served and not self.won:
| |
− | ren = self.font2.render("Press Space to Serve", 1, (255, 255, 255))
| |
− | self.screen.blit(ren, (320-ren.get_width()/2, 240-ren.get_height()/2))
| |
− | pygame.display.flip()
| |
− |
| |
− | def update(self):
| |
− | self.clock.tick(60)
| |
− | if not self.won and self.served:
| |
− | self.all.update()
| |
− | self.ball.collide(self.player)
| |
− | self.ball.collide(self.com)
| |
− |
| |
− | if self.p1score >= self.win_score:
| |
− | self.won = HUMAN
| |
− | if self.p2score >= self.win_score:
| |
− | self.won = COM
| |
− |
| |
− | if not self.ball.alive() and not self.won:
| |
− | if self.ball.scored == HUMAN:
| |
− | self.p1score += 1
| |
− | if self.ball.scored == COM:
| |
− | self.p2score += 1
| |
− | self.ball = Ball()
| |
− | self.com.set_ball(self.ball)
| |
− | self.served = False
| |
− |
| |
− | if self.won or not self.served:
| |
− | self.ball.kill()
| |
− |
| |
− | def loop(self):
| |
− | self.done = False
| |
− | while not self.done:
| |
− | self.update()
| |
− | self.handle_input()
| |
− | self.render()
| |
− |
| |
− | def main():
| |
− | pygame.init()
| |
− | os.environ["SDL_VIDEO_CENTERED"] = "1"
| |
− | pygame.display.set_caption("PyPong")
| |
− | screen = pygame.display.set_mode((640, 480))
| |
− | menu = Menu(screen)
| |
− | menu.loop()
| |
− |
| |
− |
| |
− | if __name__ == "__main__":
| |
− |
| |
− | main()
| |
− | </pre>
| |
| | | |
| ==System Setup== | | ==System Setup== |
Line 520: |
Line 48: |
| ==Files== | | ==Files== |
| [[File:PyPong.tgz]] | | [[File:PyPong.tgz]] |
| + | |
| [[File:cvex1.zip]] | | [[File:cvex1.zip]] |
| | | |