mirror of
https://github.com/Laex/Delphi-OpenCV.git
synced 2024-11-17 08:45:54 +01:00
193 lines
6.2 KiB
ObjectPascal
193 lines
6.2 KiB
ObjectPascal
|
// *****************************************************************
|
|||
|
// Delphi-OpenCV Demo
|
|||
|
// Copyright (C) 2013 Project Delphi-OpenCV
|
|||
|
// ****************************************************************
|
|||
|
// Contributor:
|
|||
|
// Laentir Valetov
|
|||
|
// email:laex@bk.ru
|
|||
|
// ****************************************************************
|
|||
|
// You may retrieve the latest version of this file at the GitHub,
|
|||
|
// located at git://github.com/Laex/Delphi-OpenCV.git
|
|||
|
// ****************************************************************
|
|||
|
// The contents of this file are used with permission, subject to
|
|||
|
// the Mozilla Public License Version 1.1 (the "License"); you may
|
|||
|
// not use this file except in compliance with the License. You may
|
|||
|
// obtain a copy of the License at
|
|||
|
// http://www.mozilla.org/MPL/MPL-1_1Final.html
|
|||
|
//
|
|||
|
// Software distributed under the License is distributed on an
|
|||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|||
|
// implied. See the License for the specific language governing
|
|||
|
// rights and limitations under the License.
|
|||
|
// *******************************************************************
|
|||
|
// Original: http://anikettatipamula.blogspot.ro/2012/02/hand-gesture-using-opencv.html
|
|||
|
// *******************************************************************
|
|||
|
|
|||
|
program HandsDetect2;
|
|||
|
|
|||
|
{$APPTYPE CONSOLE}
|
|||
|
{$POINTERMATH ON}
|
|||
|
{$R *.res}
|
|||
|
|
|||
|
uses
|
|||
|
System.SysUtils,
|
|||
|
ocv.highgui_c,
|
|||
|
ocv.core_c,
|
|||
|
ocv.core.types_c,
|
|||
|
ocv.imgproc_c,
|
|||
|
ocv.imgproc.types_c;
|
|||
|
|
|||
|
procedure detect(const img_8uc1: pIplImage; const img_8uc3: pIplImage);
|
|||
|
Var
|
|||
|
storage: pCvMemStorage;
|
|||
|
first_contour: pCvSeq;
|
|||
|
maxitem: pCvSeq;
|
|||
|
area, areamax: Double;
|
|||
|
maxn: Integer;
|
|||
|
Nc: Integer;
|
|||
|
n: Integer;
|
|||
|
c: pCvSeq;
|
|||
|
storage3: pCvMemStorage;
|
|||
|
pt0: TCvPoint;
|
|||
|
storage1, storage2: pCvMemStorage;
|
|||
|
ptseq: pCvSeq;
|
|||
|
hull, defects: pCvSeq;
|
|||
|
i, j: Integer;
|
|||
|
p: pCvPoint;
|
|||
|
hullcount: Integer;
|
|||
|
defectArray: pCvConvexityDefect;
|
|||
|
nomdef: Integer;
|
|||
|
font: TCvFont;
|
|||
|
txt: AnsiString;
|
|||
|
begin
|
|||
|
// 8uc1 is BW image with hand as white And 8uc3 is the original image
|
|||
|
storage := cvCreateMemStorage(0);
|
|||
|
first_contour := AllocMem(SizeOf(TCvSeq));
|
|||
|
maxitem := nil;
|
|||
|
area := 0;
|
|||
|
areamax := 0;
|
|||
|
maxn := 0;
|
|||
|
|
|||
|
// function to find the white objects in the image and return the object boundaries
|
|||
|
Nc := cvFindContours(img_8uc1, storage, @first_contour, SizeOf(TCvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE,
|
|||
|
cvPoint(0, 0));
|
|||
|
// Try all four values and see what happens
|
|||
|
|
|||
|
n := 0;
|
|||
|
WriteLn('Total Contours Detected: ', Nc);
|
|||
|
// Here we find the contour with maximum area
|
|||
|
|
|||
|
if (Nc > 0) then
|
|||
|
begin
|
|||
|
c := first_contour;
|
|||
|
While c <> nil do
|
|||
|
begin
|
|||
|
// cvCvtColor( img_8uc1, img_8uc3, CV_GRAY2BGR );
|
|||
|
area := Abs(cvContourArea(c, CV_WHOLE_SEQ));
|
|||
|
if (area > areamax) then
|
|||
|
begin
|
|||
|
areamax := area;
|
|||
|
maxitem := c;
|
|||
|
maxn := n;
|
|||
|
c := c^.h_next;
|
|||
|
end;
|
|||
|
Inc(n);
|
|||
|
end;
|
|||
|
|
|||
|
storage3 := cvCreateMemStorage(0);
|
|||
|
if (areamax > 5000) then // check for area greater than certain value and find convex hull
|
|||
|
begin
|
|||
|
maxitem := cvApproxPoly(maxitem, SizeOf(TCvContour), storage3, CV_POLY_APPROX_DP, 10, 1);
|
|||
|
storage1 := cvCreateMemStorage(0);
|
|||
|
storage2 := cvCreateMemStorage(0);
|
|||
|
ptseq := cvCreateSeq(CV_SEQ_KIND_GENERIC or CV_32SC2, SizeOf(TCvContour), SizeOf(TCvPoint), storage1);
|
|||
|
for i := 0 to maxitem^.total - 1 do
|
|||
|
begin
|
|||
|
p := CV_GET_SEQ_ELEM(SizeOf(TCvPoint), maxitem, i);
|
|||
|
pt0.x := p^.x;
|
|||
|
pt0.y := p^.y;
|
|||
|
cvSeqPush(ptseq, @pt0);
|
|||
|
end;
|
|||
|
hull := cvConvexHull2(ptseq, nil, CV_CLOCKWISE, 0);
|
|||
|
hullcount := hull^.total;
|
|||
|
defects := cvConvexityDefects(ptseq, hull, storage2);
|
|||
|
WriteLn('cvConvexityDefects total ', defects^.total);
|
|||
|
|
|||
|
// int m_nomdef:=0;
|
|||
|
// This cycle marks all defects of convexity of current contours.
|
|||
|
While Assigned(defects) do
|
|||
|
begin
|
|||
|
nomdef := defects^.total; // defect amount
|
|||
|
// outlet_float( m_nomdef, nomdef );
|
|||
|
WriteLn('defect no ', nomdef);
|
|||
|
if (nomdef = 0) then
|
|||
|
begin
|
|||
|
defects := defects^.h_next;
|
|||
|
continue;
|
|||
|
end;
|
|||
|
// Alloc memory for defect set.
|
|||
|
// fprintf(stderr,'malloc');
|
|||
|
defectArray := AllocMem(SizeOf(TCvConvexityDefect) * nomdef);
|
|||
|
// Get defect set.
|
|||
|
// fprintf(stderr,'cvCvtSeqToArray');
|
|||
|
cvCvtSeqToArray(defects, defectArray, CV_WHOLE_SEQ);
|
|||
|
// Draw marks for all defects.
|
|||
|
for i := 0 to nomdef - 1 do
|
|||
|
begin
|
|||
|
WriteLn('Defect depth for defect ', i:4, defectArray[i].depth:10:3);
|
|||
|
cvLine(img_8uc3, defectArray[i].start^, defectArray[i].depth_point^, CV_RGB(255, 255, 0), 1, CV_AA, 0);
|
|||
|
cvCircle(img_8uc3, defectArray[i].depth_point^, 5, CV_RGB(0, 0, 164), 2, 8, 0);
|
|||
|
cvCircle(img_8uc3, defectArray[i].start^, 5, CV_RGB(0, 0, 164), 2, 8, 0);
|
|||
|
cvLine(img_8uc3, defectArray[i].depth_point^, defectArray[i]._end^, CV_RGB(255, 255, 0), 1, CV_AA, 0);
|
|||
|
end;
|
|||
|
txt := '0' + IntToStr(nomdef - 1);
|
|||
|
cvInitFont(@font, CV_FONT_HERSHEY_SIMPLEX, 1.0, 1.0, 0, 5, CV_AA);
|
|||
|
cvPutText(img_8uc3, PAnsiChar(@txt[1]), cvPoint(50, 50), @font, cvScalar(0, 0, 255, 0));
|
|||
|
Inc(j);
|
|||
|
// Free memory.
|
|||
|
freemem(defectArray);
|
|||
|
defects := defects^.h_next;
|
|||
|
end;
|
|||
|
|
|||
|
cvReleaseMemStorage(storage);
|
|||
|
cvReleaseMemStorage(storage1);
|
|||
|
cvReleaseMemStorage(storage2);
|
|||
|
cvReleaseMemStorage(storage3);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
Var
|
|||
|
capture: PCvCapture;
|
|||
|
frame: pIplImage;
|
|||
|
image: pIplImage = nil;
|
|||
|
gray_image: pIplImage = nil;
|
|||
|
|
|||
|
begin
|
|||
|
try
|
|||
|
capture := cvCreateCameraCapture(CV_CAP_ANY);
|
|||
|
cvNamedWindow('capture', CV_WINDOW_AUTOSIZE);
|
|||
|
while true do
|
|||
|
begin
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
|||
|
frame := cvQueryFrame(capture);
|
|||
|
|
|||
|
image := cvCloneImage(frame);
|
|||
|
gray_image := cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
|
|||
|
cvCvtColor(image, gray_image, CV_RGB2GRAY);
|
|||
|
detect(gray_image, image);
|
|||
|
cvShowImage('capture', image);
|
|||
|
cvReleaseImage(image);
|
|||
|
cvReleaseImage(gray_image);
|
|||
|
if cvWaitKey(33) = 27 then
|
|||
|
Break;
|
|||
|
end;
|
|||
|
cvReleaseCapture(capture);
|
|||
|
cvDestroyWindow('capture');
|
|||
|
except
|
|||
|
on E: Exception do
|
|||
|
WriteLn(E.ClassName, ': ', E.Message);
|
|||
|
end;
|
|||
|
|
|||
|
end.
|