2013-09-25 21:18:23 +02:00
|
|
|
// *****************************************************************
|
|
|
|
// 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 file:
|
|
|
|
// opencv\samples\c\contours.c
|
|
|
|
// ****************************************************************
|
|
|
|
|
2013-04-13 00:05:58 +02:00
|
|
|
program cv_FindContours2;
|
|
|
|
|
|
|
|
{$APPTYPE CONSOLE}
|
|
|
|
{$R *.res}
|
|
|
|
|
|
|
|
uses
|
|
|
|
System.SysUtils,
|
2014-05-22 08:53:48 +02:00
|
|
|
opencv.highgui_c,
|
|
|
|
opencv.core_c,
|
|
|
|
opencv.core.types_c,
|
|
|
|
opencv.imgproc_c,
|
|
|
|
opencv.imgproc.types_c,
|
2014-05-19 21:29:48 +02:00
|
|
|
uResourcePaths;
|
2013-04-13 00:05:58 +02:00
|
|
|
|
|
|
|
procedure help;
|
|
|
|
begin
|
|
|
|
Writeln('This program creates an image to demonstrate the use of the ''c'' contour');
|
|
|
|
Writeln('functions: cvFindContours() and cvApproxPoly() along with the storage');
|
|
|
|
Writeln('functions cvCreateMemStorage() and cvDrawContours().');
|
|
|
|
Writeln('It also shows the use of a trackbar to control contour retrieval.');
|
|
|
|
Writeln;
|
|
|
|
Writeln('Usage :');
|
|
|
|
Writeln('contours');
|
|
|
|
end;
|
|
|
|
|
|
|
|
const
|
|
|
|
w = 500;
|
|
|
|
|
|
|
|
Var
|
2014-05-08 22:52:42 +02:00
|
|
|
levels: Integer = 3;
|
|
|
|
contours: pCvSeq = nil;
|
2013-04-13 00:05:58 +02:00
|
|
|
|
|
|
|
procedure on_trackbar(pos: Integer); cdecl;
|
|
|
|
Var
|
2014-05-08 22:52:42 +02:00
|
|
|
cnt_img: pIplImage;
|
2013-04-13 00:05:58 +02:00
|
|
|
_contours: pCvSeq;
|
2014-05-08 22:52:42 +02:00
|
|
|
_levels: Integer;
|
2013-04-13 00:05:58 +02:00
|
|
|
begin
|
2014-05-08 22:52:42 +02:00
|
|
|
cnt_img := cvCreateImage(cvSize(w, w), 8, 3);
|
2013-04-13 00:05:58 +02:00
|
|
|
_contours := contours;
|
2014-05-08 22:52:42 +02:00
|
|
|
_levels := levels - 3;
|
2013-04-13 00:05:58 +02:00
|
|
|
// (void)pos;
|
|
|
|
|
|
|
|
if (_levels <= 0) then // get to the nearest face to make it look more funny
|
|
|
|
_contours := _contours^.h_next^.h_next^.h_next;
|
|
|
|
cvZero(cnt_img);
|
2014-05-08 22:52:42 +02:00
|
|
|
cvDrawContours(cnt_img, _contours, CV_RGB(255, 0, 0), CV_RGB(0, 255, 0), _levels, 3, CV_AA, cvPoint(0, 0));
|
|
|
|
cvShowImage('contours', cnt_img);
|
2013-04-13 00:05:58 +02:00
|
|
|
cvReleaseImage(cnt_img);
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure findCComp(img: pIplImage);
|
|
|
|
var
|
|
|
|
x, y, cidx: Integer;
|
2014-05-08 22:52:42 +02:00
|
|
|
mask: pIplImage;
|
2013-04-13 00:05:58 +02:00
|
|
|
begin
|
|
|
|
cidx := 1;
|
2014-05-08 22:52:42 +02:00
|
|
|
mask := cvCreateImage(cvSize(img^.width + 2, img^.height + 2), 8, 1);
|
2013-04-13 00:05:58 +02:00
|
|
|
cvZero(mask);
|
2014-05-08 22:52:42 +02:00
|
|
|
cvRectangle(mask, cvPoint(0, 0), cvPoint(mask^.width - 1, mask^.height - 1), cvScalarAll(1), 1, 8, 0);
|
2013-04-13 00:05:58 +02:00
|
|
|
|
2014-05-08 22:52:42 +02:00
|
|
|
for y := 0 to img^.height - 1 do
|
2013-04-13 00:05:58 +02:00
|
|
|
for x := 0 to img^.width - 1 do
|
|
|
|
begin
|
|
|
|
if uchar(CV_IMAGE_ELEM(mask, SizeOf(uchar), y + 1, x + 1)^) <> 0 then
|
|
|
|
continue;
|
2014-05-08 22:52:42 +02:00
|
|
|
cvFloodFill(img, cvPoint(x, y), cvScalarAll(cidx), cvScalarAll(0), cvScalarAll(0), nil, 4, mask);
|
2013-04-13 00:05:58 +02:00
|
|
|
Inc(cidx);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
Var
|
2014-05-08 22:52:42 +02:00
|
|
|
i, j: Integer;
|
2013-04-13 00:05:58 +02:00
|
|
|
storage: pCvMemStorage;
|
2014-05-08 22:52:42 +02:00
|
|
|
img: pIplImage;
|
|
|
|
img32f: pIplImage;
|
|
|
|
img32s: pIplImage;
|
|
|
|
img3: pIplImage;
|
|
|
|
|
|
|
|
dx, dy: Integer;
|
|
|
|
white: TCvScalar;
|
|
|
|
black: TCvScalar;
|
|
|
|
angle: double;
|
|
|
|
attrs: array [0 .. 2] of pCVChar;
|
|
|
|
rng: TCvRNG;
|
2013-04-13 00:05:58 +02:00
|
|
|
tcontours: pCvSeq;
|
2014-05-08 22:52:42 +02:00
|
|
|
color: TCvScalar;
|
2013-04-13 00:05:58 +02:00
|
|
|
|
|
|
|
begin
|
|
|
|
try
|
|
|
|
storage := cvCreateMemStorage(0);
|
2014-05-08 22:52:42 +02:00
|
|
|
img := cvCreateImage(cvSize(w, w), 8, 1);
|
|
|
|
img32f := cvCreateImage(cvSize(w, w), IPL_DEPTH_32F, 1);
|
|
|
|
img32s := cvCreateImage(cvSize(w, w), IPL_DEPTH_32S, 1);
|
|
|
|
img3 := cvCreateImage(cvSize(w, w), 8, 3);
|
2013-04-13 00:05:58 +02:00
|
|
|
help;
|
|
|
|
|
|
|
|
cvZero(img);
|
|
|
|
|
|
|
|
for i := 0 to 5 do
|
|
|
|
begin
|
2014-05-08 22:52:42 +02:00
|
|
|
dx := (i mod 2) * 250 - 30;
|
|
|
|
dy := (i div 2) * 150;
|
2013-04-13 00:05:58 +02:00
|
|
|
white := cvRealScalar(255);
|
|
|
|
black := cvRealScalar(0);
|
|
|
|
|
|
|
|
if (i = 0) then
|
|
|
|
begin
|
|
|
|
for j := 0 to 9 do
|
|
|
|
begin
|
|
|
|
angle := (j + 5) * CV_PI / 21;
|
2014-05-08 22:52:42 +02:00
|
|
|
cvLine(img, cvPoint(cvRound(dx + 100 + j * 10 - 80 * cos(angle)), cvRound(dy + 100 - 90 * sin(angle))),
|
|
|
|
cvPoint(cvRound(dx + 100 + j * 10 - 30 * cos(angle)), cvRound(dy + 100 - 30 * sin(angle))), white, 3, 8, 0);
|
2013-04-13 00:05:58 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2014-05-08 22:52:42 +02:00
|
|
|
cvEllipse(img, cvPoint(dx + 150, dy + 100), cvSize(100, 70), 0, 0, 360, white, -1, 8, 0);
|
|
|
|
cvEllipse(img, cvPoint(dx + 115, dy + 70), cvSize(30, 20), 0, 0, 360, black, -1, 8, 0);
|
|
|
|
cvEllipse(img, cvPoint(dx + 185, dy + 70), cvSize(30, 20), 0, 0, 360, black, -1, 8, 0);
|
|
|
|
cvEllipse(img, cvPoint(dx + 115, dy + 70), cvSize(15, 15), 0, 0, 360, white, -1, 8, 0);
|
|
|
|
cvEllipse(img, cvPoint(dx + 185, dy + 70), cvSize(15, 15), 0, 0, 360, white, -1, 8, 0);
|
|
|
|
cvEllipse(img, cvPoint(dx + 115, dy + 70), cvSize(5, 5), 0, 0, 360, black, -1, 8, 0);
|
|
|
|
cvEllipse(img, cvPoint(dx + 185, dy + 70), cvSize(5, 5), 0, 0, 360, black, -1, 8, 0);
|
|
|
|
cvEllipse(img, cvPoint(dx + 150, dy + 100), cvSize(10, 5), 0, 0, 360, black, -1, 8, 0);
|
|
|
|
cvEllipse(img, cvPoint(dx + 150, dy + 150), cvSize(40, 10), 0, 0, 360, black, -1, 8, 0);
|
|
|
|
cvEllipse(img, cvPoint(dx + 27, dy + 100), cvSize(20, 35), 0, 0, 360, white, -1, 8, 0);
|
|
|
|
cvEllipse(img, cvPoint(dx + 273, dy + 100), cvSize(20, 35), 0, 0, 360, white, -1, 8, 0);
|
2013-04-13 00:05:58 +02:00
|
|
|
end;
|
|
|
|
|
2014-05-08 22:52:42 +02:00
|
|
|
cvNamedWindow('image', 1);
|
|
|
|
cvShowImage('image', img);
|
|
|
|
cvConvert(img, img32f);
|
2013-04-13 00:05:58 +02:00
|
|
|
findCComp(img32f);
|
2014-05-08 22:52:42 +02:00
|
|
|
cvConvert(img32f, img32s);
|
2013-04-13 00:05:58 +02:00
|
|
|
|
|
|
|
// cvFindContours(img32s, storage, @contours, SizeOf(TCvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
|
2014-05-08 22:52:42 +02:00
|
|
|
cvFindContours(img, storage, @contours, SizeOf(TCvContour), CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
|
2013-04-13 00:05:58 +02:00
|
|
|
|
|
|
|
attrs[0] := 'recursive';
|
|
|
|
attrs[1] := '1';
|
2014-05-19 21:29:48 +02:00
|
|
|
cvSave(cResourceResult+'contours.xml', contours, nil, nil, cvAttrList(@attrs));
|
|
|
|
contours := pCvSeq(cvLoad(cResourceResult+'contours.xml', storage));
|
2013-04-13 00:05:58 +02:00
|
|
|
|
|
|
|
// comment this out if you do not want approximation
|
2014-05-08 22:52:42 +02:00
|
|
|
contours := cvApproxPoly(contours, SizeOf(TCvContour), storage, CV_POLY_APPROX_DP, 3, 1);
|
2013-04-13 00:05:58 +02:00
|
|
|
|
2014-05-08 22:52:42 +02:00
|
|
|
cvNamedWindow('contours', 1);
|
|
|
|
cvCreateTrackbar('levels+3', 'contours', @levels, 7, on_trackbar);
|
2013-04-13 00:05:58 +02:00
|
|
|
|
2014-05-08 22:52:42 +02:00
|
|
|
rng := CvRNG(-1);
|
2013-04-13 00:05:58 +02:00
|
|
|
tcontours := contours;
|
|
|
|
|
2014-05-08 22:52:42 +02:00
|
|
|
cvCvtColor(img, img3, CV_GRAY2BGR);
|
2013-04-13 00:05:58 +02:00
|
|
|
|
|
|
|
while Assigned(tcontours^.h_next) do
|
|
|
|
tcontours := tcontours^.h_next;
|
|
|
|
|
|
|
|
while not Assigned(tcontours) do
|
|
|
|
begin
|
|
|
|
color.val[0] := cvRandInt(rng) mod 256;
|
|
|
|
color.val[1] := cvRandInt(rng) mod 256;
|
|
|
|
color.val[2] := cvRandInt(rng) mod 256;
|
|
|
|
color.val[3] := cvRandInt(rng) mod 256;
|
2014-05-08 22:52:42 +02:00
|
|
|
cvDrawContours(img3, tcontours, color, color, 0, -1, 8, cvPoint(0, 0));
|
2013-04-13 00:05:58 +02:00
|
|
|
if Assigned(tcontours^.v_next) then
|
|
|
|
begin
|
|
|
|
color.val[0] := cvRandInt(rng) mod 256;
|
|
|
|
color.val[1] := cvRandInt(rng) mod 256;
|
|
|
|
color.val[2] := cvRandInt(rng) mod 256;
|
|
|
|
color.val[3] := cvRandInt(rng) mod 256;
|
2014-05-08 22:52:42 +02:00
|
|
|
cvDrawContours(img3, tcontours^.v_next, color, color, 1, -1, 8, cvPoint(0, 0));
|
2013-04-13 00:05:58 +02:00
|
|
|
end;
|
|
|
|
tcontours := tcontours^.h_prev;
|
|
|
|
end;
|
|
|
|
|
2014-05-08 22:52:42 +02:00
|
|
|
cvShowImage('colored', img3);
|
2013-04-13 00:05:58 +02:00
|
|
|
on_trackbar(0);
|
|
|
|
|
|
|
|
cvWaitKey(0);
|
|
|
|
cvReleaseMemStorage(storage);
|
|
|
|
cvReleaseImage(img);
|
|
|
|
cvReleaseImage(img32f);
|
|
|
|
cvReleaseImage(img32s);
|
|
|
|
cvReleaseImage(img3);
|
|
|
|
cvDestroyAllWindows;
|
|
|
|
|
|
|
|
except
|
|
|
|
on E: Exception do
|
2014-05-08 22:52:42 +02:00
|
|
|
Writeln(E.ClassName, ': ', E.Message);
|
2013-04-13 00:05:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
end.
|