This is a simple example of solving the task of constructing a cyclist's skeleton using the reflective balls on his equipment.
Captured and processed frame from the video (the face in this picture was blurred in another program before publishing):
Code: Select all
; AAT
;
IncludeFile "includes/cv_functions.pbi"
;
; Select the video source here:
;
#WebCam = 0 ; > --------+
#Video = 1 ; > --------+
; |
#VideoSource = #Video ; <---------+
#WriteSkeleton = #True ; #True, if you need to write the processed video to a file
#WriteFileName = "C:\Skeleton\1.avi" ; the folder for the file must exist before recording starts
#MinArea = 30
#MaxArea = 300
#CV_WINDOW_NAME = "Cyclist's skeleton"
#CV_DESCRIPTION = "How to get cyclist's skeleton by using glowing spheres and the OpenCV package + #LF$ + #LF$ + SpaceKey - capture the frame and save it"
Structure xy
x.l
y.l
EndStructure
Global lpPrevWndFunc
Global Dim sk.xy(7), Dim sk1.xy(7)
Procedure WindowCallback(hWnd, uMsg, wParam, lParam)
Shared exitCV
Select uMsg
Case #WM_COMMAND
Select wParam
Case 10
exitCV = #True
EndSelect
Case #WM_DESTROY
exitCV = #True
EndSelect
ProcedureReturn CallWindowProc_(lpPrevWndFunc, hWnd, uMsg, wParam, lParam)
EndProcedure
Procedure CvMouseCallback(event, x.l, y.l, flags, *param.CvUserData)
Select event
Case #CV_EVENT_RBUTTONDOWN
DisplayPopupMenu(0, *param\Value)
EndSelect
EndProcedure
CompilerIf #VideoSource = #WebCam
Repeat
nCreate + 1
*capture = cvCreateCameraCapture(0)
Until nCreate = 5 Or *capture
CompilerElseIf #VideoSource = #Video
Pattern$ = "MP4 (*.mp4)|*.mp4|AVI (*.avi)|*.avi|All files (*.*)|*.*"
PatternPosition = 0
Filename.s = OpenFileRequester("Select video source", "videos/1.mp4", Pattern$, PatternPosition)
If FileSize(Filename) > 0
*capture.CvCapture = cvCreateFileCapture(Filename)
Else
MessageRequester(#CV_WINDOW_NAME, "Video not selected.", #MB_ICONERROR)
EndIf
CompilerEndIf
If *capture
*image.IplImage
*storage.CvMemStorage = cvCreateMemStorage(0)
*contours.CvSeq
*poly.CvContour
moments.CvMoments
CompilerIf #WriteSkeleton = #True
FrameWidth = cvGetCaptureProperty(*capture, #CV_CAP_PROP_FRAME_WIDTH)
FrameHeight = cvGetCaptureProperty(*capture, #CV_CAP_PROP_FRAME_HEIGHT)
sVideo.s = #WriteFileName
fps.d = cvGetCaptureProperty(*capture, #CV_CAP_PROP_FPS)
*writer.CvVideoWriter = cvCreateVideoWriter(sVideo, CV_FOURCC("X", "V", "I", "D"), fps, FrameWidth, FrameHeight, #True)
If *writer
CompilerEndIf
cvNamedWindow(#CV_WINDOW_NAME, #CV_WINDOW_AUTOSIZE)
window_handle = cvGetWindowHandle(#CV_WINDOW_NAME)
*window_name = cvGetWindowName(window_handle)
lpPrevWndFunc = SetWindowLongPtr_(window_handle, #GWL_WNDPROC, @WindowCallback())
If CreatePopupImageMenu(0, #PB_Menu_ModernLook)
MenuItem(10, "Exit")
EndIf
hWnd = GetParent_(window_handle)
iconCV = LoadImage_(GetModuleHandle_(#Null), @"icons/opencv.ico", #IMAGE_ICON, 35, 32, #LR_LOADFROMFILE)
SendMessage_(hWnd, #WM_SETICON, 0, iconCV)
wStyle = GetWindowLongPtr_(hWnd, #GWL_STYLE)
SetWindowLongPtr_(hWnd, #GWL_STYLE, wStyle & ~(#WS_MAXIMIZEBOX | #WS_MINIMIZEBOX | #WS_SIZEBOX))
FrameWidth = cvGetCaptureProperty(*capture, #CV_CAP_PROP_FRAME_WIDTH)
FrameHeight = cvGetCaptureProperty(*capture, #CV_CAP_PROP_FRAME_HEIGHT)
cvMoveWindow(#CV_WINDOW_NAME, 20, 20)
ToolTip(window_handle, #CV_DESCRIPTION)
*param.CvUserData = AllocateMemory(SizeOf(CvUserData))
*param\Value = window_handle
cvSetMouseCallback(*window_name, @CvMouseCallback(), *param)
Repeat
*image = cvQueryFrame(*capture)
If *image
ImageHeight = *image\height
If *image\nChannels = 1
*gray.IplImage = cvCloneImage(*image)
Else
*gray.IplImage = cvCreateImage(*image\width, *image\height, #IPL_DEPTH_8U, 1)
cvCvtColor(*image, *gray, #CV_BGR2GRAY, 1)
EndIf
cvThreshold(*gray, *gray, 210, 255, #CV_THRESH_BINARY)
cvClearMemStorage(*storage)
nContours = cvFindContours(*gray, *storage, @*contours, SizeOf(CvContour), #CV_RETR_LIST, #CV_CHAIN_APPROX_SIMPLE, 0, 0)
If nContours
*contour.IplImage = cvCreateImage(*gray\width, *gray\height, #IPL_DEPTH_8U, 3)
cvSet(*contour, 25, 36, 0, 0, #Null)
cntr = 0
For rtnCount = 0 To nContours - 1
area.d = cvContourArea(*contours, 0, #CV_WHOLE_SEQ_END_INDEX, 0)
; selecting glowing spheres by area
If area >= #MinArea And area <= #MaxArea
*poly = cvApproxPoly(*contours, SizeOf(CvContour), *storage, #CV_POLY_APPROX_DP, 5, 1)
; mass center of sphere
cvMoments(*contours, @moments, 0)
cx.d = moments\m10 / area
cy.d = moments\m01 / area
x = Round(cx, #PB_Round_Nearest)
y = Round(cy, #PB_Round_Nearest)
If cntr <= 7
sk(cntr)\x = x
sk(cntr)\y = y
cntr + 1
EndIf
; drawing the red circle in the mass center of a glowing sphere
cvCircle(*image, x, y, 2, 0, 0, 255, 0, 2, #CV_AA, #Null)
EndIf
*contours = *contours\h_next
Next
; connecting the dots to draw a skeleton
SortStructuredArray(sk(), #PB_Sort_Descending, OffsetOf(xy\x), TypeOf(xy\x))
For k=0 To 3
sk1(k)\x = sk(k)\x
sk1(k)\y = sk(k)\y
Next
If sk(4)\y > ImageHeight/3
sk1(4)\x = sk(4)\x
sk1(4)\y = sk(4)\y
sk1(7)\x = sk(5)\x
sk1(7)\y = sk(5)\y
Else
sk1(4)\x = sk(5)\x
sk1(4)\y = sk(5)\y
sk1(7)\x = sk(4)\x
sk1(7)\y = sk(4)\y
EndIf
SortStructuredArray(sk(), #PB_Sort_Ascending, OffsetOf(xy\x), TypeOf(xy\x))
For k=0 To 1
sk1(k+5)\x = sk(k)\x
sk1(k+5)\y = sk(k)\y
Next
For k=0 To 7
If k > 0
cvLine(*image, sk1(k-1)\x, sk1(k-1)\y, sk1(k)\x, sk1(k)\y, 0, 255, 255, 0, 2, #CV_AA, #Null)
EndIf
Next
EndIf
CompilerIf #WriteSkeleton = #True
cvWriteFrame(*writer, *image)
CompilerEndIf
cvShowImage(#CV_WINDOW_NAME, *image)
keyPressed = cvWaitKey(30)
cvReleaseImage(@*contour)
cvReleaseImage(@*gray)
If keyPressed = 32 ; SpaceKey - capture the frame and save it
If FileSize(GetCurrentDirectory()+"/Frames") <> -2
CreateDirectory(GetCurrentDirectory()+"/Frames")
EndIf
sFrame.s = GetCurrentDirectory()+"/Frames/"+ FormatDate("%yyyy.%mm.%dd %hh-%ii-%ss", Date()) + ".png"
cvSaveImage(sFrame, *image, #Null)
HaveToSaveFrame = #False
EndIf
Else
Break
EndIf
Until keyPressed = 27 Or exitCV
FreeMemory(*param)
cvReleaseMemStorage(@*storage)
cvReleaseImage(@*gray)
CompilerIf #WriteSkeleton = #True
cvReleaseVideoWriter(@*writer)
Else
MessageRequester(#CV_WINDOW_NAME, "Unable start writer", #MB_ICONERROR)
EndIf
CompilerEndIf
cvDestroyAllWindows()
cvReleaseCapture(@*capture)
Else
MessageRequester(#CV_WINDOW_NAME, "Unable to open video - operation cancelled.", #MB_ICONERROR)
EndIf