wstępne poruszanie kursorem
This commit is contained in:
1 parent
f81b88acfe
commit
b2e1e6f82e
42 files changed
+3527
-33
No files matched your search
@@ -0,0 +1,5 @@
|
||||
# This code depends on make tool being used
|
||||
DEPFILES=$(wildcard $(addsuffix .d, ${OBJECTFILES}))
|
||||
ifneq (${DEPFILES},)
|
||||
include ${DEPFILES}
|
||||
endif
|
||||
@@ -0,0 +1 @@
|
||||
build/Debug/GNU-Linux-x86/main.o: main.cpp
|
||||
BIN
Binary file not shown.
@@ -42,8 +42,8 @@ OBJECTFILES= \
|
||||
CFLAGS=pkg-config --cflags --libs opencv
|
||||
|
||||
# CC Compiler Flags
|
||||
CCFLAGS=`pkg-config --cflags --libs opencv`
|
||||
CXXFLAGS=`pkg-config --cflags --libs opencv`
|
||||
CCFLAGS=`pkg-config --cflags --libs opencv` -lX11
|
||||
CXXFLAGS=`pkg-config --cflags --libs opencv` -lX11
|
||||
|
||||
# Fortran Compiler Flags
|
||||
FFLAGS=
|
||||
@@ -56,16 +56,16 @@ LDLIBSOPTIONS=
|
||||
|
||||
# Build Targets
|
||||
.build-conf: ${BUILD_SUBPROJECTS}
|
||||
"${MAKE}" -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/modal-handpointer
|
||||
"${MAKE}" -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/przyklad
|
||||
|
||||
${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/modal-handpointer: ${OBJECTFILES}
|
||||
${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/przyklad: ${OBJECTFILES}
|
||||
${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}
|
||||
${LINK.cc} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/modal-handpointer ${OBJECTFILES} ${LDLIBSOPTIONS}
|
||||
${LINK.cc} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/przyklad ${OBJECTFILES} ${LDLIBSOPTIONS}
|
||||
|
||||
${OBJECTDIR}/main.o: main.cpp
|
||||
${MKDIR} -p ${OBJECTDIR}
|
||||
${RM} $@.d
|
||||
$(COMPILE.cc) -g `pkg-config --cflags --libs opencv` -MMD -MP -MF $@.d -o ${OBJECTDIR}/main.o main.cpp
|
||||
$(COMPILE.cc) -g `pkg-config --cflags --libs opencv` -lX11 -MMD -MP -MF $@.d -o ${OBJECTDIR}/main.o main.cpp
|
||||
|
||||
# Subprojects
|
||||
.build-subprojects:
|
||||
@@ -73,7 +73,7 @@ ${OBJECTDIR}/main.o: main.cpp
|
||||
# Clean Targets
|
||||
.clean-conf: ${CLEAN_SUBPROJECTS}
|
||||
${RM} -r ${CND_BUILDDIR}/${CND_CONF}
|
||||
${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/modal-handpointer
|
||||
${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/przyklad
|
||||
|
||||
# Subprojects
|
||||
.clean-subprojects:
|
||||
|
||||
@@ -56,11 +56,11 @@ LDLIBSOPTIONS=
|
||||
|
||||
# Build Targets
|
||||
.build-conf: ${BUILD_SUBPROJECTS}
|
||||
"${MAKE}" -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/modal-handpointer
|
||||
"${MAKE}" -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/przyklad
|
||||
|
||||
${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/modal-handpointer: ${OBJECTFILES}
|
||||
${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/przyklad: ${OBJECTFILES}
|
||||
${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}
|
||||
${LINK.cc} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/modal-handpointer ${OBJECTFILES} ${LDLIBSOPTIONS}
|
||||
${LINK.cc} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/przyklad ${OBJECTFILES} ${LDLIBSOPTIONS}
|
||||
|
||||
${OBJECTDIR}/main.o: main.cpp
|
||||
${MKDIR} -p ${OBJECTDIR}
|
||||
@@ -73,7 +73,7 @@ ${OBJECTDIR}/main.o: main.cpp
|
||||
# Clean Targets
|
||||
.clean-conf: ${CLEAN_SUBPROJECTS}
|
||||
${RM} -r ${CND_BUILDDIR}/${CND_CONF}
|
||||
${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/modal-handpointer
|
||||
${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/przyklad
|
||||
|
||||
# Subprojects
|
||||
.clean-subprojects:
|
||||
|
||||
@@ -24,7 +24,7 @@ CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}}
|
||||
|
||||
|
||||
# Project Name
|
||||
PROJECTNAME=Modal-HandPointer
|
||||
PROJECTNAME=Przyklad
|
||||
|
||||
# Active Configuration
|
||||
DEFAULTCONF=Debug
|
||||
|
||||
@@ -9,19 +9,19 @@ CND_DISTDIR=dist
|
||||
# Debug configuration
|
||||
CND_PLATFORM_Debug=GNU-Linux-x86
|
||||
CND_ARTIFACT_DIR_Debug=dist/Debug/GNU-Linux-x86
|
||||
CND_ARTIFACT_NAME_Debug=modal-handpointer
|
||||
CND_ARTIFACT_PATH_Debug=dist/Debug/GNU-Linux-x86/modal-handpointer
|
||||
CND_ARTIFACT_NAME_Debug=przyklad
|
||||
CND_ARTIFACT_PATH_Debug=dist/Debug/GNU-Linux-x86/przyklad
|
||||
CND_PACKAGE_DIR_Debug=dist/Debug/GNU-Linux-x86/package
|
||||
CND_PACKAGE_NAME_Debug=modal-handpointer.tar
|
||||
CND_PACKAGE_PATH_Debug=dist/Debug/GNU-Linux-x86/package/modal-handpointer.tar
|
||||
CND_PACKAGE_NAME_Debug=przyklad.tar
|
||||
CND_PACKAGE_PATH_Debug=dist/Debug/GNU-Linux-x86/package/przyklad.tar
|
||||
# Release configuration
|
||||
CND_PLATFORM_Release=GNU-Linux-x86
|
||||
CND_ARTIFACT_DIR_Release=dist/Release/GNU-Linux-x86
|
||||
CND_ARTIFACT_NAME_Release=modal-handpointer
|
||||
CND_ARTIFACT_PATH_Release=dist/Release/GNU-Linux-x86/modal-handpointer
|
||||
CND_ARTIFACT_NAME_Release=przyklad
|
||||
CND_ARTIFACT_PATH_Release=dist/Release/GNU-Linux-x86/przyklad
|
||||
CND_PACKAGE_DIR_Release=dist/Release/GNU-Linux-x86/package
|
||||
CND_PACKAGE_NAME_Release=modal-handpointer.tar
|
||||
CND_PACKAGE_PATH_Release=dist/Release/GNU-Linux-x86/package/modal-handpointer.tar
|
||||
CND_PACKAGE_NAME_Release=przyklad.tar
|
||||
CND_PACKAGE_PATH_Release=dist/Release/GNU-Linux-x86/package/przyklad.tar
|
||||
#
|
||||
# include compiler specific variables
|
||||
#
|
||||
|
||||
@@ -12,9 +12,9 @@ CND_DISTDIR=dist
|
||||
CND_BUILDDIR=build
|
||||
NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging
|
||||
TMPDIRNAME=tmp-packaging
|
||||
OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/modal-handpointer
|
||||
OUTPUT_BASENAME=modal-handpointer
|
||||
PACKAGE_TOP_DIR=modal-handpointer/
|
||||
OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/przyklad
|
||||
OUTPUT_BASENAME=przyklad
|
||||
PACKAGE_TOP_DIR=przyklad/
|
||||
|
||||
# Functions
|
||||
function checkReturnCode
|
||||
@@ -59,15 +59,15 @@ mkdir -p ${NBTMPDIR}
|
||||
|
||||
# Copy files and create directories and links
|
||||
cd "${TOP}"
|
||||
makeDirectory "${NBTMPDIR}/modal-handpointer/bin"
|
||||
makeDirectory "${NBTMPDIR}/przyklad/bin"
|
||||
copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755
|
||||
|
||||
|
||||
# Generate tar file
|
||||
cd "${TOP}"
|
||||
rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/modal-handpointer.tar
|
||||
rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/przyklad.tar
|
||||
cd ${NBTMPDIR}
|
||||
tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/modal-handpointer.tar *
|
||||
tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/przyklad.tar *
|
||||
checkReturnCode
|
||||
|
||||
# Cleanup
|
||||
|
||||
@@ -12,9 +12,9 @@ CND_DISTDIR=dist
|
||||
CND_BUILDDIR=build
|
||||
NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging
|
||||
TMPDIRNAME=tmp-packaging
|
||||
OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/modal-handpointer
|
||||
OUTPUT_BASENAME=modal-handpointer
|
||||
PACKAGE_TOP_DIR=modal-handpointer/
|
||||
OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/przyklad
|
||||
OUTPUT_BASENAME=przyklad
|
||||
PACKAGE_TOP_DIR=przyklad/
|
||||
|
||||
# Functions
|
||||
function checkReturnCode
|
||||
@@ -59,15 +59,15 @@ mkdir -p ${NBTMPDIR}
|
||||
|
||||
# Copy files and create directories and links
|
||||
cd "${TOP}"
|
||||
makeDirectory "${NBTMPDIR}/modal-handpointer/bin"
|
||||
makeDirectory "${NBTMPDIR}/przyklad/bin"
|
||||
copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755
|
||||
|
||||
|
||||
# Generate tar file
|
||||
cd "${TOP}"
|
||||
rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/modal-handpointer.tar
|
||||
rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/przyklad.tar
|
||||
cd ${NBTMPDIR}
|
||||
tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/modal-handpointer.tar *
|
||||
tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/przyklad.tar *
|
||||
checkReturnCode
|
||||
|
||||
# Cleanup
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
<commandLine>pkg-config --cflags --libs opencv</commandLine>
|
||||
</cTool>
|
||||
<ccTool>
|
||||
<commandLine>`pkg-config --cflags --libs opencv`</commandLine>
|
||||
<commandLine>`pkg-config --cflags --libs opencv` -lX11</commandLine>
|
||||
</ccTool>
|
||||
</compileType>
|
||||
<item path="main.cpp" ex="false" tool="1" flavor2="0">
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,5 @@
|
||||
# This code depends on make tool being used
|
||||
DEPFILES=$(wildcard $(addsuffix .d, ${OBJECTFILES}))
|
||||
ifneq (${DEPFILES},)
|
||||
include ${DEPFILES}
|
||||
endif
|
||||
@@ -0,0 +1,128 @@
|
||||
#
|
||||
# There exist several targets which are by default empty and which can be
|
||||
# used for execution of your targets. These targets are usually executed
|
||||
# before and after some main targets. They are:
|
||||
#
|
||||
# .build-pre: called before 'build' target
|
||||
# .build-post: called after 'build' target
|
||||
# .clean-pre: called before 'clean' target
|
||||
# .clean-post: called after 'clean' target
|
||||
# .clobber-pre: called before 'clobber' target
|
||||
# .clobber-post: called after 'clobber' target
|
||||
# .all-pre: called before 'all' target
|
||||
# .all-post: called after 'all' target
|
||||
# .help-pre: called before 'help' target
|
||||
# .help-post: called after 'help' target
|
||||
#
|
||||
# Targets beginning with '.' are not intended to be called on their own.
|
||||
#
|
||||
# Main targets can be executed directly, and they are:
|
||||
#
|
||||
# build build a specific configuration
|
||||
# clean remove built files from a configuration
|
||||
# clobber remove all built files
|
||||
# all build all configurations
|
||||
# help print help mesage
|
||||
#
|
||||
# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
|
||||
# .help-impl are implemented in nbproject/makefile-impl.mk.
|
||||
#
|
||||
# Available make variables:
|
||||
#
|
||||
# CND_BASEDIR base directory for relative paths
|
||||
# CND_DISTDIR default top distribution directory (build artifacts)
|
||||
# CND_BUILDDIR default top build directory (object files, ...)
|
||||
# CONF name of current configuration
|
||||
# CND_PLATFORM_${CONF} platform name (current configuration)
|
||||
# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration)
|
||||
# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration)
|
||||
# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration)
|
||||
# CND_PACKAGE_DIR_${CONF} directory of package (current configuration)
|
||||
# CND_PACKAGE_NAME_${CONF} name of package (current configuration)
|
||||
# CND_PACKAGE_PATH_${CONF} path to package (current configuration)
|
||||
#
|
||||
# NOCDDL
|
||||
|
||||
|
||||
# Environment
|
||||
MKDIR=mkdir
|
||||
CP=cp
|
||||
CCADMIN=CCadmin
|
||||
|
||||
|
||||
# build
|
||||
build: .build-post
|
||||
|
||||
.build-pre:
|
||||
# Add your pre 'build' code here...
|
||||
|
||||
.build-post: .build-impl
|
||||
# Add your post 'build' code here...
|
||||
|
||||
|
||||
# clean
|
||||
clean: .clean-post
|
||||
|
||||
.clean-pre:
|
||||
# Add your pre 'clean' code here...
|
||||
|
||||
.clean-post: .clean-impl
|
||||
# Add your post 'clean' code here...
|
||||
|
||||
|
||||
# clobber
|
||||
clobber: .clobber-post
|
||||
|
||||
.clobber-pre:
|
||||
# Add your pre 'clobber' code here...
|
||||
|
||||
.clobber-post: .clobber-impl
|
||||
# Add your post 'clobber' code here...
|
||||
|
||||
|
||||
# all
|
||||
all: .all-post
|
||||
|
||||
.all-pre:
|
||||
# Add your pre 'all' code here...
|
||||
|
||||
.all-post: .all-impl
|
||||
# Add your post 'all' code here...
|
||||
|
||||
|
||||
# build tests
|
||||
build-tests: .build-tests-post
|
||||
|
||||
.build-tests-pre:
|
||||
# Add your pre 'build-tests' code here...
|
||||
|
||||
.build-tests-post: .build-tests-impl
|
||||
# Add your post 'build-tests' code here...
|
||||
|
||||
|
||||
# run tests
|
||||
test: .test-post
|
||||
|
||||
.test-pre: build-tests
|
||||
# Add your pre 'test' code here...
|
||||
|
||||
.test-post: .test-impl
|
||||
# Add your post 'test' code here...
|
||||
|
||||
|
||||
# help
|
||||
help: .help-post
|
||||
|
||||
.help-pre:
|
||||
# Add your pre 'help' code here...
|
||||
|
||||
.help-post: .help-impl
|
||||
# Add your post 'help' code here...
|
||||
|
||||
|
||||
|
||||
# include project implementation makefile
|
||||
include nbproject/Makefile-impl.mk
|
||||
|
||||
# include project make variables
|
||||
include nbproject/Makefile-variables.mk
|
||||
@@ -0,0 +1,3 @@
|
||||
build/Debug/GNU-Linux-x86/Mouse.o: Mouse.cpp Mouse.hpp
|
||||
|
||||
Mouse.hpp:
|
||||
@@ -0,0 +1 @@
|
||||
build/Debug/GNU-Linux-x86/main.o: main.cpp
|
||||
@@ -0,0 +1,4 @@
|
||||
build/Debug/GNU-Linux-x86/src/HandPointer/HandPointer.cpp.o: \
|
||||
src/HandPointer/HandPointer.cpp.cpp src/HandPointer/Mouse.hpp
|
||||
|
||||
src/HandPointer/Mouse.hpp:
|
||||
@@ -0,0 +1,7 @@
|
||||
build/Debug/GNU-Linux-x86/src/HandPointer/HandPointer.o: \
|
||||
src/HandPointer/HandPointer.cpp include/cvBlob/cvblob.h \
|
||||
src/HandPointer/Mouse.hpp
|
||||
|
||||
include/cvBlob/cvblob.h:
|
||||
|
||||
src/HandPointer/Mouse.hpp:
|
||||
@@ -0,0 +1,4 @@
|
||||
build/Debug/GNU-Linux-x86/src/HandPointer/Mouse.o: \
|
||||
src/HandPointer/Mouse.cpp src/HandPointer/Mouse.hpp
|
||||
|
||||
src/HandPointer/Mouse.hpp:
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,45 @@
|
||||
# Copyright (C) 2007 by Cristóbal Carnero Liñán
|
||||
# grendel.ccl@gmail.com
|
||||
#
|
||||
# This file is part of cvBlob.
|
||||
#
|
||||
# cvBlob is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the Lesser GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# cvBlob is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# Lesser GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the Lesser GNU General Public License
|
||||
# along with cvBlob. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
find_package(OpenCV REQUIRED)
|
||||
|
||||
set(cvBlob_CVBLOB cvblob.cpp
|
||||
cvlabel.cpp
|
||||
cvaux.cpp
|
||||
cvcontour.cpp
|
||||
cvtrack.cpp
|
||||
cvcolor.cpp
|
||||
)
|
||||
|
||||
set_source_files_properties(${cvBlob_SRC}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "-O3"
|
||||
)
|
||||
|
||||
add_library(cvblob SHARED ${cvBlob_CVBLOB})
|
||||
|
||||
target_link_libraries(cvblob ${OpenCV_LIBS})
|
||||
|
||||
install(FILES cvblob.h DESTINATION include)
|
||||
|
||||
install(TARGETS cvblob
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright (C) 2007 by Cristóbal Carnero Liñán
|
||||
// grendel.ccl@gmail.com
|
||||
//
|
||||
// This file is part of cvBlob.
|
||||
//
|
||||
// cvBlob is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the Lesser GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// cvBlob is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// Lesser GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the Lesser GNU General Public License
|
||||
// along with cvBlob. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#if (defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) || (defined(__APPLE__) & defined(__MACH__)))
|
||||
#include <cv.h>
|
||||
#else
|
||||
#include <opencv/cv.h>
|
||||
#endif
|
||||
|
||||
#include "cvblob.h"
|
||||
|
||||
namespace cvb
|
||||
{
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=geometry1
|
||||
|
||||
double cvDotProductPoints(CvPoint const &a, CvPoint const &b, CvPoint const &c)
|
||||
{
|
||||
double abx = b.x-a.x;
|
||||
double aby = b.y-a.y;
|
||||
double bcx = c.x-b.x;
|
||||
double bcy = c.y-b.y;
|
||||
|
||||
return abx*bcx + aby*bcy;
|
||||
}
|
||||
|
||||
double cvCrossProductPoints(CvPoint const &a, CvPoint const &b, CvPoint const &c)
|
||||
{
|
||||
double abx = b.x-a.x;
|
||||
double aby = b.y-a.y;
|
||||
double acx = c.x-a.x;
|
||||
double acy = c.y-a.y;
|
||||
|
||||
return abx*acy - aby*acx;
|
||||
}
|
||||
|
||||
double cvDistancePointPoint(CvPoint const &a, CvPoint const &b)
|
||||
{
|
||||
double abx = a.x-b.x;
|
||||
double aby = a.y-b.y;
|
||||
|
||||
return sqrt(abx*abx + aby*aby);
|
||||
}
|
||||
|
||||
double cvDistanceLinePoint(CvPoint const &a, CvPoint const &b, CvPoint const &c, bool isSegment)
|
||||
{
|
||||
if (isSegment)
|
||||
{
|
||||
double dot1 = cvDotProductPoints(a, b, c);
|
||||
if (dot1>0) return cvDistancePointPoint(b, c);
|
||||
|
||||
double dot2 = cvDotProductPoints(b, a, c);
|
||||
if(dot2>0) return cvDistancePointPoint(a, c);
|
||||
}
|
||||
|
||||
return fabs(cvCrossProductPoints(a,b,c)/cvDistancePointPoint(a,b));
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
// Copyright (C) 2007 by Cristóbal Carnero Liñán
|
||||
// grendel.ccl@gmail.com
|
||||
//
|
||||
// This file is part of cvBlob.
|
||||
//
|
||||
// cvBlob is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the Lesser GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// cvBlob is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// Lesser GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the Lesser GNU General Public License
|
||||
// along with cvBlob. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#if (defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) || (defined(__APPLE__) & defined(__MACH__)))
|
||||
#include <cv.h>
|
||||
#include <highgui.h>
|
||||
#else
|
||||
#include <opencv/cv.h>
|
||||
#include <opencv/highgui.h>
|
||||
#endif
|
||||
|
||||
#include "cvblob.h"
|
||||
|
||||
namespace cvb
|
||||
{
|
||||
|
||||
CvLabel cvLargestBlob(const CvBlobs &blobs)
|
||||
{
|
||||
CvLabel label=0;
|
||||
unsigned int maxArea=0;
|
||||
|
||||
for (CvBlobs::const_iterator it=blobs.begin();it!=blobs.end();++it)
|
||||
{
|
||||
CvBlob *blob=(*it).second;
|
||||
|
||||
if (blob->area > maxArea)
|
||||
{
|
||||
label=blob->label;
|
||||
maxArea=blob->area;
|
||||
}
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
void cvFilterByArea(CvBlobs &blobs, unsigned int minArea, unsigned int maxArea)
|
||||
{
|
||||
CvBlobs::iterator it=blobs.begin();
|
||||
while(it!=blobs.end())
|
||||
{
|
||||
CvBlob *blob=(*it).second;
|
||||
if ((blob->area<minArea)||(blob->area>maxArea))
|
||||
{
|
||||
cvReleaseBlob(blob);
|
||||
|
||||
CvBlobs::iterator tmp=it;
|
||||
++it;
|
||||
blobs.erase(tmp);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void cvFilterByLabel(CvBlobs &blobs, CvLabel label)
|
||||
{
|
||||
CvBlobs::iterator it=blobs.begin();
|
||||
while(it!=blobs.end())
|
||||
{
|
||||
CvBlob *blob=(*it).second;
|
||||
if (blob->label!=label)
|
||||
{
|
||||
delete blob;
|
||||
CvBlobs::iterator tmp=it;
|
||||
++it;
|
||||
blobs.erase(tmp);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
/*void cvCentralMoments(CvBlob *blob, const IplImage *img)
|
||||
{
|
||||
CV_FUNCNAME("cvCentralMoments");
|
||||
__CV_BEGIN__;
|
||||
if (!blob->centralMoments)
|
||||
{
|
||||
CV_ASSERT(img&&(img->depth==IPL_DEPTH_LABEL)&&(img->nChannels==1));
|
||||
|
||||
//cvCentroid(blob); // Here?
|
||||
|
||||
blob->u11=blob->u20=blob->u02=0.;
|
||||
|
||||
// Only in the bounding box
|
||||
int stepIn = img->widthStep / (img->depth / 8);
|
||||
int img_width = img->width;
|
||||
int img_height = img->height;
|
||||
int img_offset = 0;
|
||||
if(0 != img->roi)
|
||||
{
|
||||
img_width = img->roi->width;
|
||||
img_height = img->roi->height;
|
||||
img_offset = img->roi->xOffset + (img->roi->yOffset * stepIn);
|
||||
}
|
||||
|
||||
CvLabel *imgData=(CvLabel *)img->imageData + (blob->miny * stepIn) + img_offset;
|
||||
for (unsigned int r=blob->miny;
|
||||
r<blob->maxy;
|
||||
r++,imgData+=stepIn)
|
||||
for (unsigned int c=blob->minx;c<blob->maxx;c++)
|
||||
if (imgData[c]==blob->label)
|
||||
{
|
||||
double tx=(c-blob->centroid.x);
|
||||
double ty=(r-blob->centroid.y);
|
||||
blob->u11+=tx*ty;
|
||||
blob->u20+=tx*tx;
|
||||
blob->u02+=ty*ty;
|
||||
}
|
||||
|
||||
blob->centralMoments = true;
|
||||
}
|
||||
__CV_END__;
|
||||
}*/
|
||||
|
||||
void cvRenderBlob(const IplImage *imgLabel, CvBlob *blob, IplImage *imgSource, IplImage *imgDest, unsigned short mode, CvScalar const &color, double alpha)
|
||||
{
|
||||
CV_FUNCNAME("cvRenderBlob");
|
||||
__CV_BEGIN__;
|
||||
|
||||
CV_ASSERT(imgLabel&&(imgLabel->depth==IPL_DEPTH_LABEL)&&(imgLabel->nChannels==1));
|
||||
CV_ASSERT(imgDest&&(imgDest->depth==IPL_DEPTH_8U)&&(imgDest->nChannels==3));
|
||||
|
||||
if (mode&CV_BLOB_RENDER_COLOR)
|
||||
{
|
||||
int stepLbl = imgLabel->widthStep/(imgLabel->depth/8);
|
||||
int stepSrc = imgSource->widthStep/(imgSource->depth/8);
|
||||
int stepDst = imgDest->widthStep/(imgDest->depth/8);
|
||||
int imgLabel_width = imgLabel->width;
|
||||
int imgLabel_height = imgLabel->height;
|
||||
int imgLabel_offset = 0;
|
||||
int imgSource_width = imgSource->width;
|
||||
int imgSource_height = imgSource->height;
|
||||
int imgSource_offset = 0;
|
||||
int imgDest_width = imgDest->width;
|
||||
int imgDest_height = imgDest->height;
|
||||
int imgDest_offset = 0;
|
||||
if(imgLabel->roi)
|
||||
{
|
||||
imgLabel_width = imgLabel->roi->width;
|
||||
imgLabel_height = imgLabel->roi->height;
|
||||
imgLabel_offset = (imgLabel->nChannels * imgLabel->roi->xOffset) + (imgLabel->roi->yOffset * stepLbl);
|
||||
}
|
||||
if(imgSource->roi)
|
||||
{
|
||||
imgSource_width = imgSource->roi->width;
|
||||
imgSource_height = imgSource->roi->height;
|
||||
imgSource_offset = (imgSource->nChannels * imgSource->roi->xOffset) + (imgSource->roi->yOffset * stepSrc);
|
||||
}
|
||||
if(imgDest->roi)
|
||||
{
|
||||
imgDest_width = imgDest->roi->width;
|
||||
imgDest_height = imgDest->roi->height;
|
||||
imgDest_offset = (imgDest->nChannels * imgDest->roi->xOffset) + (imgDest->roi->yOffset * stepDst);
|
||||
}
|
||||
|
||||
CvLabel *labels = (CvLabel *)imgLabel->imageData + imgLabel_offset + (blob->miny * stepLbl);
|
||||
unsigned char *source = (unsigned char *)imgSource->imageData + imgSource_offset + (blob->miny * stepSrc);
|
||||
unsigned char *imgData = (unsigned char *)imgDest->imageData + imgDest_offset + (blob->miny * stepDst);
|
||||
|
||||
for (unsigned int r=blob->miny; r<blob->maxy; r++, labels+=stepLbl, source+=stepSrc, imgData+=stepDst)
|
||||
for (unsigned int c=blob->minx; c<blob->maxx; c++)
|
||||
{
|
||||
if (labels[c]==blob->label)
|
||||
{
|
||||
imgData[imgDest->nChannels*c+0] = (unsigned char)((1.-alpha)*source[imgSource->nChannels*c+0]+alpha*color.val[0]);
|
||||
imgData[imgDest->nChannels*c+1] = (unsigned char)((1.-alpha)*source[imgSource->nChannels*c+1]+alpha*color.val[1]);
|
||||
imgData[imgDest->nChannels*c+2] = (unsigned char)((1.-alpha)*source[imgSource->nChannels*c+2]+alpha*color.val[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mode)
|
||||
{
|
||||
if (mode&CV_BLOB_RENDER_TO_LOG)
|
||||
{
|
||||
std::clog << "Blob " << blob->label << std::endl;
|
||||
std::clog << " - Bounding box: (" << blob->minx << ", " << blob->miny << ") - (" << blob->maxx << ", " << blob->maxy << ")" << std::endl;
|
||||
std::clog << " - Bounding box area: " << (1 + blob->maxx - blob->minx) * (1 + blob->maxy - blob->miny) << std::endl;
|
||||
std::clog << " - Area: " << blob->area << std::endl;
|
||||
std::clog << " - Centroid: (" << blob->centroid.x << ", " << blob->centroid.y << ")" << std::endl;
|
||||
std::clog << std::endl;
|
||||
}
|
||||
|
||||
if (mode&CV_BLOB_RENDER_TO_STD)
|
||||
{
|
||||
std::cout << "Blob " << blob->label << std::endl;
|
||||
std::cout << " - Bounding box: (" << blob->minx << ", " << blob->miny << ") - (" << blob->maxx << ", " << blob->maxy << ")" << std::endl;
|
||||
std::cout << " - Bounding box area: " << (1 + blob->maxx - blob->minx) * (1 + blob->maxy - blob->miny) << std::endl;
|
||||
std::cout << " - Area: " << blob->area << std::endl;
|
||||
std::cout << " - Centroid: (" << blob->centroid.x << ", " << blob->centroid.y << ")" << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
if (mode&CV_BLOB_RENDER_BOUNDING_BOX)
|
||||
cvRectangle(imgDest, cvPoint(blob->minx, blob->miny), cvPoint(blob->maxx-1, blob->maxy-1), CV_RGB(255., 0., 0.));
|
||||
|
||||
if (mode&CV_BLOB_RENDER_ANGLE)
|
||||
{
|
||||
double angle = cvAngle(blob);
|
||||
|
||||
double x1,y1,x2,y2;
|
||||
double lengthLine = MAX(blob->maxx-blob->minx, blob->maxy-blob->miny)/2.;
|
||||
|
||||
x1=blob->centroid.x-lengthLine*cos(angle);
|
||||
y1=blob->centroid.y-lengthLine*sin(angle);
|
||||
x2=blob->centroid.x+lengthLine*cos(angle);
|
||||
y2=blob->centroid.y+lengthLine*sin(angle);
|
||||
cvLine(imgDest,cvPoint(int(x1),int(y1)),cvPoint(int(x2),int(y2)),CV_RGB(0.,255.,0.));
|
||||
}
|
||||
|
||||
if (mode&CV_BLOB_RENDER_CENTROID)
|
||||
{
|
||||
cvLine(imgDest,cvPoint(int(blob->centroid.x)-3,int(blob->centroid.y)),cvPoint(int(blob->centroid.x)+3,int(blob->centroid.y)),CV_RGB(0.,0.,255.));
|
||||
cvLine(imgDest,cvPoint(int(blob->centroid.x),int(blob->centroid.y)-3),cvPoint(int(blob->centroid.x),int(blob->centroid.y)+3),CV_RGB(0.,0.,255.));
|
||||
}
|
||||
}
|
||||
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Based on http://en.wikipedia.org/wiki/HSL_and_HSV
|
||||
|
||||
/// \def _HSV2RGB_(H, S, V, R, G, B)
|
||||
/// \brief Color translation between HSV and RGB.
|
||||
#define _HSV2RGB_(H, S, V, R, G, B) \
|
||||
{ \
|
||||
double _h = H/60.; \
|
||||
int _hf = (int)floor(_h); \
|
||||
int _hi = ((int)_h)%6; \
|
||||
double _f = _h - _hf; \
|
||||
\
|
||||
double _p = V * (1. - S); \
|
||||
double _q = V * (1. - _f * S); \
|
||||
double _t = V * (1. - (1. - _f) * S); \
|
||||
\
|
||||
switch (_hi) \
|
||||
{ \
|
||||
case 0: \
|
||||
R = 255.*V; G = 255.*_t; B = 255.*_p; \
|
||||
break; \
|
||||
case 1: \
|
||||
R = 255.*_q; G = 255.*V; B = 255.*_p; \
|
||||
break; \
|
||||
case 2: \
|
||||
R = 255.*_p; G = 255.*V; B = 255.*_t; \
|
||||
break; \
|
||||
case 3: \
|
||||
R = 255.*_p; G = 255.*_q; B = 255.*V; \
|
||||
break; \
|
||||
case 4: \
|
||||
R = 255.*_t; G = 255.*_p; B = 255.*V; \
|
||||
break; \
|
||||
case 5: \
|
||||
R = 255.*V; G = 255.*_p; B = 255.*_q; \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef std::map<CvLabel, CvScalar> Palete;
|
||||
|
||||
void cvRenderBlobs(const IplImage *imgLabel, CvBlobs &blobs, IplImage *imgSource, IplImage *imgDest, unsigned short mode, double alpha)
|
||||
{
|
||||
CV_FUNCNAME("cvRenderBlobs");
|
||||
__CV_BEGIN__;
|
||||
{
|
||||
|
||||
CV_ASSERT(imgLabel&&(imgLabel->depth==IPL_DEPTH_LABEL)&&(imgLabel->nChannels==1));
|
||||
CV_ASSERT(imgDest&&(imgDest->depth==IPL_DEPTH_8U)&&(imgDest->nChannels==3));
|
||||
|
||||
Palete pal;
|
||||
if (mode&CV_BLOB_RENDER_COLOR)
|
||||
{
|
||||
|
||||
unsigned int colorCount = 0;
|
||||
for (CvBlobs::const_iterator it=blobs.begin(); it!=blobs.end(); ++it)
|
||||
{
|
||||
CvLabel label = (*it).second->label;
|
||||
|
||||
double r, g, b;
|
||||
|
||||
_HSV2RGB_((double)((colorCount*77)%360), .5, 1., r, g, b);
|
||||
colorCount++;
|
||||
|
||||
pal[label] = CV_RGB(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
for (CvBlobs::iterator it=blobs.begin(); it!=blobs.end(); ++it)
|
||||
cvRenderBlob(imgLabel, (*it).second, imgSource, imgDest, mode, pal[(*it).second->label], alpha);
|
||||
|
||||
}
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
// Returns radians
|
||||
double cvAngle(CvBlob *blob)
|
||||
{
|
||||
CV_FUNCNAME("cvAngle");
|
||||
__CV_BEGIN__;
|
||||
|
||||
return .5*atan2(2.*blob->u11,(blob->u20-blob->u02));
|
||||
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
void cvSaveImageBlob(const char *filename, IplImage *img, CvBlob const *blob)
|
||||
{
|
||||
CvRect roi = cvGetImageROI(img);
|
||||
cvSetImageROItoBlob(img, blob);
|
||||
cvSaveImage(filename, img);
|
||||
cvSetImageROI(img, roi);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream& output, const cvb::CvBlob& b)
|
||||
{
|
||||
output << b.label << ": " << b.area << ", (" << b.centroid.x << ", " << b.centroid.y << "), [(" << b.minx << ", " << b.miny << ") - (" << b.maxx << ", " << b.maxy << ")]";
|
||||
|
||||
return output;
|
||||
}
|
||||
@@ -0,0 +1,587 @@
|
||||
// Copyright (C) 2007 by Cristóbal Carnero Liñán
|
||||
// grendel.ccl@gmail.com
|
||||
//
|
||||
// This file is part of cvBlob.
|
||||
//
|
||||
// cvBlob is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the Lesser GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// Lesser GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the Lesser GNU General Public License
|
||||
// along with cvBlob. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
/// \file cvblob.h
|
||||
/// \brief OpenCV Blob header file.
|
||||
|
||||
#ifdef SWIG
|
||||
%module cvblob
|
||||
%{
|
||||
#include "cvblob.h"
|
||||
%}
|
||||
#endif
|
||||
|
||||
#ifndef CVBLOB_H
|
||||
#define CVBLOB_H
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
|
||||
#if (defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) || (defined(__APPLE__) & defined(__MACH__)))
|
||||
#include <cv.h>
|
||||
#else
|
||||
#include <opencv/cv.h>
|
||||
#endif
|
||||
|
||||
#ifndef __CV_BEGIN__
|
||||
#define __CV_BEGIN__ __BEGIN__
|
||||
#endif
|
||||
#ifndef __CV_END__
|
||||
#define __CV_END__ __END__
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
namespace cvb
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Contours
|
||||
|
||||
// Chain code:
|
||||
// 7 0 1
|
||||
// 6 2
|
||||
// 5 4 3
|
||||
#define CV_CHAINCODE_UP 0 ///< Up.
|
||||
#define CV_CHAINCODE_UP_RIGHT 1 ///< Up and right.
|
||||
#define CV_CHAINCODE_RIGHT 2 ///< Right.
|
||||
#define CV_CHAINCODE_DOWN_RIGHT 3 ///< Down and right.
|
||||
#define CV_CHAINCODE_DOWN 4 ///< Down.
|
||||
#define CV_CHAINCODE_DOWN_LEFT 5 ///< Down and left.
|
||||
#define CV_CHAINCODE_LEFT 6 ///< Left.
|
||||
#define CV_CHAINCODE_UP_LEFT 7 ///< Up and left.
|
||||
|
||||
/// \brief Move vectors of chain codes.
|
||||
/// \see CV_CHAINCODE_UP
|
||||
/// \see CV_CHAINCODE_UP_LEFT
|
||||
/// \see CV_CHAINCODE_LEFT
|
||||
/// \see CV_CHAINCODE_DOWN_LEFT
|
||||
/// \see CV_CHAINCODE_DOWN
|
||||
/// \see CV_CHAINCODE_DOWN_RIGHT
|
||||
/// \see CV_CHAINCODE_RIGHT
|
||||
/// \see CV_CHAINCODE_UP_RIGHT
|
||||
const char cvChainCodeMoves[8][2] = { { 0, -1},
|
||||
{ 1, -1},
|
||||
{ 1, 0},
|
||||
{ 1, 1},
|
||||
{ 0, 1},
|
||||
{-1, 1},
|
||||
{-1, 0},
|
||||
{-1, -1}
|
||||
};
|
||||
|
||||
/// \brief Direction.
|
||||
/// \see CV_CHAINCODE_UP
|
||||
/// \see CV_CHAINCODE_UP_LEFT
|
||||
/// \see CV_CHAINCODE_LEFT
|
||||
/// \see CV_CHAINCODE_DOWN_LEFT
|
||||
/// \see CV_CHAINCODE_DOWN
|
||||
/// \see CV_CHAINCODE_DOWN_RIGHT
|
||||
/// \see CV_CHAINCODE_RIGHT
|
||||
/// \see CV_CHAINCODE_UP_RIGHT
|
||||
typedef unsigned char CvChainCode;
|
||||
|
||||
/// \brief Chain code.
|
||||
/// \see CvChainCode
|
||||
typedef std::list<CvChainCode> CvChainCodes;
|
||||
|
||||
/// \brief Chain code contour.
|
||||
/// \see CvChainCodes
|
||||
struct CvContourChainCode
|
||||
{
|
||||
CvPoint startingPoint; ///< Point where contour begin.
|
||||
CvChainCodes chainCode; ///< Polygon description based on chain codes.
|
||||
};
|
||||
|
||||
typedef std::list<CvContourChainCode *> CvContoursChainCode; ///< List of contours (chain codes type).
|
||||
|
||||
/// \brief Polygon based contour.
|
||||
typedef std::vector<CvPoint> CvContourPolygon;
|
||||
|
||||
/// \fn void cvRenderContourChainCode(CvContourChainCode const *contour, IplImage const *img, CvScalar const &color=CV_RGB(255, 255, 255))
|
||||
/// \brief Draw a contour.
|
||||
/// \param contour Chain code contour.
|
||||
/// \param img Image to draw on.
|
||||
/// \param color Color to draw (default, white).
|
||||
/// \see CvContourChainCode
|
||||
void cvRenderContourChainCode(CvContourChainCode const *contour, IplImage const *img, CvScalar const &color=CV_RGB(255, 255, 255));
|
||||
|
||||
/// \fn CvContourPolygon *cvConvertChainCodesToPolygon(CvContourChainCode const *cc)
|
||||
/// \brief Convert a chain code contour to a polygon.
|
||||
/// \param cc Chain code contour.
|
||||
/// \return A polygon.
|
||||
/// \see CvContourChainCode
|
||||
/// \see CvContourPolygon
|
||||
CvContourPolygon *cvConvertChainCodesToPolygon(CvContourChainCode const *cc);
|
||||
|
||||
/// \fn void cvRenderContourPolygon(CvContourPolygon const *contour, IplImage *img, CvScalar const &color=CV_RGB(255, 255, 255))
|
||||
/// \brief Draw a polygon.
|
||||
/// \param contour Polygon contour.
|
||||
/// \param img Image to draw on.
|
||||
/// \param color Color to draw (default, white).
|
||||
/// \see CvContourPolygon
|
||||
void cvRenderContourPolygon(CvContourPolygon const *contour, IplImage *img, CvScalar const &color=CV_RGB(255, 255, 255));
|
||||
|
||||
/// \fn double cvContourPolygonArea(CvContourPolygon const *p)
|
||||
/// \brief Calculates area of a polygonal contour.
|
||||
/// \param p Contour (polygon type).
|
||||
/// \return Area of the contour.
|
||||
double cvContourPolygonArea(CvContourPolygon const *p);
|
||||
|
||||
/// \fn double cvContourChainCodePerimeter(CvContourChainCode const *c)
|
||||
/// \brief Calculates perimeter of a chain code contour.
|
||||
/// \param c Contour (chain code type).
|
||||
/// \return Perimeter of the contour.
|
||||
double cvContourChainCodePerimeter(CvContourChainCode const *c);
|
||||
|
||||
/// \fn double cvContourPolygonPerimeter(CvContourPolygon const *p)
|
||||
/// \brief Calculates perimeter of a polygonal contour.
|
||||
/// \param p Contour (polygon type).
|
||||
/// \return Perimeter of the contour.
|
||||
double cvContourPolygonPerimeter(CvContourPolygon const *p);
|
||||
|
||||
/// \fn double cvContourPolygonCircularity(const CvContourPolygon *p)
|
||||
/// \brief Calculates the circularity of a polygon (compactness measure).
|
||||
/// \param p Contour (polygon type).
|
||||
/// \return Circularity: a non-negative value, where 0 correspond with a circumference.
|
||||
double cvContourPolygonCircularity(const CvContourPolygon *p);
|
||||
|
||||
/// \fn CvContourPolygon *cvSimplifyPolygon(CvContourPolygon const *p, double const delta=1.)
|
||||
/// \brief Simplify a polygon reducing the number of vertex according the distance "delta".
|
||||
/// Uses a version of the Ramer-Douglas-Peucker algorithm (http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm).
|
||||
/// \param p Contour (polygon type).
|
||||
/// \param delta Minimun distance.
|
||||
/// \return A simplify version of the original polygon.
|
||||
CvContourPolygon *cvSimplifyPolygon(CvContourPolygon const *p, double const delta=1.);
|
||||
|
||||
/// \fn CvContourPolygon *cvPolygonContourConvexHull(CvContourPolygon const *p)
|
||||
/// \brief Calculates convex hull of a contour.
|
||||
/// Uses the Melkman Algorithm. Code based on the version in http://w3.impa.br/~rdcastan/Cgeometry/.
|
||||
/// \param p Contour (polygon type).
|
||||
/// \return Convex hull.
|
||||
CvContourPolygon *cvPolygonContourConvexHull(CvContourPolygon const *p);
|
||||
|
||||
/// \fn void cvWriteContourPolygonCSV(const CvContourPolygon& p, const std::string& filename)
|
||||
/// \brief Write a contour to a CSV (Comma-separated values) file.
|
||||
/// \param p Polygon contour.
|
||||
/// \param filename File name.
|
||||
void cvWriteContourPolygonCSV(const CvContourPolygon& p, const std::string& filename);
|
||||
|
||||
/// \fn void cvWriteContourPolygonSVG(const CvContourPolygon& p, const std::string& filename, const CvScalar& stroke=cvScalar(0,0,0), const CvScalar& fill=cvScalar(255,255,255))
|
||||
/// \brief Write a contour to a SVG file (http://en.wikipedia.org/wiki/Scalable_Vector_Graphics).
|
||||
/// \param p Polygon contour.
|
||||
/// \param filename File name.
|
||||
/// \param stroke Stroke color (black by default).
|
||||
/// \param fill Fill color (white by default).
|
||||
void cvWriteContourPolygonSVG(const CvContourPolygon& p, const std::string& filename, const CvScalar& stroke=cvScalar(0,0,0), const CvScalar& fill=cvScalar(255,255,255));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Blobs
|
||||
|
||||
/// \brief Type of label.
|
||||
/// \see IPL_DEPTH_LABEL
|
||||
typedef unsigned int CvLabel;
|
||||
//typedef unsigned char CvLabel;
|
||||
|
||||
/// \def IPL_DEPTH_LABEL
|
||||
/// \brief Size of a label in bits.
|
||||
/// \see CvLabel
|
||||
#define IPL_DEPTH_LABEL (sizeof(cvb::CvLabel)*8)
|
||||
|
||||
/// \def CV_BLOB_MAX_LABEL
|
||||
/// \brief Max label number.
|
||||
/// \see CvLabel.
|
||||
#define CV_BLOB_MAX_LABEL std::numeric_limits<CvLabel>::max()
|
||||
|
||||
/// \brief Type of identification numbers.
|
||||
typedef unsigned int CvID;
|
||||
|
||||
/// \brief Struct that contain information about one blob.
|
||||
struct CvBlob
|
||||
{
|
||||
CvLabel label; ///< Label assigned to the blob.
|
||||
|
||||
union
|
||||
{
|
||||
unsigned int area; ///< Area (moment 00).
|
||||
unsigned int m00; ///< Moment 00 (area).
|
||||
};
|
||||
|
||||
unsigned int minx; ///< X min.
|
||||
unsigned int maxx; ///< X max.
|
||||
unsigned int miny; ///< Y min.
|
||||
unsigned int maxy; ///< y max.
|
||||
|
||||
CvPoint2D64f centroid; ///< Centroid.
|
||||
|
||||
double m10; ///< Moment 10.
|
||||
double m01; ///< Moment 01.
|
||||
double m11; ///< Moment 11.
|
||||
double m20; ///< Moment 20.
|
||||
double m02; ///< Moment 02.
|
||||
|
||||
double u11; ///< Central moment 11.
|
||||
double u20; ///< Central moment 20.
|
||||
double u02; ///< Central moment 02.
|
||||
|
||||
double n11; ///< Normalized central moment 11.
|
||||
double n20; ///< Normalized central moment 20.
|
||||
double n02; ///< Normalized central moment 02.
|
||||
|
||||
double p1; ///< Hu moment 1.
|
||||
double p2; ///< Hu moment 2.
|
||||
|
||||
CvContourChainCode contour; ///< Contour.
|
||||
CvContoursChainCode internalContours; ///< Internal contours.
|
||||
};
|
||||
|
||||
/// \var typedef std::map<CvLabel,CvBlob *> CvBlobs
|
||||
/// \brief List of blobs.
|
||||
/// A map is used to access each blob from its label number.
|
||||
/// \see CvLabel
|
||||
/// \see CvBlob
|
||||
typedef std::map<CvLabel,CvBlob *> CvBlobs;
|
||||
|
||||
/// \var typedef std::pair<CvLabel,CvBlob *> CvLabelBlob
|
||||
/// \brief Pair (label, blob).
|
||||
/// \see CvLabel
|
||||
/// \see CvBlob
|
||||
typedef std::pair<CvLabel,CvBlob *> CvLabelBlob;
|
||||
|
||||
/// \fn unsigned int cvLabel (IplImage const *img, IplImage *imgOut, CvBlobs &blobs);
|
||||
/// \brief Label the connected parts of a binary image.
|
||||
/// Algorithm based on paper "A linear-time component-labeling algorithm using contour tracing technique" of Fu Chang, Chun-Jen Chen and Chi-Jen Lu.
|
||||
/// \param img Input binary image (depth=IPL_DEPTH_8U and num. channels=1).
|
||||
/// \param imgOut Output image (depth=IPL_DEPTH_LABEL and num. channels=1).
|
||||
/// \param blobs List of blobs.
|
||||
/// \return Number of pixels that has been labeled.
|
||||
unsigned int cvLabel (IplImage const *img, IplImage *imgOut, CvBlobs &blobs);
|
||||
|
||||
//IplImage *cvFilterLabel(IplImage *imgIn, CvLabel label);
|
||||
|
||||
/// \fn void cvFilterLabels(IplImage *imgIn, IplImage *imgOut, const CvBlobs &blobs)
|
||||
/// \brief Draw a binary image with the blobs that have been given.
|
||||
/// \param imgIn Input image (depth=IPL_DEPTH_LABEL and num. channels=1).
|
||||
/// \param imgOut Output binary image (depth=IPL_DEPTH_8U and num. channels=1).
|
||||
/// \param blobs List of blobs to be drawn.
|
||||
/// \see cvLabel
|
||||
void cvFilterLabels(IplImage *imgIn, IplImage *imgOut, const CvBlobs &blobs);
|
||||
|
||||
/// \fn CvLabel cvGetLabel(IplImage const *img, unsigned int x, unsigned int y)
|
||||
/// \brief Get the label value from a labeled image.
|
||||
/// \param img Label image.
|
||||
/// \param x X coordenate.
|
||||
/// \param y Y coordenate.
|
||||
/// \return Label value.
|
||||
/// \see CvLabel
|
||||
CvLabel cvGetLabel(IplImage const *img, unsigned int x, unsigned int y);
|
||||
|
||||
/// \fn inline void cvReleaseBlob(CvBlob *blob)
|
||||
/// \brief Clear a blob structure.
|
||||
/// \param blob Blob.
|
||||
/// \see CvBlob
|
||||
inline void cvReleaseBlob(CvBlob *blob)
|
||||
{
|
||||
if (blob)
|
||||
{
|
||||
for (CvContoursChainCode::iterator jt=blob->internalContours.begin(); jt!=blob->internalContours.end(); ++jt)
|
||||
{
|
||||
CvContourChainCode *contour = *jt;
|
||||
if (contour)
|
||||
delete contour;
|
||||
}
|
||||
blob->internalContours.clear();
|
||||
|
||||
delete blob;
|
||||
}
|
||||
}
|
||||
|
||||
/// \fn inline void cvReleaseBlobs(CvBlobs &blobs)
|
||||
/// \brief Clear blobs structure.
|
||||
/// \param blobs List of blobs.
|
||||
/// \see CvBlobs
|
||||
inline void cvReleaseBlobs(CvBlobs &blobs)
|
||||
{
|
||||
for (CvBlobs::iterator it=blobs.begin(); it!=blobs.end(); ++it)
|
||||
{
|
||||
cvReleaseBlob((*it).second);
|
||||
}
|
||||
blobs.clear();
|
||||
}
|
||||
|
||||
/// \fn CvLabel cvLargestBlob(const CvBlobs &blobs)
|
||||
/// \brief Find largest blob (biggest area).
|
||||
/// \param blobs List of blobs.
|
||||
/// \return Label of the largest blob or 0 if there are no blobs.
|
||||
/// \see cvLabel
|
||||
CvLabel cvLargestBlob(const CvBlobs &blobs);
|
||||
|
||||
inline CvLabel cvGreaterBlob(const CvBlobs &blobs)
|
||||
{
|
||||
return cvLargestBlob(blobs);
|
||||
}
|
||||
|
||||
/// \fn void cvFilterByArea(CvBlobs &blobs, unsigned int minArea, unsigned int maxArea)
|
||||
/// \brief Filter blobs by area.
|
||||
/// Those blobs whose areas are not in range will be erased from the input list of blobs.
|
||||
/// \param blobs List of blobs.
|
||||
/// \param minArea Minimun area.
|
||||
/// \param maxArea Maximun area.
|
||||
void cvFilterByArea(CvBlobs &blobs, unsigned int minArea, unsigned int maxArea);
|
||||
|
||||
/// \fn void cvFilterByLabel(CvBlobs &blobs, CvLabel label)
|
||||
/// \brief Filter blobs by label.
|
||||
/// Delete all blobs except those with label l.
|
||||
/// \param blobs List of blobs.
|
||||
/// \param label Label to leave.
|
||||
void cvFilterByLabel(CvBlobs &blobs, CvLabel label);
|
||||
|
||||
/// \fn inline CvPoint2D64f cvCentroid(CvBlob *blob)
|
||||
/// \brief Calculates centroid.
|
||||
/// Centroid will be returned and stored in the blob structure.
|
||||
/// \param blob Blob whose centroid will be calculated.
|
||||
/// \return Centroid.
|
||||
/// \see CvBlob
|
||||
inline CvPoint2D64f cvCentroid(CvBlob *blob)
|
||||
{
|
||||
return blob->centroid=cvPoint2D64f(blob->m10/blob->area, blob->m01/blob->area);
|
||||
}
|
||||
|
||||
/// \fn double cvAngle(CvBlob *blob)
|
||||
/// \brief Calculates angle orientation of a blob.
|
||||
/// \param blob Blob.
|
||||
/// \return Angle orientation in radians.
|
||||
/// \see CvBlob
|
||||
double cvAngle(CvBlob *blob);
|
||||
|
||||
/// \fn cvSaveImageBlob(const char *filename, IplImage *img, CvBlob const *blob)
|
||||
/// \brief Save the image of a blob to a file.
|
||||
/// The function uses an image (that can be the original pre-processed image or a processed one, or even the result of cvRenderBlobs, for example) and a blob structure.
|
||||
/// Then the function saves a copy of the part of the image where the blob is.
|
||||
/// \param filename Name of the file.
|
||||
/// \param img Image.
|
||||
/// \param blob Blob.
|
||||
/// \see CvBlob
|
||||
/// \see cvRenderBlob
|
||||
void cvSaveImageBlob(const char *filename, IplImage *img, CvBlob const *blob);
|
||||
|
||||
#define CV_BLOB_RENDER_COLOR 0x0001 ///< Render each blog with a different color. \see cvRenderBlobs
|
||||
#define CV_BLOB_RENDER_CENTROID 0x0002 ///< Render centroid. \see cvRenderBlobs
|
||||
#define CV_BLOB_RENDER_BOUNDING_BOX 0x0004 ///< Render bounding box. \see cvRenderBlobs
|
||||
#define CV_BLOB_RENDER_ANGLE 0x0008 ///< Render angle. \see cvRenderBlobs
|
||||
#define CV_BLOB_RENDER_TO_LOG 0x0010 ///< Print blob data to log out. \see cvRenderBlobs
|
||||
#define CV_BLOB_RENDER_TO_STD 0x0020 ///< Print blob data to std out. \see cvRenderBlobs
|
||||
|
||||
/// \fn void cvRenderBlob(const IplImage *imgLabel, CvBlob *blob, IplImage *imgSource, IplImage *imgDest, unsigned short mode=0x000f, CvScalar const &color=CV_RGB(255, 255, 255), double alpha=1.)
|
||||
/// \brief Draws or prints information about a blob.
|
||||
/// \param imgLabel Label image (depth=IPL_DEPTH_LABEL and num. channels=1).
|
||||
/// \param blob Blob.
|
||||
/// \param imgSource Input image (depth=IPL_DEPTH_8U and num. channels=3).
|
||||
/// \param imgDest Output image (depth=IPL_DEPTH_8U and num. channels=3).
|
||||
/// \param mode Render mode. By default is CV_BLOB_RENDER_COLOR|CV_BLOB_RENDER_CENTROID|CV_BLOB_RENDER_BOUNDING_BOX|CV_BLOB_RENDER_ANGLE.
|
||||
/// \param color Color to render (if CV_BLOB_RENDER_COLOR is used).
|
||||
/// \param alpha If mode CV_BLOB_RENDER_COLOR is used. 1.0 indicates opaque and 0.0 translucent (1.0 by default).
|
||||
/// \see CV_BLOB_RENDER_COLOR
|
||||
/// \see CV_BLOB_RENDER_CENTROID
|
||||
/// \see CV_BLOB_RENDER_BOUNDING_BOX
|
||||
/// \see CV_BLOB_RENDER_ANGLE
|
||||
/// \see CV_BLOB_RENDER_TO_LOG
|
||||
/// \see CV_BLOB_RENDER_TO_STD
|
||||
void cvRenderBlob(const IplImage *imgLabel, CvBlob *blob, IplImage *imgSource, IplImage *imgDest, unsigned short mode=0x000f, CvScalar const &color=CV_RGB(255, 255, 255), double alpha=1.);
|
||||
|
||||
/// \fn void cvRenderBlobs(const IplImage *imgLabel, CvBlobs &blobs, IplImage *imgSource, IplImage *imgDest, unsigned short mode=0x000f, double alpha=1.)
|
||||
/// \brief Draws or prints information about blobs.
|
||||
/// \param imgLabel Label image (depth=IPL_DEPTH_LABEL and num. channels=1).
|
||||
/// \param blobs List of blobs.
|
||||
/// \param imgSource Input image (depth=IPL_DEPTH_8U and num. channels=3).
|
||||
/// \param imgDest Output image (depth=IPL_DEPTH_8U and num. channels=3).
|
||||
/// \param mode Render mode. By default is CV_BLOB_RENDER_COLOR|CV_BLOB_RENDER_CENTROID|CV_BLOB_RENDER_BOUNDING_BOX|CV_BLOB_RENDER_ANGLE.
|
||||
/// \param alpha If mode CV_BLOB_RENDER_COLOR is used. 1.0 indicates opaque and 0.0 translucent (1.0 by default).
|
||||
/// \see CV_BLOB_RENDER_COLOR
|
||||
/// \see CV_BLOB_RENDER_CENTROID
|
||||
/// \see CV_BLOB_RENDER_BOUNDING_BOX
|
||||
/// \see CV_BLOB_RENDER_ANGLE
|
||||
/// \see CV_BLOB_RENDER_TO_LOG
|
||||
/// \see CV_BLOB_RENDER_TO_STD
|
||||
void cvRenderBlobs(const IplImage *imgLabel, CvBlobs &blobs, IplImage *imgSource, IplImage *imgDest, unsigned short mode=0x000f, double alpha=1.);
|
||||
|
||||
/// \fn void cvSetImageROItoBlob(IplImage *img, CvBlob const *blob)
|
||||
/// \brief Set the ROI of an image to the bounding box of a blob.
|
||||
/// \param img Image.
|
||||
/// \param blob Blob.
|
||||
/// \see CvBlob
|
||||
inline void cvSetImageROItoBlob(IplImage *img, CvBlob const *blob)
|
||||
{
|
||||
cvSetImageROI(img, cvRect(blob->minx, blob->miny, blob->maxx-blob->minx, blob->maxy-blob->miny));
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Color
|
||||
|
||||
/// \fn CvScalar cvBlobMeanColor(CvBlob const *blob, IplImage const *imgLabel, IplImage const *img)
|
||||
/// \brief Calculates mean color of a blob in an image.
|
||||
/// \param blob Blob.
|
||||
/// \param imgLabel Image of labels.
|
||||
/// \param img Original image.
|
||||
/// \return Average color.
|
||||
CvScalar cvBlobMeanColor(CvBlob const *blob, IplImage const *imgLabel, IplImage const *img);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Aux
|
||||
|
||||
/// \fn double cvDotProductPoints(CvPoint const &a, CvPoint const &b, CvPoint const &c)
|
||||
/// \brief Dot product of the vectors ab and bc.
|
||||
/// \param a First point.
|
||||
/// \param b Middle point.
|
||||
/// \param c Last point.
|
||||
/// \return Dot product of ab and bc.
|
||||
double cvDotProductPoints(CvPoint const &a, CvPoint const &b, CvPoint const &c);
|
||||
|
||||
/// \fn double cvCrossProductPoints(CvPoint const &a, CvPoint const &b, CvPoint const &c)
|
||||
/// \brief Cross product of the vectors ab and bc.
|
||||
/// \param a Point.
|
||||
/// \param b Point.
|
||||
/// \param c Point.
|
||||
/// \return Cross product of ab and bc.
|
||||
double cvCrossProductPoints(CvPoint const &a, CvPoint const &b, CvPoint const &c);
|
||||
|
||||
/// \fn double cvDistancePointPoint(CvPoint const &a, CvPoint const &b)
|
||||
/// \brief Distance between two points.
|
||||
/// \param a Point.
|
||||
/// \param b Point.
|
||||
/// \return Distance.
|
||||
double cvDistancePointPoint(CvPoint const &a, CvPoint const &b);
|
||||
|
||||
/// \fn double cvDistanceLinePoint(CvPoint const &a, CvPoint const &b, CvPoint const &c, bool isSegment=true)
|
||||
/// \brief Distance between line ab and point c.
|
||||
/// \param a First point of the segment.
|
||||
/// \param b Second point of the segment.
|
||||
/// \param c Point.
|
||||
/// \param isSegment If false then the distance will be calculated from the line defined by the points a and b, to the point c.
|
||||
/// \return Distance between ab and c.
|
||||
double cvDistanceLinePoint(CvPoint const &a, CvPoint const &b, CvPoint const &c, bool isSegment=true);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tracking
|
||||
|
||||
/// \brief Struct that contain information about one track.
|
||||
/// \see CvID
|
||||
/// \see CvLabel
|
||||
struct CvTrack
|
||||
{
|
||||
CvID id; ///< Track identification number.
|
||||
|
||||
CvLabel label; ///< Label assigned to the blob related to this track.
|
||||
|
||||
unsigned int minx; ///< X min.
|
||||
unsigned int maxx; ///< X max.
|
||||
unsigned int miny; ///< Y min.
|
||||
unsigned int maxy; ///< y max.
|
||||
|
||||
CvPoint2D64f centroid; ///< Centroid.
|
||||
|
||||
unsigned int lifetime; ///< Indicates how much frames the object has been in scene.
|
||||
unsigned int active; ///< Indicates number of frames that has been active from last inactive period.
|
||||
unsigned int inactive; ///< Indicates number of frames that has been missing.
|
||||
};
|
||||
|
||||
/// \var typedef std::map<CvID, CvTrack *> CvTracks
|
||||
/// \brief List of tracks.
|
||||
/// \see CvID
|
||||
/// \see CvTrack
|
||||
typedef std::map<CvID, CvTrack *> CvTracks;
|
||||
|
||||
/// \var typedef std::pair<CvID, CvTrack *> CvIDTrack
|
||||
/// \brief Pair (identification number, track).
|
||||
/// \see CvID
|
||||
/// \see CvTrack
|
||||
typedef std::pair<CvID, CvTrack *> CvIDTrack;
|
||||
|
||||
/// \fn inline void cvReleaseTracks(CvTracks &tracks)
|
||||
/// \brief Clear tracks structure.
|
||||
/// \param tracks List of tracks.
|
||||
/// \see CvTracks
|
||||
inline void cvReleaseTracks(CvTracks &tracks)
|
||||
{
|
||||
for (CvTracks::iterator it=tracks.begin(); it!=tracks.end(); it++)
|
||||
{
|
||||
CvTrack *track = (*it).second;
|
||||
if (track) delete track;
|
||||
}
|
||||
|
||||
tracks.clear();
|
||||
}
|
||||
|
||||
/// \fn cvUpdateTracks(CvBlobs const &b, CvTracks &t, const double thDistance, const unsigned int thInactive, const unsigned int thActive=0)
|
||||
/// \brief Updates list of tracks based on current blobs.
|
||||
/// Tracking based on:
|
||||
/// A. Senior, A. Hampapur, Y-L Tian, L. Brown, S. Pankanti, R. Bolle. Appearance Models for
|
||||
/// Occlusion Handling. Second International workshop on Performance Evaluation of Tracking and
|
||||
/// Surveillance Systems & CVPR'01. December, 2001.
|
||||
/// (http://www.research.ibm.com/peoplevision/PETS2001.pdf)
|
||||
/// \param b List of blobs.
|
||||
/// \param t List of tracks.
|
||||
/// \param thDistance Max distance to determine when a track and a blob match.
|
||||
/// \param thInactive Max number of frames a track can be inactive.
|
||||
/// \param thActive If a track becomes inactive but it has been active less than thActive frames, the track will be deleted.
|
||||
/// \see CvBlobs
|
||||
/// \see Tracks
|
||||
void cvUpdateTracks(CvBlobs const &b, CvTracks &t, const double thDistance, const unsigned int thInactive, const unsigned int thActive=0);
|
||||
|
||||
#define CV_TRACK_RENDER_ID 0x0001 ///< Print the ID of each track in the image. \see cvRenderTracks
|
||||
#define CV_TRACK_RENDER_BOUNDING_BOX 0x0002 ///< Draw bounding box of each track in the image. \see cvRenderTracks
|
||||
#define CV_TRACK_RENDER_TO_LOG 0x0010 ///< Print track info to log out. \see cvRenderTracks
|
||||
#define CV_TRACK_RENDER_TO_STD 0x0020 ///< Print track info to log out. \see cvRenderTracks
|
||||
|
||||
/// \fn void cvRenderTracks(CvTracks const tracks, IplImage *imgSource, IplImage *imgDest, unsigned short mode=0x00ff, CvFont *font=NULL)
|
||||
/// \brief Prints tracks information.
|
||||
/// \param tracks List of tracks.
|
||||
/// \param imgSource Input image (depth=IPL_DEPTH_8U and num. channels=3).
|
||||
/// \param imgDest Output image (depth=IPL_DEPTH_8U and num. channels=3).
|
||||
/// \param mode Render mode. By default is CV_TRACK_RENDER_ID|CV_TRACK_RENDER_BOUNDING_BOX.
|
||||
/// \param font OpenCV font for print on the image.
|
||||
/// \see CV_TRACK_RENDER_ID
|
||||
/// \see CV_TRACK_RENDER_BOUNDING_BOX
|
||||
/// \see CV_TRACK_RENDER_TO_LOG
|
||||
/// \see CV_TRACK_RENDER_TO_STD
|
||||
void cvRenderTracks(CvTracks const tracks, IplImage *imgSource, IplImage *imgDest, unsigned short mode=0x000f, CvFont *font=NULL);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/// \fn std::ostream& operator<< (std::ostream& output, const cvb::CvBlob& b)
|
||||
/// \brief Overload operator "<<" for printing blob structure.
|
||||
/// \return Stream.
|
||||
std::ostream& operator<< (std::ostream& output, const cvb::CvBlob& b);
|
||||
|
||||
/// \fn std::ostream& operator<< (std::ostream& output, const cvb::CvContourPolygon& p)
|
||||
/// \brief Overload operator "<<" for printing polygons in CSV format.
|
||||
/// \return Stream.
|
||||
std::ostream& operator<< (std::ostream& output, const cvb::CvContourPolygon& p);
|
||||
|
||||
/// \fn std::ostream& operator<< (std::ostream& output, const cvb::CvTrack& t)
|
||||
/// \brief Overload operator "<<" for printing track structure.
|
||||
/// \return Stream.
|
||||
std::ostream& operator<< (std::ostream& output, const cvb::CvTrack& t);
|
||||
#endif
|
||||
@@ -0,0 +1,104 @@
|
||||
// Copyright (C) 2007 by Cristóbal Carnero Liñán
|
||||
// grendel.ccl@gmail.com
|
||||
//
|
||||
// This file is part of cvBlob.
|
||||
//
|
||||
// cvBlob is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the Lesser GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// cvBlob is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// Lesser GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the Lesser GNU General Public License
|
||||
// along with cvBlob. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#if (defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) || (defined(__APPLE__) & defined(__MACH__)))
|
||||
#include <cv.h>
|
||||
#else
|
||||
#include <opencv/cv.h>
|
||||
#endif
|
||||
|
||||
#include "cvblob.h"
|
||||
|
||||
namespace cvb
|
||||
{
|
||||
|
||||
CvScalar cvBlobMeanColor(CvBlob const *blob, IplImage const *imgLabel, IplImage const *img)
|
||||
{
|
||||
CV_FUNCNAME("cvBlobMeanColor");
|
||||
__CV_BEGIN__;
|
||||
{
|
||||
CV_ASSERT(imgLabel&&(imgLabel->depth==IPL_DEPTH_LABEL)&&(imgLabel->nChannels==1));
|
||||
CV_ASSERT(img&&(img->depth==IPL_DEPTH_8U)&&(img->nChannels==3));
|
||||
|
||||
int stepLbl = imgLabel->widthStep/(imgLabel->depth/8);
|
||||
int stepImg = img->widthStep/(img->depth/8);
|
||||
int imgLabel_width = imgLabel->width;
|
||||
int imgLabel_height = imgLabel->height;
|
||||
int imgLabel_offset = 0;
|
||||
int img_width = img->width;
|
||||
int img_height = img->height;
|
||||
int img_offset = 0;
|
||||
if(imgLabel->roi)
|
||||
{
|
||||
imgLabel_width = imgLabel->roi->width;
|
||||
imgLabel_height = imgLabel->roi->height;
|
||||
imgLabel_offset = (imgLabel->nChannels * imgLabel->roi->xOffset) + (imgLabel->roi->yOffset * stepLbl);
|
||||
}
|
||||
if(img->roi)
|
||||
{
|
||||
img_width = img->roi->width;
|
||||
img_height = img->roi->height;
|
||||
img_offset = (img->nChannels * img->roi->xOffset) + (img->roi->yOffset * stepImg);
|
||||
}
|
||||
|
||||
CvLabel *labels = (CvLabel *)imgLabel->imageData + imgLabel_offset;
|
||||
unsigned char *imgData = (unsigned char *)img->imageData + img_offset;
|
||||
|
||||
double mb = 0;
|
||||
double mg = 0;
|
||||
double mr = 0;
|
||||
double pixels = (double)blob->area;
|
||||
|
||||
for (unsigned int r=0; r<(unsigned int)imgLabel_height; r++, labels+=stepLbl, imgData+=stepImg)
|
||||
for (unsigned int c=0; c<(unsigned int)imgLabel_width; c++)
|
||||
{
|
||||
if (labels[c]==blob->label)
|
||||
{
|
||||
mb += ((double)imgData[img->nChannels*c+0])/pixels; // B
|
||||
mg += ((double)imgData[img->nChannels*c+1])/pixels; // G
|
||||
mr += ((double)imgData[img->nChannels*c+2])/pixels; // R
|
||||
}
|
||||
}
|
||||
|
||||
/*double mb = 0;
|
||||
double mg = 0;
|
||||
double mr = 0;
|
||||
double pixels = (double)blob->area;
|
||||
for (unsigned int y=0; y<imgLabel->height; y++)
|
||||
for (unsigned int x=0; x<imgLabel->width; x++)
|
||||
{
|
||||
if (cvGetLabel(imgLabel, x, y)==blob->label)
|
||||
{
|
||||
CvScalar color = cvGet2D(img, y, x);
|
||||
mb += color.val[0]/pixels;
|
||||
mg += color.val[1]/pixels;
|
||||
mr += color.val[2]/pixels;
|
||||
}
|
||||
}*/
|
||||
|
||||
return cvScalar(mr, mg, mb);
|
||||
}
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,436 @@
|
||||
// Copyright (C) 2007 by Cristóbal Carnero Liñán
|
||||
// grendel.ccl@gmail.com
|
||||
//
|
||||
// This file is part of cvBlob.
|
||||
//
|
||||
// cvBlob is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the Lesser GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// cvBlob is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// Lesser GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the Lesser GNU General Public License
|
||||
// along with cvBlob. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
#include <climits>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <cmath>
|
||||
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
#if (defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) || (defined(__APPLE__) & defined(__MACH__)))
|
||||
#include <cv.h>
|
||||
#else
|
||||
#include <opencv/cv.h>
|
||||
#endif
|
||||
|
||||
#include "cvblob.h"
|
||||
|
||||
#ifdef M_PI
|
||||
const double pi = M_PI;
|
||||
#else
|
||||
const double pi = std::atan(1.)*4.;
|
||||
#endif // M_PI
|
||||
|
||||
namespace cvb
|
||||
{
|
||||
|
||||
void cvRenderContourChainCode(CvContourChainCode const *contour, IplImage const *img, CvScalar const &color)
|
||||
{
|
||||
CV_FUNCNAME("cvRenderContourChainCode");
|
||||
__CV_BEGIN__;
|
||||
{
|
||||
CV_ASSERT(img&&(img->depth==IPL_DEPTH_8U)&&(img->nChannels==3));
|
||||
|
||||
int stepDst = img->widthStep/(img->depth/8);
|
||||
int img_width = img->width;
|
||||
int img_height = img->height;
|
||||
int img_offset = 0;
|
||||
|
||||
if(img->roi)
|
||||
{
|
||||
img_width = img->roi->width;
|
||||
img_height = img->roi->height;
|
||||
img_offset = (img->nChannels * img->roi->xOffset) + (img->roi->yOffset * stepDst);
|
||||
}
|
||||
|
||||
unsigned char *imgData = (unsigned char *)img->imageData + img_offset;
|
||||
|
||||
unsigned int x = contour->startingPoint.x;
|
||||
unsigned int y = contour->startingPoint.y;
|
||||
|
||||
for (CvChainCodes::const_iterator it=contour->chainCode.begin(); it!=contour->chainCode.end(); ++it)
|
||||
{
|
||||
imgData[img->nChannels*x+img->widthStep*y+0] = (unsigned char)(color.val[0]); // Blue
|
||||
imgData[img->nChannels*x+img->widthStep*y+1] = (unsigned char)(color.val[1]); // Green
|
||||
imgData[img->nChannels*x+img->widthStep*y+2] = (unsigned char)(color.val[2]); // Red
|
||||
|
||||
x += cvChainCodeMoves[*it][0];
|
||||
y += cvChainCodeMoves[*it][1];
|
||||
}
|
||||
}
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
CvContourPolygon *cvConvertChainCodesToPolygon(CvContourChainCode const *cc)
|
||||
{
|
||||
CV_FUNCNAME("cvConvertChainCodesToPolygon");
|
||||
__CV_BEGIN__;
|
||||
{
|
||||
CV_ASSERT(cc!=NULL);
|
||||
|
||||
CvContourPolygon *contour = new CvContourPolygon;
|
||||
|
||||
unsigned int x = cc->startingPoint.x;
|
||||
unsigned int y = cc->startingPoint.y;
|
||||
contour->push_back(cvPoint(x, y));
|
||||
|
||||
if (cc->chainCode.size())
|
||||
{
|
||||
CvChainCodes::const_iterator it=cc->chainCode.begin();
|
||||
CvChainCode lastCode = *it;
|
||||
|
||||
x += cvChainCodeMoves[*it][0];
|
||||
y += cvChainCodeMoves[*it][1];
|
||||
|
||||
++it;
|
||||
|
||||
for (; it!=cc->chainCode.end(); ++it)
|
||||
{
|
||||
if (lastCode!=*it)
|
||||
{
|
||||
contour->push_back(cvPoint(x, y));
|
||||
lastCode=*it;
|
||||
}
|
||||
|
||||
x += cvChainCodeMoves[*it][0];
|
||||
y += cvChainCodeMoves[*it][1];
|
||||
}
|
||||
}
|
||||
|
||||
return contour;
|
||||
}
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
void cvRenderContourPolygon(CvContourPolygon const *contour, IplImage *img, CvScalar const &color)
|
||||
{
|
||||
CV_FUNCNAME("cvRenderContourPolygon");
|
||||
__CV_BEGIN__;
|
||||
{
|
||||
CV_ASSERT(img&&(img->depth==IPL_DEPTH_8U)&&(img->nChannels==3));
|
||||
|
||||
CvContourPolygon::const_iterator it=contour->begin();
|
||||
|
||||
if (it!=contour->end())
|
||||
{
|
||||
unsigned int fx, x, fy, y;
|
||||
fx = x = it->x;
|
||||
fy = y = it->y;
|
||||
|
||||
for (; it!=contour->end(); ++it)
|
||||
{
|
||||
cvLine(img, cvPoint(x, y), cvPoint(it->x, it->y), color, 1);
|
||||
x = it->x;
|
||||
y = it->y;
|
||||
}
|
||||
|
||||
cvLine(img, cvPoint(x, y), cvPoint(fx, fy), color, 1);
|
||||
}
|
||||
}
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
double cvContourPolygonArea(CvContourPolygon const *p)
|
||||
{
|
||||
CV_FUNCNAME("cvContourPolygonArea");
|
||||
__CV_BEGIN__;
|
||||
{
|
||||
CV_ASSERT(p!=NULL);
|
||||
|
||||
if (p->size()<=2)
|
||||
return 1.;
|
||||
|
||||
CvContourPolygon::const_iterator it=p->begin();
|
||||
CvPoint lastPoint = p->back();
|
||||
|
||||
double a = 0.;
|
||||
|
||||
for (; it!=p->end(); ++it)
|
||||
{
|
||||
a += lastPoint.x*it->y - lastPoint.y*it->x;
|
||||
lastPoint = *it;
|
||||
}
|
||||
|
||||
return a*0.5;
|
||||
}
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
double cvContourChainCodePerimeter(CvContourChainCode const *c)
|
||||
{
|
||||
CV_FUNCNAME("cvContourChainCodePerimeter");
|
||||
__CV_BEGIN__;
|
||||
{
|
||||
CV_ASSERT(c!=NULL);
|
||||
|
||||
double perimeter = 0.;
|
||||
|
||||
for(CvChainCodes::const_iterator it=c->chainCode.begin(); it!=c->chainCode.end(); ++it)
|
||||
{
|
||||
if ((*it)%2)
|
||||
perimeter+=sqrt(1.+1.);
|
||||
else
|
||||
perimeter+=1.;
|
||||
}
|
||||
|
||||
return perimeter;
|
||||
}
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
double cvContourPolygonPerimeter(CvContourPolygon const *p)
|
||||
{
|
||||
CV_FUNCNAME("cvContourPolygonPerimeter");
|
||||
__CV_BEGIN__;
|
||||
{
|
||||
CV_ASSERT(p!=NULL);
|
||||
|
||||
double perimeter = cvDistancePointPoint((*p)[p->size()-1], (*p)[0]);
|
||||
|
||||
for (unsigned int i=0; i<p->size()-1; i++)
|
||||
perimeter+=cvDistancePointPoint((*p)[i], (*p)[i+1]);
|
||||
|
||||
return perimeter;
|
||||
}
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
double cvContourPolygonCircularity(const CvContourPolygon *p)
|
||||
{
|
||||
CV_FUNCNAME("cvContourPolygonCircularity");
|
||||
__CV_BEGIN__;
|
||||
{
|
||||
CV_ASSERT(p!=NULL);
|
||||
|
||||
double l = cvContourPolygonPerimeter(p);
|
||||
double c = (l*l/cvContourPolygonArea(p)) - 4.*pi;
|
||||
|
||||
if (c>=0.)
|
||||
return c;
|
||||
else // This could happen if the blob it's only a pixel: the perimeter will be 0. Another solution would be to force "cvContourPolygonPerimeter" to be 1 or greater.
|
||||
return 0.;
|
||||
}
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
void simplifyPolygonRecursive(CvContourPolygon const *p, int const i1, int const i2, bool *pnUseFlag, double const delta)
|
||||
{
|
||||
CV_FUNCNAME("cvSimplifyPolygonRecursive");
|
||||
__CV_BEGIN__;
|
||||
{
|
||||
int endIndex = (i2<0)?p->size():i2;
|
||||
|
||||
if (abs(i1-endIndex)<=1)
|
||||
return;
|
||||
|
||||
CvPoint firstPoint = (*p)[i1];
|
||||
CvPoint lastPoint = (i2<0)?p->front():(*p)[i2];
|
||||
|
||||
double furtherDistance=0.;
|
||||
int furtherIndex=0;
|
||||
|
||||
for (int i=i1+1; i<endIndex; i++)
|
||||
{
|
||||
double d = cvDistanceLinePoint(firstPoint, lastPoint, (*p)[i]);
|
||||
|
||||
if ((d>=delta)&&(d>furtherDistance))
|
||||
{
|
||||
furtherDistance=d;
|
||||
furtherIndex=i;
|
||||
}
|
||||
}
|
||||
|
||||
if (furtherIndex)
|
||||
{
|
||||
pnUseFlag[furtherIndex]=true;
|
||||
|
||||
simplifyPolygonRecursive(p, i1, furtherIndex, pnUseFlag, delta);
|
||||
simplifyPolygonRecursive(p, furtherIndex, i2, pnUseFlag, delta);
|
||||
}
|
||||
}
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
CvContourPolygon *cvSimplifyPolygon(CvContourPolygon const *p, double const delta)
|
||||
{
|
||||
CV_FUNCNAME("cvSimplifyPolygon");
|
||||
__CV_BEGIN__;
|
||||
{
|
||||
CV_ASSERT(p!=NULL);
|
||||
|
||||
double furtherDistance=0.;
|
||||
unsigned int furtherIndex=0;
|
||||
|
||||
CvContourPolygon::const_iterator it=p->begin();
|
||||
++it;
|
||||
for (unsigned int i=1; it!=p->end(); ++it, i++)
|
||||
{
|
||||
double d = cvDistancePointPoint(*it, p->front());
|
||||
|
||||
if (d>furtherDistance)
|
||||
{
|
||||
furtherDistance = d;
|
||||
furtherIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (furtherDistance<delta)
|
||||
{
|
||||
CvContourPolygon *result = new CvContourPolygon;
|
||||
result->push_back(p->front());
|
||||
return result;
|
||||
}
|
||||
|
||||
bool *pnUseFlag = new bool[p->size()];
|
||||
for (unsigned int i=1; i<p->size(); i++) pnUseFlag[i] = false;
|
||||
|
||||
pnUseFlag[0] = pnUseFlag[furtherIndex] = true;
|
||||
|
||||
simplifyPolygonRecursive(p, 0, furtherIndex, pnUseFlag, delta);
|
||||
simplifyPolygonRecursive(p, furtherIndex, -1, pnUseFlag, delta);
|
||||
|
||||
CvContourPolygon *result = new CvContourPolygon;
|
||||
|
||||
for (unsigned int i=0; i<p->size(); i++)
|
||||
if (pnUseFlag[i])
|
||||
result->push_back((*p)[i]);
|
||||
|
||||
delete[] pnUseFlag;
|
||||
|
||||
return result;
|
||||
}
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
CvContourPolygon *cvPolygonContourConvexHull(CvContourPolygon const *p)
|
||||
{
|
||||
CV_FUNCNAME("cvPolygonContourConvexHull");
|
||||
__CV_BEGIN__;
|
||||
{
|
||||
CV_ASSERT(p!=NULL);
|
||||
|
||||
if (p->size()<=3)
|
||||
{
|
||||
return new CvContourPolygon(p->begin(), p->end());
|
||||
}
|
||||
|
||||
deque<CvPoint> dq;
|
||||
|
||||
if (cvCrossProductPoints((*p)[0], (*p)[1], (*p)[2])>0)
|
||||
{
|
||||
dq.push_back((*p)[0]);
|
||||
dq.push_back((*p)[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
dq.push_back((*p)[1]);
|
||||
dq.push_back((*p)[0]);
|
||||
}
|
||||
|
||||
dq.push_back((*p)[2]);
|
||||
dq.push_front((*p)[2]);
|
||||
|
||||
for (unsigned int i=3; i<p->size(); i++)
|
||||
{
|
||||
int s = dq.size();
|
||||
|
||||
if ((cvCrossProductPoints((*p)[i], dq.at(0), dq.at(1))>=0) && (cvCrossProductPoints(dq.at(s-2), dq.at(s-1), (*p)[i])>=0))
|
||||
continue; // TODO Optimize.
|
||||
|
||||
while (cvCrossProductPoints(dq.at(s-2), dq.at(s-1), (*p)[i])<0)
|
||||
{
|
||||
dq.pop_back();
|
||||
s = dq.size();
|
||||
}
|
||||
|
||||
dq.push_back((*p)[i]);
|
||||
|
||||
while (cvCrossProductPoints((*p)[i], dq.at(0), dq.at(1))<0)
|
||||
dq.pop_front();
|
||||
|
||||
dq.push_front((*p)[i]);
|
||||
}
|
||||
|
||||
return new CvContourPolygon(dq.begin(), dq.end());
|
||||
}
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
void cvWriteContourPolygonCSV(const CvContourPolygon& p, const string& filename)
|
||||
{
|
||||
ofstream f;
|
||||
f.open(filename.c_str());
|
||||
|
||||
f << p << endl;
|
||||
|
||||
f.close();
|
||||
}
|
||||
|
||||
void cvWriteContourPolygonSVG(const CvContourPolygon& p, const string& filename, const CvScalar& stroke, const CvScalar& fill)
|
||||
{
|
||||
int minx=INT_MAX;
|
||||
int miny=INT_MAX;
|
||||
int maxx=INT_MIN;
|
||||
int maxy=INT_MIN;
|
||||
|
||||
stringstream buffer("");
|
||||
|
||||
for (CvContourPolygon::const_iterator it=p.begin(); it!=p.end(); ++it)
|
||||
{
|
||||
if (it->x>maxx)
|
||||
maxx = it->x;
|
||||
if (it->x<minx)
|
||||
minx = it->x;
|
||||
|
||||
if (it->y>maxy)
|
||||
maxy = it->y;
|
||||
if (it->y<miny)
|
||||
miny = it->y;
|
||||
|
||||
buffer << it->x << "," << it->y << " ";
|
||||
}
|
||||
|
||||
ofstream f;
|
||||
f.open(filename.c_str());
|
||||
|
||||
f << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\"?>" << endl;
|
||||
f << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">" << endl;
|
||||
f << "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:space=\"preserve\" width=\"" << maxx-minx << "px\" height=\"" << maxy-miny << "px\" viewBox=\"" << minx << " " << miny << " " << maxx << " " << maxy << "\" zoomAndPan=\"disable\" >" << endl;
|
||||
|
||||
f << "<polygon fill=\"rgb(" << fill.val[0] << "," << fill.val[1] << "," << fill.val[2] << ")\" stroke=\"rgb(" << stroke.val[0] << "," << stroke.val[1] << "," << stroke.val[2] << ")\" stroke-width=\"1\" points=\"" << buffer.str() << "\"/>" << endl;
|
||||
|
||||
f << "</svg>" << endl;
|
||||
|
||||
f.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream& output, const cvb::CvContourPolygon& p)
|
||||
{
|
||||
for (cvb::CvContourPolygon::const_iterator it=p.begin(); it!=p.end(); ++it)
|
||||
output << it->x << ", " << it->y << endl;
|
||||
|
||||
return output;
|
||||
}
|
||||
@@ -0,0 +1,444 @@
|
||||
// Copyright (C) 2007 by Cristóbal Carnero Liñán
|
||||
// grendel.ccl@gmail.com
|
||||
//
|
||||
// This file is part of cvBlob.
|
||||
//
|
||||
// cvBlob is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the Lesser GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// cvBlob is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// Lesser GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the Lesser GNU General Public License
|
||||
// along with cvBlob. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#if (defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) || (defined(__APPLE__) & defined(__MACH__)))
|
||||
#include <cv.h>
|
||||
#else
|
||||
#include <opencv/cv.h>
|
||||
#endif
|
||||
|
||||
#include "cvblob.h"
|
||||
|
||||
namespace cvb
|
||||
{
|
||||
const char movesE[4][3][4] = { { {-1, -1, 3, CV_CHAINCODE_UP_LEFT }, { 0, -1, 0, CV_CHAINCODE_UP }, { 1, -1, 0, CV_CHAINCODE_UP_RIGHT } },
|
||||
{ { 1, -1, 0, CV_CHAINCODE_UP_RIGHT }, { 1, 0, 1, CV_CHAINCODE_RIGHT}, { 1, 1, 1, CV_CHAINCODE_DOWN_RIGHT } },
|
||||
{ { 1, 1, 1, CV_CHAINCODE_DOWN_RIGHT}, { 0, 1, 2, CV_CHAINCODE_DOWN }, {-1, 1, 2, CV_CHAINCODE_DOWN_LEFT } },
|
||||
{ {-1, 1, 2, CV_CHAINCODE_DOWN_LEFT }, {-1, 0, 3, CV_CHAINCODE_LEFT }, {-1, -1, 3, CV_CHAINCODE_UP_LEFT } }
|
||||
};
|
||||
|
||||
const char movesI[4][3][4] = { { { 1, -1, 3, CV_CHAINCODE_UP_RIGHT }, { 0, -1, 0, CV_CHAINCODE_UP }, {-1, -1, 0, CV_CHAINCODE_UP_LEFT } },
|
||||
{ {-1, -1, 0, CV_CHAINCODE_UP_LEFT }, {-1, 0, 1, CV_CHAINCODE_LEFT }, {-1, 1, 1, CV_CHAINCODE_DOWN_LEFT } },
|
||||
{ {-1, 1, 1, CV_CHAINCODE_DOWN_LEFT }, { 0, 1, 2, CV_CHAINCODE_DOWN }, { 1, 1, 2, CV_CHAINCODE_DOWN_RIGHT } },
|
||||
{ { 1, 1, 2, CV_CHAINCODE_DOWN_RIGHT }, { 1, 0, 3, CV_CHAINCODE_RIGHT}, { 1, -1, 3, CV_CHAINCODE_UP_RIGHT } }
|
||||
};
|
||||
|
||||
|
||||
unsigned int cvLabel (IplImage const *img, IplImage *imgOut, CvBlobs &blobs)
|
||||
{
|
||||
CV_FUNCNAME("cvLabel");
|
||||
__CV_BEGIN__;
|
||||
{
|
||||
CV_ASSERT(img&&(img->depth==IPL_DEPTH_8U)&&(img->nChannels==1));
|
||||
CV_ASSERT(imgOut&&(imgOut->depth==IPL_DEPTH_LABEL)&&(imgOut->nChannels==1));
|
||||
|
||||
unsigned int numPixels=0;
|
||||
|
||||
cvSetZero(imgOut);
|
||||
|
||||
CvLabel label=0;
|
||||
cvReleaseBlobs(blobs);
|
||||
|
||||
unsigned int stepIn = img->widthStep / (img->depth / 8);
|
||||
unsigned int stepOut = imgOut->widthStep / (imgOut->depth / 8);
|
||||
unsigned int imgIn_width = img->width;
|
||||
unsigned int imgIn_height = img->height;
|
||||
unsigned int imgIn_offset = 0;
|
||||
unsigned int imgOut_width = imgOut->width;
|
||||
unsigned int imgOut_height = imgOut->height;
|
||||
unsigned int imgOut_offset = 0;
|
||||
if(img->roi)
|
||||
{
|
||||
imgIn_width = img->roi->width;
|
||||
imgIn_height = img->roi->height;
|
||||
imgIn_offset = img->roi->xOffset + (img->roi->yOffset * stepIn);
|
||||
}
|
||||
if(imgOut->roi)
|
||||
{
|
||||
imgOut_width = imgOut->roi->width;
|
||||
imgOut_height = imgOut->roi->height;
|
||||
imgOut_offset = imgOut->roi->xOffset + (imgOut->roi->yOffset * stepOut);
|
||||
}
|
||||
|
||||
unsigned char *imgDataIn = (unsigned char *)img->imageData + imgIn_offset;
|
||||
CvLabel *imgDataOut = (CvLabel *)imgOut->imageData + imgOut_offset;
|
||||
|
||||
#define imageIn(X, Y) imgDataIn[(X) + (Y)*stepIn]
|
||||
#define imageOut(X, Y) imgDataOut[(X) + (Y)*stepOut]
|
||||
|
||||
CvLabel lastLabel = 0;
|
||||
CvBlob *lastBlob = NULL;
|
||||
|
||||
for (unsigned int y=0; y<imgIn_height; y++)
|
||||
{
|
||||
for (unsigned int x=0; x<imgIn_width; x++)
|
||||
{
|
||||
if (imageIn(x, y))
|
||||
{
|
||||
bool labeled = imageOut(x, y);
|
||||
|
||||
if ((!imageOut(x, y))&&((y==0)||(!imageIn(x, y-1))))
|
||||
{
|
||||
labeled = true;
|
||||
|
||||
// Label contour.
|
||||
label++;
|
||||
CV_ASSERT(label!=CV_BLOB_MAX_LABEL);
|
||||
|
||||
imageOut(x, y) = label;
|
||||
numPixels++;
|
||||
|
||||
// XXX This is not necessary at all. I only do this for consistency.
|
||||
if (y>0)
|
||||
imageOut(x, y-1) = CV_BLOB_MAX_LABEL;
|
||||
|
||||
CvBlob *blob = new CvBlob;
|
||||
blob->label = label;
|
||||
blob->area = 1;
|
||||
blob->minx = x; blob->maxx = x;
|
||||
blob->miny = y; blob->maxy = y;
|
||||
blob->m10=x; blob->m01=y;
|
||||
blob->m11=x*y;
|
||||
blob->m20=x*x; blob->m02=y*y;
|
||||
blob->internalContours.clear();
|
||||
blobs.insert(CvLabelBlob(label,blob));
|
||||
|
||||
lastLabel = label;
|
||||
lastBlob = blob;
|
||||
|
||||
blob->contour.startingPoint = cvPoint(x, y);
|
||||
|
||||
unsigned char direction=1;
|
||||
unsigned int xx = x;
|
||||
unsigned int yy = y;
|
||||
|
||||
|
||||
bool contourEnd = false;
|
||||
|
||||
do
|
||||
{
|
||||
for (unsigned int numAttempts=0; numAttempts<3; numAttempts++)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
for (unsigned char i=0; i<3; i++)
|
||||
{
|
||||
int nx = xx+movesE[direction][i][0];
|
||||
int ny = yy+movesE[direction][i][1];
|
||||
if ((nx<imgIn_width)&&(nx>=0)&&(ny<imgIn_height)&&(ny>=0))
|
||||
{
|
||||
if (imageIn(nx, ny))
|
||||
{
|
||||
found = true;
|
||||
|
||||
blob->contour.chainCode.push_back(movesE[direction][i][3]);
|
||||
|
||||
xx=nx;
|
||||
yy=ny;
|
||||
|
||||
direction=movesE[direction][i][2];
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
imageOut(nx, ny) = CV_BLOB_MAX_LABEL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
direction=(direction+1)%4;
|
||||
else
|
||||
{
|
||||
if (imageOut(xx, yy) != label)
|
||||
{
|
||||
imageOut(xx, yy) = label;
|
||||
numPixels++;
|
||||
|
||||
if (xx<blob->minx) blob->minx = xx;
|
||||
else if (xx>blob->maxx) blob->maxx = xx;
|
||||
if (yy<blob->miny) blob->miny = yy;
|
||||
else if (yy>blob->maxy) blob->maxy = yy;
|
||||
|
||||
blob->area++;
|
||||
blob->m10+=xx; blob->m01+=yy;
|
||||
blob->m11+=xx*yy;
|
||||
blob->m20+=xx*xx; blob->m02+=yy*yy;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (contourEnd = ((xx==x) && (yy==y) && (direction==1)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!contourEnd);
|
||||
|
||||
}
|
||||
|
||||
if ((y+1<imgIn_height)&&(!imageIn(x, y+1))&&(!imageOut(x, y+1)))
|
||||
{
|
||||
labeled = true;
|
||||
|
||||
// Label internal contour
|
||||
CvLabel l;
|
||||
CvBlob *blob = NULL;
|
||||
|
||||
if (!imageOut(x, y))
|
||||
{
|
||||
/*if (!imageOut(x-1, y))
|
||||
{
|
||||
cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
|
||||
continue;
|
||||
}*/
|
||||
|
||||
l = imageOut(x-1, y);
|
||||
|
||||
imageOut(x, y) = l;
|
||||
numPixels++;
|
||||
|
||||
if (l==lastLabel)
|
||||
blob = lastBlob;
|
||||
else
|
||||
{
|
||||
blob = blobs.find(l)->second;
|
||||
lastLabel = l;
|
||||
lastBlob = blob;
|
||||
}
|
||||
blob->area++;
|
||||
blob->m10+=x; blob->m01+=y;
|
||||
blob->m11+=x*y;
|
||||
blob->m20+=x*x; blob->m02+=y*y;
|
||||
}
|
||||
else
|
||||
{
|
||||
l = imageOut(x, y);
|
||||
|
||||
if (l==lastLabel)
|
||||
blob = lastBlob;
|
||||
else
|
||||
{
|
||||
blob = blobs.find(l)->second;
|
||||
lastLabel = l;
|
||||
lastBlob = blob;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX This is not necessary (I believe). I only do this for consistency.
|
||||
imageOut(x, y+1) = CV_BLOB_MAX_LABEL;
|
||||
|
||||
CvContourChainCode *contour = new CvContourChainCode;
|
||||
contour->startingPoint = cvPoint(x, y);
|
||||
|
||||
unsigned char direction = 3;
|
||||
unsigned int xx = x;
|
||||
unsigned int yy = y;
|
||||
|
||||
do
|
||||
{
|
||||
for (unsigned int numAttempts=0; numAttempts<3; numAttempts++)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
for (unsigned char i=0; i<3; i++)
|
||||
{
|
||||
int nx = xx+movesI[direction][i][0];
|
||||
int ny = yy+movesI[direction][i][1];
|
||||
if (imageIn(nx, ny))
|
||||
{
|
||||
found = true;
|
||||
|
||||
contour->chainCode.push_back(movesI[direction][i][3]);
|
||||
|
||||
xx=nx;
|
||||
yy=ny;
|
||||
|
||||
direction=movesI[direction][i][2];
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
imageOut(nx, ny) = CV_BLOB_MAX_LABEL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
direction=(direction+1)%4;
|
||||
else
|
||||
{
|
||||
if (!imageOut(xx, yy))
|
||||
{
|
||||
imageOut(xx, yy) = l;
|
||||
numPixels++;
|
||||
|
||||
blob->area++;
|
||||
blob->m10+=xx; blob->m01+=yy;
|
||||
blob->m11+=xx*yy;
|
||||
blob->m20+=xx*xx; blob->m02+=yy*yy;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!(xx==x && yy==y));
|
||||
|
||||
blob->internalContours.push_back(contour);
|
||||
}
|
||||
|
||||
//else if (!imageOut(x, y))
|
||||
if (!labeled)
|
||||
{
|
||||
// Internal pixel
|
||||
CvLabel l = imageOut(x-1, y);
|
||||
|
||||
imageOut(x, y) = l;
|
||||
numPixels++;
|
||||
|
||||
CvBlob *blob = NULL;
|
||||
if (l==lastLabel)
|
||||
blob = lastBlob;
|
||||
else
|
||||
{
|
||||
blob = blobs.find(l)->second;
|
||||
lastLabel = l;
|
||||
lastBlob = blob;
|
||||
}
|
||||
blob->area++;
|
||||
blob->m10+=x; blob->m01+=y;
|
||||
blob->m11+=x*y;
|
||||
blob->m20+=x*x; blob->m02+=y*y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (CvBlobs::iterator it=blobs.begin(); it!=blobs.end(); ++it)
|
||||
{
|
||||
cvCentroid((*it).second);
|
||||
|
||||
(*it).second->u11 = (*it).second->m11 - ((*it).second->m10*(*it).second->m01)/(*it).second->m00;
|
||||
(*it).second->u20 = (*it).second->m20 - ((*it).second->m10*(*it).second->m10)/(*it).second->m00;
|
||||
(*it).second->u02 = (*it).second->m02 - ((*it).second->m01*(*it).second->m01)/(*it).second->m00;
|
||||
|
||||
double m00_2 = (*it).second->m00 * (*it).second->m00;
|
||||
|
||||
(*it).second->n11 = (*it).second->u11 / m00_2;
|
||||
(*it).second->n20 = (*it).second->u20 / m00_2;
|
||||
(*it).second->n02 = (*it).second->u02 / m00_2;
|
||||
|
||||
(*it).second->p1 = (*it).second->n20 + (*it).second->n02;
|
||||
|
||||
double nn = (*it).second->n20 - (*it).second->n02;
|
||||
(*it).second->p2 = nn*nn + 4.*((*it).second->n11*(*it).second->n11);
|
||||
}
|
||||
|
||||
return numPixels;
|
||||
|
||||
}
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
void cvFilterLabels(IplImage *imgIn, IplImage *imgOut, const CvBlobs &blobs)
|
||||
{
|
||||
CV_FUNCNAME("cvFilterLabels");
|
||||
__CV_BEGIN__;
|
||||
{
|
||||
CV_ASSERT(imgIn&&(imgIn->depth==IPL_DEPTH_LABEL)&&(imgIn->nChannels==1));
|
||||
CV_ASSERT(imgOut&&(imgOut->depth==IPL_DEPTH_8U)&&(imgOut->nChannels==1));
|
||||
|
||||
int stepIn = imgIn->widthStep / (imgIn->depth / 8);
|
||||
int stepOut = imgOut->widthStep / (imgOut->depth / 8);
|
||||
int imgIn_width = imgIn->width;
|
||||
int imgIn_height = imgIn->height;
|
||||
int imgIn_offset = 0;
|
||||
int imgOut_width = imgOut->width;
|
||||
int imgOut_height = imgOut->height;
|
||||
int imgOut_offset = 0;
|
||||
if(imgIn->roi)
|
||||
{
|
||||
imgIn_width = imgIn->roi->width;
|
||||
imgIn_height = imgIn->roi->height;
|
||||
imgIn_offset = imgIn->roi->xOffset + (imgIn->roi->yOffset * stepIn);
|
||||
}
|
||||
if(imgOut->roi)
|
||||
{
|
||||
imgOut_width = imgOut->roi->width;
|
||||
imgOut_height = imgOut->roi->height;
|
||||
imgOut_offset = imgOut->roi->xOffset + (imgOut->roi->yOffset * stepOut);
|
||||
}
|
||||
|
||||
char *imgDataOut=imgOut->imageData + imgOut_offset;
|
||||
CvLabel *imgDataIn=(CvLabel *)imgIn->imageData + imgIn_offset;
|
||||
|
||||
for (unsigned int r=0;r<(unsigned int)imgIn_height;r++,
|
||||
imgDataIn+=stepIn,imgDataOut+=stepOut)
|
||||
{
|
||||
for (unsigned int c=0;c<(unsigned int)imgIn_width;c++)
|
||||
{
|
||||
if (imgDataIn[c])
|
||||
{
|
||||
if (blobs.find(imgDataIn[c])==blobs.end()) imgDataOut[c]=0x00;
|
||||
else imgDataOut[c]=(char)0xff;
|
||||
}
|
||||
else
|
||||
imgDataOut[c]=0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
|
||||
CvLabel cvGetLabel(IplImage const *img, unsigned int x, unsigned int y)
|
||||
{
|
||||
CV_FUNCNAME("cvGetLabel");
|
||||
__CV_BEGIN__;
|
||||
{
|
||||
CV_ASSERT(img&&(img->depth==IPL_DEPTH_LABEL)&&(img->nChannels==1));
|
||||
|
||||
int step = img->widthStep / (img->depth / 8);
|
||||
int img_width = 0;
|
||||
int img_height= 0;
|
||||
int img_offset = 0;
|
||||
if(img->roi)
|
||||
{
|
||||
img_width = img->roi->width;
|
||||
img_height = img->roi->height;
|
||||
img_offset = img->roi->xOffset + (img->roi->yOffset * step);
|
||||
}
|
||||
else
|
||||
{
|
||||
img_width = img->width;
|
||||
img_height= img->height;
|
||||
}
|
||||
|
||||
CV_ASSERT((x>=0)&&(x<img_width)&&(y>=0)&&(y<img_height));
|
||||
|
||||
return ((CvLabel *)(img->imageData + img_offset))[x + y*step];
|
||||
}
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,419 @@
|
||||
// Copyright (C) 2007 by Cristóbal Carnero Liñán
|
||||
// grendel.ccl@gmail.com
|
||||
//
|
||||
// This file is part of cvBlob.
|
||||
//
|
||||
// cvBlob is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the Lesser GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// cvBlob is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// Lesser GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the Lesser GNU General Public License
|
||||
// along with cvBlob. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
#if (defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) || (defined(__APPLE__) & defined(__MACH__)))
|
||||
#include <cv.h>
|
||||
#else
|
||||
#include <opencv/cv.h>
|
||||
#endif
|
||||
|
||||
#include "cvblob.h"
|
||||
|
||||
namespace cvb
|
||||
{
|
||||
|
||||
double distantBlobTrack(CvBlob const *b, CvTrack const *t)
|
||||
{
|
||||
double d1;
|
||||
if (b->centroid.x<t->minx)
|
||||
{
|
||||
if (b->centroid.y<t->miny)
|
||||
d1 = MAX(t->minx - b->centroid.x, t->miny - b->centroid.y);
|
||||
else if (b->centroid.y>t->maxy)
|
||||
d1 = MAX(t->minx - b->centroid.x, b->centroid.y - t->maxy);
|
||||
else // if (t->miny < b->centroid.y)&&(b->centroid.y < t->maxy)
|
||||
d1 = t->minx - b->centroid.x;
|
||||
}
|
||||
else if (b->centroid.x>t->maxx)
|
||||
{
|
||||
if (b->centroid.y<t->miny)
|
||||
d1 = MAX(b->centroid.x - t->maxx, t->miny - b->centroid.y);
|
||||
else if (b->centroid.y>t->maxy)
|
||||
d1 = MAX(b->centroid.x - t->maxx, b->centroid.y - t->maxy);
|
||||
else
|
||||
d1 = b->centroid.x - t->maxx;
|
||||
}
|
||||
else // if (t->minx =< b->centroid.x) && (b->centroid.x =< t->maxx)
|
||||
{
|
||||
if (b->centroid.y<t->miny)
|
||||
d1 = t->miny - b->centroid.y;
|
||||
else if (b->centroid.y>t->maxy)
|
||||
d1 = b->centroid.y - t->maxy;
|
||||
else
|
||||
return 0.;
|
||||
}
|
||||
|
||||
double d2;
|
||||
if (t->centroid.x<b->minx)
|
||||
{
|
||||
if (t->centroid.y<b->miny)
|
||||
d2 = MAX(b->minx - t->centroid.x, b->miny - t->centroid.y);
|
||||
else if (t->centroid.y>b->maxy)
|
||||
d2 = MAX(b->minx - t->centroid.x, t->centroid.y - b->maxy);
|
||||
else // if (b->miny < t->centroid.y)&&(t->centroid.y < b->maxy)
|
||||
d2 = b->minx - t->centroid.x;
|
||||
}
|
||||
else if (t->centroid.x>b->maxx)
|
||||
{
|
||||
if (t->centroid.y<b->miny)
|
||||
d2 = MAX(t->centroid.x - b->maxx, b->miny - t->centroid.y);
|
||||
else if (t->centroid.y>b->maxy)
|
||||
d2 = MAX(t->centroid.x - b->maxx, t->centroid.y - b->maxy);
|
||||
else
|
||||
d2 = t->centroid.x - b->maxx;
|
||||
}
|
||||
else // if (b->minx =< t->centroid.x) && (t->centroid.x =< b->maxx)
|
||||
{
|
||||
if (t->centroid.y<b->miny)
|
||||
d2 = b->miny - t->centroid.y;
|
||||
else if (t->centroid.y>b->maxy)
|
||||
d2 = t->centroid.y - b->maxy;
|
||||
else
|
||||
return 0.;
|
||||
}
|
||||
|
||||
return MIN(d1, d2);
|
||||
}
|
||||
|
||||
// Access to matrix
|
||||
#define C(blob, track) close[((blob) + (track)*(nBlobs+2))]
|
||||
// Access to accumulators
|
||||
#define AB(label) C((label), (nTracks))
|
||||
#define AT(id) C((nBlobs), (id))
|
||||
// Access to identifications
|
||||
#define IB(label) C((label), (nTracks)+1)
|
||||
#define IT(id) C((nBlobs)+1, (id))
|
||||
// Access to registers
|
||||
#define B(label) blobs.find(IB(label))->second
|
||||
#define T(id) tracks.find(IT(id))->second
|
||||
|
||||
void getClusterForTrack(unsigned int trackPos, CvID *close, unsigned int nBlobs, unsigned int nTracks, CvBlobs const &blobs, CvTracks const &tracks, list<CvBlob*> &bb, list<CvTrack*> &tt);
|
||||
|
||||
void getClusterForBlob(unsigned int blobPos, CvID *close, unsigned int nBlobs, unsigned int nTracks, CvBlobs const &blobs, CvTracks const &tracks, list<CvBlob*> &bb, list<CvTrack*> &tt)
|
||||
{
|
||||
for (unsigned int j=0; j<nTracks; j++)
|
||||
{
|
||||
if (C(blobPos, j))
|
||||
{
|
||||
tt.push_back(T(j));
|
||||
|
||||
unsigned int c = AT(j);
|
||||
|
||||
C(blobPos, j) = 0;
|
||||
AB(blobPos)--;
|
||||
AT(j)--;
|
||||
|
||||
if (c>1)
|
||||
{
|
||||
getClusterForTrack(j, close, nBlobs, nTracks, blobs, tracks, bb, tt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getClusterForTrack(unsigned int trackPos, CvID *close, unsigned int nBlobs, unsigned int nTracks, CvBlobs const &blobs, CvTracks const &tracks, list<CvBlob*> &bb, list<CvTrack*> &tt)
|
||||
{
|
||||
for (unsigned int i=0; i<nBlobs; i++)
|
||||
{
|
||||
if (C(i, trackPos))
|
||||
{
|
||||
bb.push_back(B(i));
|
||||
|
||||
unsigned int c = AB(i);
|
||||
|
||||
C(i, trackPos) = 0;
|
||||
AB(i)--;
|
||||
AT(trackPos)--;
|
||||
|
||||
if (c>1)
|
||||
{
|
||||
getClusterForBlob(i, close, nBlobs, nTracks, blobs, tracks, bb, tt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cvUpdateTracks(CvBlobs const &blobs, CvTracks &tracks, const double thDistance, const unsigned int thInactive, const unsigned int thActive)
|
||||
{
|
||||
CV_FUNCNAME("cvUpdateTracks");
|
||||
__CV_BEGIN__;
|
||||
|
||||
unsigned int nBlobs = blobs.size();
|
||||
unsigned int nTracks = tracks.size();
|
||||
|
||||
// Proximity matrix:
|
||||
// Last row/column is for ID/label.
|
||||
// Last-1 "/" is for accumulation.
|
||||
CvID *close = new unsigned int[(nBlobs+2)*(nTracks+2)]; // XXX Must be same type than CvLabel.
|
||||
|
||||
try
|
||||
{
|
||||
// Inicialization:
|
||||
unsigned int i=0;
|
||||
for (CvBlobs::const_iterator it = blobs.begin(); it!=blobs.end(); ++it, i++)
|
||||
{
|
||||
AB(i) = 0;
|
||||
IB(i) = it->second->label;
|
||||
}
|
||||
|
||||
CvID maxTrackID = 0;
|
||||
|
||||
unsigned int j=0;
|
||||
for (CvTracks::const_iterator jt = tracks.begin(); jt!=tracks.end(); ++jt, j++)
|
||||
{
|
||||
AT(j) = 0;
|
||||
IT(j) = jt->second->id;
|
||||
if (jt->second->id > maxTrackID)
|
||||
maxTrackID = jt->second->id;
|
||||
}
|
||||
|
||||
// Proximity matrix calculation and "used blob" list inicialization:
|
||||
for (i=0; i<nBlobs; i++)
|
||||
for (j=0; j<nTracks; j++)
|
||||
if (C(i, j) = (distantBlobTrack(B(i), T(j)) < thDistance))
|
||||
{
|
||||
AB(i)++;
|
||||
AT(j)++;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Detect inactive tracks
|
||||
for (j=0; j<nTracks; j++)
|
||||
{
|
||||
unsigned int c = AT(j);
|
||||
|
||||
if (c==0)
|
||||
{
|
||||
//cout << "Inactive track: " << j << endl;
|
||||
|
||||
// Inactive track.
|
||||
CvTrack *track = T(j);
|
||||
track->inactive++;
|
||||
track->label = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Detect new tracks
|
||||
for (i=0; i<nBlobs; i++)
|
||||
{
|
||||
unsigned int c = AB(i);
|
||||
|
||||
if (c==0)
|
||||
{
|
||||
//cout << "Blob (new track): " << maxTrackID+1 << endl;
|
||||
//cout << *B(i) << endl;
|
||||
|
||||
// New track.
|
||||
maxTrackID++;
|
||||
CvBlob *blob = B(i);
|
||||
CvTrack *track = new CvTrack;
|
||||
track->id = maxTrackID;
|
||||
track->label = blob->label;
|
||||
track->minx = blob->minx;
|
||||
track->miny = blob->miny;
|
||||
track->maxx = blob->maxx;
|
||||
track->maxy = blob->maxy;
|
||||
track->centroid = blob->centroid;
|
||||
track->lifetime = 0;
|
||||
track->active = 0;
|
||||
track->inactive = 0;
|
||||
tracks.insert(CvIDTrack(maxTrackID, track));
|
||||
}
|
||||
}
|
||||
|
||||
// Clustering
|
||||
for (j=0; j<nTracks; j++)
|
||||
{
|
||||
unsigned int c = AT(j);
|
||||
|
||||
if (c)
|
||||
{
|
||||
list<CvTrack*> tt; tt.push_back(T(j));
|
||||
list<CvBlob*> bb;
|
||||
|
||||
getClusterForTrack(j, close, nBlobs, nTracks, blobs, tracks, bb, tt);
|
||||
|
||||
// Select track
|
||||
CvTrack *track;
|
||||
unsigned int area = 0;
|
||||
for (list<CvTrack*>::const_iterator it=tt.begin(); it!=tt.end(); ++it)
|
||||
{
|
||||
CvTrack *t = *it;
|
||||
|
||||
unsigned int a = (t->maxx-t->minx)*(t->maxy-t->miny);
|
||||
if (a>area)
|
||||
{
|
||||
area = a;
|
||||
track = t;
|
||||
}
|
||||
}
|
||||
|
||||
// Select blob
|
||||
CvBlob *blob;
|
||||
area = 0;
|
||||
//cout << "Matching blobs: ";
|
||||
for (list<CvBlob*>::const_iterator it=bb.begin(); it!=bb.end(); ++it)
|
||||
{
|
||||
CvBlob *b = *it;
|
||||
|
||||
//cout << b->label << " ";
|
||||
|
||||
if (b->area>area)
|
||||
{
|
||||
area = b->area;
|
||||
blob = b;
|
||||
}
|
||||
}
|
||||
//cout << endl;
|
||||
|
||||
// Update track
|
||||
//cout << "Matching: track=" << track->id << ", blob=" << blob->label << endl;
|
||||
track->label = blob->label;
|
||||
track->centroid = blob->centroid;
|
||||
track->minx = blob->minx;
|
||||
track->miny = blob->miny;
|
||||
track->maxx = blob->maxx;
|
||||
track->maxy = blob->maxy;
|
||||
if (track->inactive)
|
||||
track->active = 0;
|
||||
track->inactive = 0;
|
||||
|
||||
// Others to inactive
|
||||
for (list<CvTrack*>::const_iterator it=tt.begin(); it!=tt.end(); ++it)
|
||||
{
|
||||
CvTrack *t = *it;
|
||||
|
||||
if (t!=track)
|
||||
{
|
||||
//cout << "Inactive: track=" << t->id << endl;
|
||||
t->inactive++;
|
||||
t->label = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
for (CvTracks::iterator jt=tracks.begin(); jt!=tracks.end();)
|
||||
if ((jt->second->inactive>=thInactive)||((jt->second->inactive)&&(thActive)&&(jt->second->active<thActive)))
|
||||
{
|
||||
delete jt->second;
|
||||
tracks.erase(jt++);
|
||||
}
|
||||
else
|
||||
{
|
||||
jt->second->lifetime++;
|
||||
if (!jt->second->inactive)
|
||||
jt->second->active++;
|
||||
++jt;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
delete[] close;
|
||||
throw; // TODO: OpenCV style.
|
||||
}
|
||||
|
||||
delete[] close;
|
||||
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
CvFont *defaultFont = NULL;
|
||||
|
||||
void cvRenderTracks(CvTracks const tracks, IplImage *imgSource, IplImage *imgDest, unsigned short mode, CvFont *font)
|
||||
{
|
||||
CV_FUNCNAME("cvRenderTracks");
|
||||
__CV_BEGIN__;
|
||||
|
||||
CV_ASSERT(imgDest&&(imgDest->depth==IPL_DEPTH_8U)&&(imgDest->nChannels==3));
|
||||
|
||||
if ((mode&CV_TRACK_RENDER_ID)&&(!font))
|
||||
{
|
||||
if (!defaultFont)
|
||||
{
|
||||
font = defaultFont = new CvFont;
|
||||
cvInitFont(font, CV_FONT_HERSHEY_DUPLEX, 0.5, 0.5, 0, 1);
|
||||
// Other fonts:
|
||||
// CV_FONT_HERSHEY_SIMPLEX, CV_FONT_HERSHEY_PLAIN,
|
||||
// CV_FONT_HERSHEY_DUPLEX, CV_FONT_HERSHEY_COMPLEX,
|
||||
// CV_FONT_HERSHEY_TRIPLEX, CV_FONT_HERSHEY_COMPLEX_SMALL,
|
||||
// CV_FONT_HERSHEY_SCRIPT_SIMPLEX, CV_FONT_HERSHEY_SCRIPT_COMPLEX
|
||||
}
|
||||
else
|
||||
font = defaultFont;
|
||||
}
|
||||
|
||||
if (mode)
|
||||
{
|
||||
for (CvTracks::const_iterator it=tracks.begin(); it!=tracks.end(); ++it)
|
||||
{
|
||||
if (mode&CV_TRACK_RENDER_ID)
|
||||
if (!it->second->inactive)
|
||||
{
|
||||
stringstream buffer;
|
||||
buffer << it->first;
|
||||
cvPutText(imgDest, buffer.str().c_str(), cvPoint((int)it->second->centroid.x, (int)it->second->centroid.y), font, CV_RGB(0.,255.,0.));
|
||||
}
|
||||
|
||||
if (mode&CV_TRACK_RENDER_BOUNDING_BOX)
|
||||
if (it->second->inactive)
|
||||
cvRectangle(imgDest, cvPoint(it->second->minx, it->second->miny), cvPoint(it->second->maxx-1, it->second->maxy-1), CV_RGB(0., 0., 50.));
|
||||
else
|
||||
cvRectangle(imgDest, cvPoint(it->second->minx, it->second->miny), cvPoint(it->second->maxx-1, it->second->maxy-1), CV_RGB(0., 0., 255.));
|
||||
|
||||
if (mode&CV_TRACK_RENDER_TO_LOG)
|
||||
{
|
||||
clog << "Track " << it->second->id << endl;
|
||||
if (it->second->inactive)
|
||||
clog << " - Inactive for " << it->second->inactive << " frames" << endl;
|
||||
else
|
||||
clog << " - Associated with blob " << it->second->label << endl;
|
||||
clog << " - Lifetime " << it->second->lifetime << endl;
|
||||
clog << " - Active " << it->second->active << endl;
|
||||
clog << " - Bounding box: (" << it->second->minx << ", " << it->second->miny << ") - (" << it->second->maxx << ", " << it->second->maxy << ")" << endl;
|
||||
clog << " - Centroid: (" << it->second->centroid.x << ", " << it->second->centroid.y << ")" << endl;
|
||||
clog << endl;
|
||||
}
|
||||
|
||||
if (mode&CV_TRACK_RENDER_TO_STD)
|
||||
{
|
||||
cout << "Track " << it->second->id << endl;
|
||||
if (it->second->inactive)
|
||||
cout << " - Inactive for " << it->second->inactive << " frames" << endl;
|
||||
else
|
||||
cout << " - Associated with blobs " << it->second->label << endl;
|
||||
cout << " - Lifetime " << it->second->lifetime << endl;
|
||||
cout << " - Active " << it->second->active << endl;
|
||||
cout << " - Bounding box: (" << it->second->minx << ", " << it->second->miny << ") - (" << it->second->maxx << ", " << it->second->maxy << ")" << endl;
|
||||
cout << " - Centroid: (" << it->second->centroid.x << ", " << it->second->centroid.y << ")" << endl;
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__CV_END__;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
#
|
||||
# Generated Makefile - do not edit!
|
||||
#
|
||||
# Edit the Makefile in the project folder instead (../Makefile). Each target
|
||||
# has a -pre and a -post target defined where you can add customized code.
|
||||
#
|
||||
# This makefile implements configuration specific macros and targets.
|
||||
|
||||
|
||||
# Environment
|
||||
MKDIR=mkdir
|
||||
CP=cp
|
||||
GREP=grep
|
||||
NM=nm
|
||||
CCADMIN=CCadmin
|
||||
RANLIB=ranlib
|
||||
CC=gcc
|
||||
CCC=g++
|
||||
CXX=g++
|
||||
FC=gfortran
|
||||
AS=as
|
||||
|
||||
# Macros
|
||||
CND_PLATFORM=GNU-Linux-x86
|
||||
CND_DLIB_EXT=so
|
||||
CND_CONF=Debug
|
||||
CND_DISTDIR=dist
|
||||
CND_BUILDDIR=build
|
||||
|
||||
# Include project Makefile
|
||||
include Makefile
|
||||
|
||||
# Object Directory
|
||||
OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}
|
||||
|
||||
# Object Files
|
||||
OBJECTFILES= \
|
||||
${OBJECTDIR}/src/HandPointer/HandPointer.o \
|
||||
${OBJECTDIR}/src/HandPointer/Mouse.o
|
||||
|
||||
|
||||
# C Compiler Flags
|
||||
CFLAGS=
|
||||
|
||||
# CC Compiler Flags
|
||||
CCFLAGS=`pkg-config opencv --cflags --libs` -lX11 -I/usr/local/include -L/usr/local/lib -lcvblob
|
||||
CXXFLAGS=`pkg-config opencv --cflags --libs` -lX11 -I/usr/local/include -L/usr/local/lib -lcvblob
|
||||
|
||||
# Fortran Compiler Flags
|
||||
FFLAGS=
|
||||
|
||||
# Assembler Flags
|
||||
ASFLAGS=
|
||||
|
||||
# Link Libraries and Options
|
||||
LDLIBSOPTIONS=
|
||||
|
||||
# Build Targets
|
||||
.build-conf: ${BUILD_SUBPROJECTS}
|
||||
"${MAKE}" -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/mariusz
|
||||
|
||||
${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/mariusz: ${OBJECTFILES}
|
||||
${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}
|
||||
${LINK.cc} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/mariusz ${OBJECTFILES} ${LDLIBSOPTIONS}
|
||||
|
||||
${OBJECTDIR}/src/HandPointer/HandPointer.o: nbproject/Makefile-${CND_CONF}.mk src/HandPointer/HandPointer.cpp
|
||||
${MKDIR} -p ${OBJECTDIR}/src/HandPointer
|
||||
${RM} $@.d
|
||||
$(COMPILE.cc) -g -Iinclude/cvBlob `pkg-config opencv --cflags --libs` -lX11 -I/usr/local/include -L/usr/local/lib -lcvblob -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HandPointer/HandPointer.o src/HandPointer/HandPointer.cpp
|
||||
|
||||
${OBJECTDIR}/src/HandPointer/Mouse.o: nbproject/Makefile-${CND_CONF}.mk src/HandPointer/Mouse.cpp
|
||||
${MKDIR} -p ${OBJECTDIR}/src/HandPointer
|
||||
${RM} $@.d
|
||||
$(COMPILE.cc) -g -Iinclude/cvBlob `pkg-config opencv --cflags --libs` -lX11 -I/usr/local/include -L/usr/local/lib -lcvblob -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HandPointer/Mouse.o src/HandPointer/Mouse.cpp
|
||||
|
||||
# Subprojects
|
||||
.build-subprojects:
|
||||
|
||||
# Clean Targets
|
||||
.clean-conf: ${CLEAN_SUBPROJECTS}
|
||||
${RM} -r ${CND_BUILDDIR}/${CND_CONF}
|
||||
${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/mariusz
|
||||
|
||||
# Subprojects
|
||||
.clean-subprojects:
|
||||
|
||||
# Enable dependency checking
|
||||
.dep.inc: .depcheck-impl
|
||||
|
||||
include .dep.inc
|
||||
@@ -0,0 +1,90 @@
|
||||
#
|
||||
# Generated Makefile - do not edit!
|
||||
#
|
||||
# Edit the Makefile in the project folder instead (../Makefile). Each target
|
||||
# has a -pre and a -post target defined where you can add customized code.
|
||||
#
|
||||
# This makefile implements configuration specific macros and targets.
|
||||
|
||||
|
||||
# Environment
|
||||
MKDIR=mkdir
|
||||
CP=cp
|
||||
GREP=grep
|
||||
NM=nm
|
||||
CCADMIN=CCadmin
|
||||
RANLIB=ranlib
|
||||
CC=gcc
|
||||
CCC=g++
|
||||
CXX=g++
|
||||
FC=gfortran
|
||||
AS=as
|
||||
|
||||
# Macros
|
||||
CND_PLATFORM=GNU-Linux-x86
|
||||
CND_DLIB_EXT=so
|
||||
CND_CONF=Release
|
||||
CND_DISTDIR=dist
|
||||
CND_BUILDDIR=build
|
||||
|
||||
# Include project Makefile
|
||||
include Makefile
|
||||
|
||||
# Object Directory
|
||||
OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}
|
||||
|
||||
# Object Files
|
||||
OBJECTFILES= \
|
||||
${OBJECTDIR}/src/HandPointer/HandPointer.o \
|
||||
${OBJECTDIR}/src/HandPointer/Mouse.o
|
||||
|
||||
|
||||
# C Compiler Flags
|
||||
CFLAGS=
|
||||
|
||||
# CC Compiler Flags
|
||||
CCFLAGS=
|
||||
CXXFLAGS=
|
||||
|
||||
# Fortran Compiler Flags
|
||||
FFLAGS=
|
||||
|
||||
# Assembler Flags
|
||||
ASFLAGS=
|
||||
|
||||
# Link Libraries and Options
|
||||
LDLIBSOPTIONS=
|
||||
|
||||
# Build Targets
|
||||
.build-conf: ${BUILD_SUBPROJECTS}
|
||||
"${MAKE}" -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/mariusz
|
||||
|
||||
${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/mariusz: ${OBJECTFILES}
|
||||
${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}
|
||||
${LINK.cc} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/mariusz ${OBJECTFILES} ${LDLIBSOPTIONS}
|
||||
|
||||
${OBJECTDIR}/src/HandPointer/HandPointer.o: src/HandPointer/HandPointer.cpp
|
||||
${MKDIR} -p ${OBJECTDIR}/src/HandPointer
|
||||
${RM} $@.d
|
||||
$(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HandPointer/HandPointer.o src/HandPointer/HandPointer.cpp
|
||||
|
||||
${OBJECTDIR}/src/HandPointer/Mouse.o: src/HandPointer/Mouse.cpp
|
||||
${MKDIR} -p ${OBJECTDIR}/src/HandPointer
|
||||
${RM} $@.d
|
||||
$(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HandPointer/Mouse.o src/HandPointer/Mouse.cpp
|
||||
|
||||
# Subprojects
|
||||
.build-subprojects:
|
||||
|
||||
# Clean Targets
|
||||
.clean-conf: ${CLEAN_SUBPROJECTS}
|
||||
${RM} -r ${CND_BUILDDIR}/${CND_CONF}
|
||||
${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/mariusz
|
||||
|
||||
# Subprojects
|
||||
.clean-subprojects:
|
||||
|
||||
# Enable dependency checking
|
||||
.dep.inc: .depcheck-impl
|
||||
|
||||
include .dep.inc
|
||||
@@ -0,0 +1,133 @@
|
||||
#
|
||||
# Generated Makefile - do not edit!
|
||||
#
|
||||
# Edit the Makefile in the project folder instead (../Makefile). Each target
|
||||
# has a pre- and a post- target defined where you can add customization code.
|
||||
#
|
||||
# This makefile implements macros and targets common to all configurations.
|
||||
#
|
||||
# NOCDDL
|
||||
|
||||
|
||||
# Building and Cleaning subprojects are done by default, but can be controlled with the SUB
|
||||
# macro. If SUB=no, subprojects will not be built or cleaned. The following macro
|
||||
# statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf
|
||||
# and .clean-reqprojects-conf unless SUB has the value 'no'
|
||||
SUB_no=NO
|
||||
SUBPROJECTS=${SUB_${SUB}}
|
||||
BUILD_SUBPROJECTS_=.build-subprojects
|
||||
BUILD_SUBPROJECTS_NO=
|
||||
BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}}
|
||||
CLEAN_SUBPROJECTS_=.clean-subprojects
|
||||
CLEAN_SUBPROJECTS_NO=
|
||||
CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}}
|
||||
|
||||
|
||||
# Project Name
|
||||
PROJECTNAME=mariusz
|
||||
|
||||
# Active Configuration
|
||||
DEFAULTCONF=Debug
|
||||
CONF=${DEFAULTCONF}
|
||||
|
||||
# All Configurations
|
||||
ALLCONFS=Debug Release
|
||||
|
||||
|
||||
# build
|
||||
.build-impl: .build-pre .validate-impl .depcheck-impl
|
||||
@#echo "=> Running $@... Configuration=$(CONF)"
|
||||
"${MAKE}" -f nbproject/Makefile-${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .build-conf
|
||||
|
||||
|
||||
# clean
|
||||
.clean-impl: .clean-pre .validate-impl .depcheck-impl
|
||||
@#echo "=> Running $@... Configuration=$(CONF)"
|
||||
"${MAKE}" -f nbproject/Makefile-${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .clean-conf
|
||||
|
||||
|
||||
# clobber
|
||||
.clobber-impl: .clobber-pre .depcheck-impl
|
||||
@#echo "=> Running $@..."
|
||||
for CONF in ${ALLCONFS}; \
|
||||
do \
|
||||
"${MAKE}" -f nbproject/Makefile-$${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .clean-conf; \
|
||||
done
|
||||
|
||||
# all
|
||||
.all-impl: .all-pre .depcheck-impl
|
||||
@#echo "=> Running $@..."
|
||||
for CONF in ${ALLCONFS}; \
|
||||
do \
|
||||
"${MAKE}" -f nbproject/Makefile-$${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .build-conf; \
|
||||
done
|
||||
|
||||
# build tests
|
||||
.build-tests-impl: .build-impl .build-tests-pre
|
||||
@#echo "=> Running $@... Configuration=$(CONF)"
|
||||
"${MAKE}" -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-tests-conf
|
||||
|
||||
# run tests
|
||||
.test-impl: .build-tests-impl .test-pre
|
||||
@#echo "=> Running $@... Configuration=$(CONF)"
|
||||
"${MAKE}" -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .test-conf
|
||||
|
||||
# dependency checking support
|
||||
.depcheck-impl:
|
||||
@echo "# This code depends on make tool being used" >.dep.inc
|
||||
@if [ -n "${MAKE_VERSION}" ]; then \
|
||||
echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \
|
||||
echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \
|
||||
echo "include \$${DEPFILES}" >>.dep.inc; \
|
||||
echo "endif" >>.dep.inc; \
|
||||
else \
|
||||
echo ".KEEP_STATE:" >>.dep.inc; \
|
||||
echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \
|
||||
fi
|
||||
|
||||
# configuration validation
|
||||
.validate-impl:
|
||||
@if [ ! -f nbproject/Makefile-${CONF}.mk ]; \
|
||||
then \
|
||||
echo ""; \
|
||||
echo "Error: can not find the makefile for configuration '${CONF}' in project ${PROJECTNAME}"; \
|
||||
echo "See 'make help' for details."; \
|
||||
echo "Current directory: " `pwd`; \
|
||||
echo ""; \
|
||||
fi
|
||||
@if [ ! -f nbproject/Makefile-${CONF}.mk ]; \
|
||||
then \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
|
||||
# help
|
||||
.help-impl: .help-pre
|
||||
@echo "This makefile supports the following configurations:"
|
||||
@echo " ${ALLCONFS}"
|
||||
@echo ""
|
||||
@echo "and the following targets:"
|
||||
@echo " build (default target)"
|
||||
@echo " clean"
|
||||
@echo " clobber"
|
||||
@echo " all"
|
||||
@echo " help"
|
||||
@echo ""
|
||||
@echo "Makefile Usage:"
|
||||
@echo " make [CONF=<CONFIGURATION>] [SUB=no] build"
|
||||
@echo " make [CONF=<CONFIGURATION>] [SUB=no] clean"
|
||||
@echo " make [SUB=no] clobber"
|
||||
@echo " make [SUB=no] all"
|
||||
@echo " make help"
|
||||
@echo ""
|
||||
@echo "Target 'build' will build a specific configuration and, unless 'SUB=no',"
|
||||
@echo " also build subprojects."
|
||||
@echo "Target 'clean' will clean a specific configuration and, unless 'SUB=no',"
|
||||
@echo " also clean subprojects."
|
||||
@echo "Target 'clobber' will remove all built files from all configurations and,"
|
||||
@echo " unless 'SUB=no', also from subprojects."
|
||||
@echo "Target 'all' will will build all configurations and, unless 'SUB=no',"
|
||||
@echo " also build subprojects."
|
||||
@echo "Target 'help' prints this message."
|
||||
@echo ""
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# Generated - do not edit!
|
||||
#
|
||||
# NOCDDL
|
||||
#
|
||||
CND_BASEDIR=`pwd`
|
||||
CND_BUILDDIR=build
|
||||
CND_DISTDIR=dist
|
||||
# Debug configuration
|
||||
CND_PLATFORM_Debug=GNU-Linux-x86
|
||||
CND_ARTIFACT_DIR_Debug=dist/Debug/GNU-Linux-x86
|
||||
CND_ARTIFACT_NAME_Debug=mariusz
|
||||
CND_ARTIFACT_PATH_Debug=dist/Debug/GNU-Linux-x86/mariusz
|
||||
CND_PACKAGE_DIR_Debug=dist/Debug/GNU-Linux-x86/package
|
||||
CND_PACKAGE_NAME_Debug=mariusz.tar
|
||||
CND_PACKAGE_PATH_Debug=dist/Debug/GNU-Linux-x86/package/mariusz.tar
|
||||
# Release configuration
|
||||
CND_PLATFORM_Release=GNU-Linux-x86
|
||||
CND_ARTIFACT_DIR_Release=dist/Release/GNU-Linux-x86
|
||||
CND_ARTIFACT_NAME_Release=mariusz
|
||||
CND_ARTIFACT_PATH_Release=dist/Release/GNU-Linux-x86/mariusz
|
||||
CND_PACKAGE_DIR_Release=dist/Release/GNU-Linux-x86/package
|
||||
CND_PACKAGE_NAME_Release=mariusz.tar
|
||||
CND_PACKAGE_PATH_Release=dist/Release/GNU-Linux-x86/package/mariusz.tar
|
||||
#
|
||||
# include compiler specific variables
|
||||
#
|
||||
# dmake command
|
||||
ROOT:sh = test -f nbproject/private/Makefile-variables.mk || \
|
||||
(mkdir -p nbproject/private && touch nbproject/private/Makefile-variables.mk)
|
||||
#
|
||||
# gmake command
|
||||
.PHONY: $(shell test -f nbproject/private/Makefile-variables.mk || (mkdir -p nbproject/private && touch nbproject/private/Makefile-variables.mk))
|
||||
#
|
||||
include nbproject/private/Makefile-variables.mk
|
||||
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
#
|
||||
# Generated - do not edit!
|
||||
#
|
||||
|
||||
# Macros
|
||||
TOP=`pwd`
|
||||
CND_PLATFORM=GNU-Linux-x86
|
||||
CND_CONF=Debug
|
||||
CND_DISTDIR=dist
|
||||
CND_BUILDDIR=build
|
||||
NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging
|
||||
TMPDIRNAME=tmp-packaging
|
||||
OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/mariusz
|
||||
OUTPUT_BASENAME=mariusz
|
||||
PACKAGE_TOP_DIR=mariusz/
|
||||
|
||||
# Functions
|
||||
function checkReturnCode
|
||||
{
|
||||
rc=$?
|
||||
if [ $rc != 0 ]
|
||||
then
|
||||
exit $rc
|
||||
fi
|
||||
}
|
||||
function makeDirectory
|
||||
# $1 directory path
|
||||
# $2 permission (optional)
|
||||
{
|
||||
mkdir -p "$1"
|
||||
checkReturnCode
|
||||
if [ "$2" != "" ]
|
||||
then
|
||||
chmod $2 "$1"
|
||||
checkReturnCode
|
||||
fi
|
||||
}
|
||||
function copyFileToTmpDir
|
||||
# $1 from-file path
|
||||
# $2 to-file path
|
||||
# $3 permission
|
||||
{
|
||||
cp "$1" "$2"
|
||||
checkReturnCode
|
||||
if [ "$3" != "" ]
|
||||
then
|
||||
chmod $3 "$2"
|
||||
checkReturnCode
|
||||
fi
|
||||
}
|
||||
|
||||
# Setup
|
||||
cd "${TOP}"
|
||||
mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package
|
||||
rm -rf ${NBTMPDIR}
|
||||
mkdir -p ${NBTMPDIR}
|
||||
|
||||
# Copy files and create directories and links
|
||||
cd "${TOP}"
|
||||
makeDirectory "${NBTMPDIR}/mariusz/bin"
|
||||
copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755
|
||||
|
||||
|
||||
# Generate tar file
|
||||
cd "${TOP}"
|
||||
rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/mariusz.tar
|
||||
cd ${NBTMPDIR}
|
||||
tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/mariusz.tar *
|
||||
checkReturnCode
|
||||
|
||||
# Cleanup
|
||||
cd "${TOP}"
|
||||
rm -rf ${NBTMPDIR}
|
||||
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
#
|
||||
# Generated - do not edit!
|
||||
#
|
||||
|
||||
# Macros
|
||||
TOP=`pwd`
|
||||
CND_PLATFORM=GNU-Linux-x86
|
||||
CND_CONF=Release
|
||||
CND_DISTDIR=dist
|
||||
CND_BUILDDIR=build
|
||||
NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging
|
||||
TMPDIRNAME=tmp-packaging
|
||||
OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/mariusz
|
||||
OUTPUT_BASENAME=mariusz
|
||||
PACKAGE_TOP_DIR=mariusz/
|
||||
|
||||
# Functions
|
||||
function checkReturnCode
|
||||
{
|
||||
rc=$?
|
||||
if [ $rc != 0 ]
|
||||
then
|
||||
exit $rc
|
||||
fi
|
||||
}
|
||||
function makeDirectory
|
||||
# $1 directory path
|
||||
# $2 permission (optional)
|
||||
{
|
||||
mkdir -p "$1"
|
||||
checkReturnCode
|
||||
if [ "$2" != "" ]
|
||||
then
|
||||
chmod $2 "$1"
|
||||
checkReturnCode
|
||||
fi
|
||||
}
|
||||
function copyFileToTmpDir
|
||||
# $1 from-file path
|
||||
# $2 to-file path
|
||||
# $3 permission
|
||||
{
|
||||
cp "$1" "$2"
|
||||
checkReturnCode
|
||||
if [ "$3" != "" ]
|
||||
then
|
||||
chmod $3 "$2"
|
||||
checkReturnCode
|
||||
fi
|
||||
}
|
||||
|
||||
# Setup
|
||||
cd "${TOP}"
|
||||
mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package
|
||||
rm -rf ${NBTMPDIR}
|
||||
mkdir -p ${NBTMPDIR}
|
||||
|
||||
# Copy files and create directories and links
|
||||
cd "${TOP}"
|
||||
makeDirectory "${NBTMPDIR}/mariusz/bin"
|
||||
copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755
|
||||
|
||||
|
||||
# Generate tar file
|
||||
cd "${TOP}"
|
||||
rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/mariusz.tar
|
||||
cd ${NBTMPDIR}
|
||||
tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/mariusz.tar *
|
||||
checkReturnCode
|
||||
|
||||
# Cleanup
|
||||
cd "${TOP}"
|
||||
rm -rf ${NBTMPDIR}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configurationDescriptor version="88">
|
||||
<logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT">
|
||||
<logicalFolder name="HeaderFiles"
|
||||
displayName="Header Files"
|
||||
projectFiles="true">
|
||||
<itemPath>src/HandPointer/Mouse.hpp</itemPath>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="ResourceFiles"
|
||||
displayName="Resource Files"
|
||||
projectFiles="true">
|
||||
</logicalFolder>
|
||||
<logicalFolder name="SourceFiles"
|
||||
displayName="Source Files"
|
||||
projectFiles="true">
|
||||
<itemPath>src/HandPointer/HandPointer.cpp</itemPath>
|
||||
<itemPath>src/HandPointer/Mouse.cpp</itemPath>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="TestFiles"
|
||||
displayName="Test Files"
|
||||
projectFiles="false"
|
||||
kind="TEST_LOGICAL_FOLDER">
|
||||
</logicalFolder>
|
||||
<logicalFolder name="ExternalFiles"
|
||||
displayName="Important Files"
|
||||
projectFiles="false"
|
||||
kind="IMPORTANT_FILES_FOLDER">
|
||||
<itemPath>Makefile</itemPath>
|
||||
</logicalFolder>
|
||||
</logicalFolder>
|
||||
<sourceRootList>
|
||||
<Elem>src/HandPointer</Elem>
|
||||
</sourceRootList>
|
||||
<projectmakefile>Makefile</projectmakefile>
|
||||
<confs>
|
||||
<conf name="Debug" type="1">
|
||||
<toolsSet>
|
||||
<remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
|
||||
<compilerSet>default</compilerSet>
|
||||
<dependencyChecking>true</dependencyChecking>
|
||||
<rebuildPropChanged>true</rebuildPropChanged>
|
||||
</toolsSet>
|
||||
<compileType>
|
||||
<ccTool>
|
||||
<commandlineTool>g++</commandlineTool>
|
||||
<incDir>
|
||||
<pElem>include/cvBlob</pElem>
|
||||
</incDir>
|
||||
<commandLine>`pkg-config opencv --cflags --libs` -lX11 -I/usr/local/include -L/usr/local/lib -lcvblob </commandLine>
|
||||
</ccTool>
|
||||
</compileType>
|
||||
<item path="src/HandPointer/HandPointer.cpp" ex="false" tool="1" flavor2="0">
|
||||
</item>
|
||||
<item path="src/HandPointer/Mouse.cpp" ex="false" tool="1" flavor2="0">
|
||||
</item>
|
||||
<item path="src/HandPointer/Mouse.hpp" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
</conf>
|
||||
<conf name="Release" type="1">
|
||||
<toolsSet>
|
||||
<remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
|
||||
<compilerSet>default</compilerSet>
|
||||
<dependencyChecking>true</dependencyChecking>
|
||||
<rebuildPropChanged>false</rebuildPropChanged>
|
||||
</toolsSet>
|
||||
<compileType>
|
||||
<cTool>
|
||||
<developmentMode>5</developmentMode>
|
||||
</cTool>
|
||||
<ccTool>
|
||||
<developmentMode>5</developmentMode>
|
||||
</ccTool>
|
||||
<fortranCompilerTool>
|
||||
<developmentMode>5</developmentMode>
|
||||
</fortranCompilerTool>
|
||||
<asmTool>
|
||||
<developmentMode>5</developmentMode>
|
||||
</asmTool>
|
||||
</compileType>
|
||||
<item path="src/HandPointer/HandPointer.cpp" ex="false" tool="1" flavor2="0">
|
||||
</item>
|
||||
<item path="src/HandPointer/Mouse.cpp" ex="false" tool="1" flavor2="0">
|
||||
</item>
|
||||
<item path="src/HandPointer/Mouse.hpp" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
</conf>
|
||||
</confs>
|
||||
</configurationDescriptor>
|
||||
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# Generated - do not edit!
|
||||
#
|
||||
# NOCDDL
|
||||
#
|
||||
# Debug configuration
|
||||
# Release configuration
|
||||
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configurationDescriptor version="88">
|
||||
<projectmakefile>Makefile</projectmakefile>
|
||||
<confs>
|
||||
<conf name="Debug" type="1">
|
||||
<toolsSet>
|
||||
<developmentServer>localhost</developmentServer>
|
||||
<platform>2</platform>
|
||||
</toolsSet>
|
||||
<dbx_gdbdebugger version="1">
|
||||
<gdb_pathmaps>
|
||||
</gdb_pathmaps>
|
||||
<gdb_interceptlist>
|
||||
<gdbinterceptoptions gdb_all="false" gdb_unhandled="true" gdb_unexpected="true"/>
|
||||
</gdb_interceptlist>
|
||||
<gdb_options>
|
||||
<DebugOptions>
|
||||
</DebugOptions>
|
||||
</gdb_options>
|
||||
<gdb_buildfirst gdb_buildfirst_overriden="false" gdb_buildfirst_old="false"/>
|
||||
</dbx_gdbdebugger>
|
||||
<nativedebugger version="1">
|
||||
<engine>gdb</engine>
|
||||
</nativedebugger>
|
||||
<runprofile version="9">
|
||||
<runcommandpicklist>
|
||||
<runcommandpicklistitem>"${OUTPUT_PATH}"</runcommandpicklistitem>
|
||||
</runcommandpicklist>
|
||||
<runcommand>"${OUTPUT_PATH}"</runcommand>
|
||||
<rundir></rundir>
|
||||
<buildfirst>true</buildfirst>
|
||||
<terminal-type>0</terminal-type>
|
||||
<remove-instrumentation>0</remove-instrumentation>
|
||||
<environment>
|
||||
<variable name="LD_LIBRARY_PATH" value="lib/"/>
|
||||
</environment>
|
||||
</runprofile>
|
||||
</conf>
|
||||
<conf name="Release" type="1">
|
||||
<toolsSet>
|
||||
<developmentServer>localhost</developmentServer>
|
||||
<platform>2</platform>
|
||||
</toolsSet>
|
||||
<dbx_gdbdebugger version="1">
|
||||
<gdb_pathmaps>
|
||||
</gdb_pathmaps>
|
||||
<gdb_interceptlist>
|
||||
<gdbinterceptoptions gdb_all="false" gdb_unhandled="true" gdb_unexpected="true"/>
|
||||
</gdb_interceptlist>
|
||||
<gdb_options>
|
||||
<DebugOptions>
|
||||
</DebugOptions>
|
||||
</gdb_options>
|
||||
<gdb_buildfirst gdb_buildfirst_overriden="false" gdb_buildfirst_old="false"/>
|
||||
</dbx_gdbdebugger>
|
||||
<nativedebugger version="1">
|
||||
<engine>gdb</engine>
|
||||
</nativedebugger>
|
||||
<runprofile version="9">
|
||||
<runcommandpicklist>
|
||||
<runcommandpicklistitem>"${OUTPUT_PATH}"</runcommandpicklistitem>
|
||||
</runcommandpicklist>
|
||||
<runcommand>"${OUTPUT_PATH}"</runcommand>
|
||||
<rundir></rundir>
|
||||
<buildfirst>true</buildfirst>
|
||||
<terminal-type>0</terminal-type>
|
||||
<remove-instrumentation>0</remove-instrumentation>
|
||||
<environment>
|
||||
</environment>
|
||||
</runprofile>
|
||||
</conf>
|
||||
</confs>
|
||||
</configurationDescriptor>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
|
||||
<data xmlns="http://www.netbeans.org/ns/make-project-private/1">
|
||||
<activeConfTypeElem>1</activeConfTypeElem>
|
||||
<activeConfIndexElem>0</activeConfIndexElem>
|
||||
</data>
|
||||
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
|
||||
</project-private>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.cnd.makeproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/make-project/1">
|
||||
<name>HandPointer</name>
|
||||
<c-extensions/>
|
||||
<cpp-extensions>cpp</cpp-extensions>
|
||||
<header-extensions>hpp</header-extensions>
|
||||
<sourceEncoding>UTF-8</sourceEncoding>
|
||||
<make-dep-projects/>
|
||||
<sourceRootList>
|
||||
<sourceRootElem>src/HandPointer</sourceRootElem>
|
||||
</sourceRootList>
|
||||
<confList>
|
||||
<confElem>
|
||||
<name>Debug</name>
|
||||
<type>1</type>
|
||||
</confElem>
|
||||
<confElem>
|
||||
<name>Release</name>
|
||||
<type>1</type>
|
||||
</confElem>
|
||||
</confList>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* File: main.cpp
|
||||
* Author: mar
|
||||
*
|
||||
* Created on 7 kwiecień 2013, 19:36
|
||||
*/
|
||||
|
||||
|
||||
#include <opencv2/objdetect/objdetect.hpp>
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <cvblob.h>
|
||||
#include "opencv2/opencv.hpp"
|
||||
#include <opencv/cv.h>
|
||||
#include "Mouse.hpp"
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
using namespace cvb;
|
||||
|
||||
int r = 51, g = 99, b = 57;
|
||||
int rT = 90, gT = 255, bT = 129;
|
||||
int maxArea=1000, minArea=170;
|
||||
|
||||
void setR(int v) {r = v;}
|
||||
void setG(int v) {g = v;}
|
||||
void setB(int v) {b = v;}
|
||||
void setRT(int v) {rT = v;}
|
||||
void setGT(int v) {gT = v;}
|
||||
void setBT(int v) {bT = v;}
|
||||
|
||||
|
||||
void setMax(int v){maxArea = v;}
|
||||
void setMin(int v){minArea = v;}
|
||||
|
||||
int main(int, char**) {
|
||||
VideoCapture cap(0); // open the default camera
|
||||
if (!cap.isOpened()) // check if we succeeded
|
||||
return -1;
|
||||
|
||||
Mouse mouse;
|
||||
bool mouseon = true;
|
||||
int x, y;
|
||||
|
||||
namedWindow("output", 1);
|
||||
namedWindow("bin", 1);
|
||||
|
||||
CvBlobs blobs;
|
||||
CvTracks tracks;
|
||||
|
||||
IplImage *red = 0, *tmp = 0,* framee=0,*labelImg=0;
|
||||
|
||||
Mat edges, frame;
|
||||
|
||||
cap >> frame;
|
||||
|
||||
red = cvCreateImage(cvSize(frame.cols, frame.rows), IPL_DEPTH_8U, 1);
|
||||
tmp = cvCreateImage(cvSize(frame.cols, frame.rows), IPL_DEPTH_8U, 3);
|
||||
labelImg = cvCreateImage(cvGetSize(red), IPL_DEPTH_LABEL, 1);
|
||||
framee= cvCreateImage(cvGetSize(red), 8, 3);
|
||||
|
||||
cvCreateTrackbar("R","bin",&r,255,setR);
|
||||
cvCreateTrackbar("G","bin",&g,255,setG);
|
||||
cvCreateTrackbar("B","bin",&b,255,setB);
|
||||
|
||||
cvCreateTrackbar("RT","bin",&rT,255,setRT);
|
||||
cvCreateTrackbar("BT","bin",&bT,255,setBT);
|
||||
cvCreateTrackbar("GT","bin",&gT,255,setGT);
|
||||
|
||||
cvCreateTrackbar("min","bin",&minArea,1000,setMin);
|
||||
cvCreateTrackbar("max","bin",&maxArea,100000,setMax);
|
||||
|
||||
|
||||
|
||||
for (;;) {
|
||||
cap >> frame; // gt a new frame from camera
|
||||
flip(frame, frame, 1);
|
||||
cvtColor(frame, edges, CV_BGR2HSV);
|
||||
|
||||
tmp->imageData = (char*) edges.data;
|
||||
framee->imageData = (char*) frame.data;
|
||||
|
||||
cvInRangeS(tmp, Scalar(r, g, b), Scalar(rT, gT, bT), red);
|
||||
|
||||
cvDilate(red, red, NULL, 3);
|
||||
cvErode(red, red, NULL, 4);
|
||||
cvDilate(red, red, NULL, 2);
|
||||
|
||||
cvLabel(red, labelImg, blobs);
|
||||
cvFilterByArea(blobs, minArea, maxArea);
|
||||
cvRenderBlobs(labelImg, blobs, framee, framee, CV_BLOB_RENDER_BOUNDING_BOX);
|
||||
cvUpdateTracks(blobs, tracks, 200, 5);
|
||||
cvRenderTracks(tracks, framee, framee, CV_TRACK_RENDER_ID | CV_TRACK_RENDER_BOUNDING_BOX);
|
||||
|
||||
for (CvBlobs::const_iterator it = blobs.begin(); it != blobs.end(); ++it) {
|
||||
x = (int) it->second->centroid.x;
|
||||
y = (int) it->second->centroid.y;
|
||||
if (mouseon) {
|
||||
mouse.setMouse(x/(double)frame.cols*1600,y/(double)frame.rows*900);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
imshow("output", Mat(framee));
|
||||
imshow("bin", Mat(red));
|
||||
|
||||
char key = (char) waitKey(1);
|
||||
switch (key) {
|
||||
|
||||
case 'a':
|
||||
mouseon = mouseon ? false : true;
|
||||
break;
|
||||
}
|
||||
if (key == 'b') break; //exit program
|
||||
|
||||
}
|
||||
|
||||
destroyAllWindows();
|
||||
// the camera will be deinitialized automatically in VideoCapture destructor
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* File: mouse.cpp
|
||||
* Author: mar
|
||||
*
|
||||
* Created on 13 kwiecień 2013, 15:38
|
||||
*/
|
||||
|
||||
#include "Mouse.hpp"
|
||||
|
||||
Mouse::Mouse() {
|
||||
dpy = XOpenDisplay(0);
|
||||
root_window = XRootWindow(dpy, 0);
|
||||
XSelectInput(dpy, root_window, KeyReleaseMask);
|
||||
|
||||
}
|
||||
void Mouse::setMouse(const int x,const int y){
|
||||
XWarpPointer(dpy, None, root_window, 0, 0, 0, 0, x, y);
|
||||
XFlush(dpy);
|
||||
}
|
||||
Mouse::Mouse(const Mouse& orig) {
|
||||
}
|
||||
|
||||
Mouse::~Mouse() {
|
||||
//free(&dpy);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* File: mouse.hpp
|
||||
* Author: mar
|
||||
*
|
||||
* Created on 13 kwiecień 2013, 15:38
|
||||
*/
|
||||
|
||||
#ifndef MOUSE_HPP
|
||||
#define MOUSE_HPP
|
||||
#include <X11/Xlib.h>
|
||||
class Mouse {
|
||||
public:
|
||||
Mouse();
|
||||
Mouse(const Mouse& orig);
|
||||
void setMouse(const int,const int);
|
||||
virtual ~Mouse();
|
||||
private:
|
||||
Display *dpy;
|
||||
Window root_window;
|
||||
|
||||
};
|
||||
|
||||
#endif /* MOUSE_HPP */
|
||||
|
||||
Reference in new issue
Block a user