mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 15:53:03 +04:00
removed ERFilter (to be moved to opencv_contrib/modules/text) and lineMOD (to be moved to opencv_contrib/modules/rgbd)
This commit is contained in:
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>de.rwth-aachen.ient.FaceTracker</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,86 +0,0 @@
|
||||
|
||||
#include <OpenCV/OpenCV.h>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
const char * WINDOW_NAME = "Face Tracker";
|
||||
const CFIndex CASCADE_NAME_LEN = 2048;
|
||||
char CASCADE_NAME[CASCADE_NAME_LEN] = "~/opencv/data/haarcascades/haarcascade_frontalface_alt2.xml";
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main (int argc, char * const argv[])
|
||||
{
|
||||
const int scale = 2;
|
||||
|
||||
// locate haar cascade from inside application bundle
|
||||
// (this is the mac way to package application resources)
|
||||
CFBundleRef mainBundle = CFBundleGetMainBundle ();
|
||||
assert (mainBundle);
|
||||
CFURLRef cascade_url = CFBundleCopyResourceURL (mainBundle, CFSTR("haarcascade_frontalface_alt2"), CFSTR("xml"), NULL);
|
||||
assert (cascade_url);
|
||||
Boolean got_it = CFURLGetFileSystemRepresentation (cascade_url, true,
|
||||
reinterpret_cast<UInt8 *>(CASCADE_NAME), CASCADE_NAME_LEN);
|
||||
if (! got_it)
|
||||
abort ();
|
||||
|
||||
// create all necessary instances
|
||||
cvNamedWindow (WINDOW_NAME, CV_WINDOW_AUTOSIZE);
|
||||
CvCapture * camera = cvCreateCameraCapture (CV_CAP_ANY);
|
||||
CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*) cvLoad (CASCADE_NAME, 0, 0, 0);
|
||||
CvMemStorage* storage = cvCreateMemStorage(0);
|
||||
assert (storage);
|
||||
|
||||
// you do own an iSight, don't you ?!?
|
||||
if (! camera)
|
||||
abort ();
|
||||
|
||||
// did we load the cascade?!?
|
||||
if (! cascade)
|
||||
abort ();
|
||||
|
||||
// get an initial frame and duplicate it for later work
|
||||
IplImage * current_frame = cvQueryFrame (camera);
|
||||
IplImage * draw_image = cvCreateImage(cvSize (current_frame->width, current_frame->height), IPL_DEPTH_8U, 3);
|
||||
IplImage * gray_image = cvCreateImage(cvSize (current_frame->width, current_frame->height), IPL_DEPTH_8U, 1);
|
||||
IplImage * small_image = cvCreateImage(cvSize (current_frame->width / scale, current_frame->height / scale), IPL_DEPTH_8U, 1);
|
||||
assert (current_frame && gray_image && draw_image);
|
||||
|
||||
// as long as there are images ...
|
||||
while (current_frame = cvQueryFrame (camera))
|
||||
{
|
||||
// convert to gray and downsize
|
||||
cvCvtColor (current_frame, gray_image, CV_BGR2GRAY);
|
||||
cvResize (gray_image, small_image, CV_INTER_LINEAR);
|
||||
|
||||
// detect faces
|
||||
CvSeq* faces = cvHaarDetectObjects (small_image, cascade, storage,
|
||||
1.1, 2, CV_HAAR_DO_CANNY_PRUNING,
|
||||
cvSize (30, 30));
|
||||
|
||||
// draw faces
|
||||
cvFlip (current_frame, draw_image, 1);
|
||||
for (int i = 0; i < (faces ? faces->total : 0); i++)
|
||||
{
|
||||
CvRect* r = (CvRect*) cvGetSeqElem (faces, i);
|
||||
CvPoint center;
|
||||
int radius;
|
||||
center.x = cvRound((small_image->width - r->width*0.5 - r->x) *scale);
|
||||
center.y = cvRound((r->y + r->height*0.5)*scale);
|
||||
radius = cvRound((r->width + r->height)*0.25*scale);
|
||||
cvCircle (draw_image, center, radius, CV_RGB(0,255,0), 3, 8, 0 );
|
||||
}
|
||||
|
||||
// just show the image
|
||||
cvShowImage (WINDOW_NAME, draw_image);
|
||||
|
||||
// wait a tenth of a second for keypress and window drawing
|
||||
int key = cvWaitKey (100);
|
||||
if (key == 'q' || key == 'Q')
|
||||
break;
|
||||
}
|
||||
|
||||
// be nice and return no error
|
||||
return 0;
|
||||
}
|
||||
@@ -1,262 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 42;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
4D7DBE8E0C04A90C00D8835D /* FaceTracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* FaceTracker.cpp */; };
|
||||
4D95C9BE0C0577B200983E4D /* OpenCV.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D06E1E00C039982004AF23F /* OpenCV.framework */; };
|
||||
4D95C9D80C0577BD00983E4D /* OpenCV.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4D06E1E00C039982004AF23F /* OpenCV.framework */; };
|
||||
4DBF87310C05731500880673 /* haarcascade_frontalface_alt2.xml in Resources */ = {isa = PBXBuildFile; fileRef = 4DBF87300C05731500880673 /* haarcascade_frontalface_alt2.xml */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
4D7DBE8F0C04A93300D8835D /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
4D95C9D80C0577BD00983E4D /* OpenCV.framework in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
08FB7796FE84155DC02AAC07 /* FaceTracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FaceTracker.cpp; sourceTree = "<group>"; };
|
||||
4D06E1E00C039982004AF23F /* OpenCV.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenCV.framework; path = ../../../OpenCV.framework; sourceTree = SOURCE_ROOT; };
|
||||
4D4CDBCC0C0630060001A8A2 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.txt; sourceTree = "<group>"; };
|
||||
4D7DBE570C04A8FF00D8835D /* FaceTracker.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FaceTracker.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4D7DBE590C04A8FF00D8835D /* FaceTracker-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "FaceTracker-Info.plist"; sourceTree = "<group>"; };
|
||||
4DBF87300C05731500880673 /* haarcascade_frontalface_alt2.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; name = haarcascade_frontalface_alt2.xml; path = ../../../data/haarcascades/haarcascade_frontalface_alt2.xml; sourceTree = SOURCE_ROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
4D7DBE550C04A8FF00D8835D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4D95C9BE0C0577B200983E4D /* OpenCV.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
08FB7794FE84155DC02AAC07 /* FrameworkTest */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4D4CDBCC0C0630060001A8A2 /* README.txt */,
|
||||
08FB7795FE84155DC02AAC07 /* Source */,
|
||||
4DBF872C0C0572BC00880673 /* Resources */,
|
||||
4D9D40B00C04AC1600EEFFD0 /* Frameworks */,
|
||||
1AB674ADFE9D54B511CA2CBB /* Products */,
|
||||
);
|
||||
name = FrameworkTest;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
08FB7795FE84155DC02AAC07 /* Source */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
08FB7796FE84155DC02AAC07 /* FaceTracker.cpp */,
|
||||
);
|
||||
name = Source;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1AB674ADFE9D54B511CA2CBB /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4D7DBE570C04A8FF00D8835D /* FaceTracker.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4D9D40B00C04AC1600EEFFD0 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4D06E1E00C039982004AF23F /* OpenCV.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4DBF872C0C0572BC00880673 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4DBF87300C05731500880673 /* haarcascade_frontalface_alt2.xml */,
|
||||
4D7DBE590C04A8FF00D8835D /* FaceTracker-Info.plist */,
|
||||
);
|
||||
name = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
4D7DBE560C04A8FF00D8835D /* FaceTracker */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 4D7DBE5A0C04A8FF00D8835D /* Build configuration list for PBXNativeTarget "FaceTracker" */;
|
||||
buildPhases = (
|
||||
4D7DBE530C04A8FF00D8835D /* Resources */,
|
||||
4D7DBE540C04A8FF00D8835D /* Sources */,
|
||||
4D7DBE550C04A8FF00D8835D /* Frameworks */,
|
||||
4D7DBE8F0C04A93300D8835D /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = FaceTracker;
|
||||
productName = FaceTracker;
|
||||
productReference = 4D7DBE570C04A8FF00D8835D /* FaceTracker.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "FaceTracker" */;
|
||||
hasScannedForEncodings = 1;
|
||||
mainGroup = 08FB7794FE84155DC02AAC07 /* FrameworkTest */;
|
||||
projectDirPath = "";
|
||||
targets = (
|
||||
4D7DBE560C04A8FF00D8835D /* FaceTracker */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
4D7DBE530C04A8FF00D8835D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4DBF87310C05731500880673 /* haarcascade_frontalface_alt2.xml in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
4D7DBE540C04A8FF00D8835D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4D7DBE8E0C04A90C00D8835D /* FaceTracker.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
1DEB923608733DC60010E9CD /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
PREBINDING = NO;
|
||||
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1DEB923708733DC60010E9CD /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = (
|
||||
ppc,
|
||||
i386,
|
||||
);
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
PREBINDING = NO;
|
||||
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
4D7DBE5B0C04A8FF00D8835D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
|
||||
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
|
||||
);
|
||||
FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../opencv\"";
|
||||
FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../..\"";
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = YES;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_MODEL_TUNING = G5;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
|
||||
INFOPLIST_FILE = "FaceTracker-Info.plist";
|
||||
INSTALL_PATH = "$(HOME)/Applications";
|
||||
OTHER_LDFLAGS = (
|
||||
"-framework",
|
||||
Carbon,
|
||||
);
|
||||
PREBINDING = NO;
|
||||
PRODUCT_NAME = FaceTracker;
|
||||
WRAPPER_EXTENSION = app;
|
||||
ZERO_LINK = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
4D7DBE5C0C04A8FF00D8835D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
|
||||
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
|
||||
);
|
||||
FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../opencv\"";
|
||||
FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../..\"";
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = NO;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||
GCC_MODEL_TUNING = G5;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
|
||||
INFOPLIST_FILE = "FaceTracker-Info.plist";
|
||||
INSTALL_PATH = "$(HOME)/Applications";
|
||||
OTHER_LDFLAGS = (
|
||||
"-framework",
|
||||
Carbon,
|
||||
);
|
||||
PREBINDING = NO;
|
||||
PRODUCT_NAME = FaceTracker;
|
||||
WRAPPER_EXTENSION = app;
|
||||
ZERO_LINK = NO;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "FaceTracker" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
1DEB923608733DC60010E9CD /* Debug */,
|
||||
1DEB923708733DC60010E9CD /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
4D7DBE5A0C04A8FF00D8835D /* Build configuration list for PBXNativeTarget "FaceTracker" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
4D7DBE5B0C04A8FF00D8835D /* Debug */,
|
||||
4D7DBE5C0C04A8FF00D8835D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
FaceTracker/REAME.txt
|
||||
2007-05-24, Mark Asbach <asbach@ient.rwth-aachen.de>
|
||||
|
||||
Objective:
|
||||
This document is intended to get you up and running with an OpenCV Framework on Mac OS X
|
||||
|
||||
Building the OpenCV.framework:
|
||||
In the main directory of the opencv distribution, you will find a shell script called
|
||||
'make_frameworks.sh' that does all of the typical unixy './configure && make' stuff required
|
||||
to build a universal binary framework. Invoke this script from Terminal.app, wait some minutes
|
||||
and you are done.
|
||||
|
||||
OpenCV is a Private Framework:
|
||||
On Mac OS X the concept of Framework bundles is meant to simplify distribution of shared libraries,
|
||||
accompanying headers and documentation. There are however to subtly different 'flavours' of
|
||||
Frameworks: public and private ones. The public frameworks get installed into the Frameworks
|
||||
diretories in /Library, /System/Library or ~/Library and are meant to be shared amongst
|
||||
applications. The private frameworks are only distributed as parts of an Application Bundle.
|
||||
This makes it easier to deploy applications because they bring their own framework invisibly to
|
||||
the user. No installation of the framework is necessary and different applications can bring
|
||||
different versions of the same framework without any conflict.
|
||||
Since OpenCV is still a moving target, it seems best to avoid any installation and versioning issues
|
||||
for an end user. The OpenCV framework that currently comes with this demo application therefore
|
||||
is a Private Framework.
|
||||
|
||||
Use it for targets that result in an Application Bundle:
|
||||
Since it is a Private Framework, it must be copied to the Frameworks/ directory of an Application
|
||||
Bundle, which means, it is useless for plain unix console applications. You should create a Carbon
|
||||
or a Cocoa application target in XCode for your projects. Then add the OpenCV.framework just like
|
||||
in this demo and add a Copy Files build phase to your target. Let that phase copy to the Framework
|
||||
directory and drop the OpenCV.framework on the build phase (again just like in this demo code).
|
||||
|
||||
The resulting application bundle will be self contained and if you set compiler option correctly
|
||||
(in the "Build" tab of the "Project Info" window you should find 'i386 ppc' for the architectures),
|
||||
your application can just be copied to any OS 10.4 Mac and used without further installation.
|
||||
@@ -1,705 +0,0 @@
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/core/utility.hpp>
|
||||
#include <opencv2/imgproc/imgproc_c.h> // cvFindContours
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/objdetect.hpp>
|
||||
#include <opencv2/videoio.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
// Function prototypes
|
||||
void subtractPlane(const cv::Mat& depth, cv::Mat& mask, std::vector<CvPoint>& chain, double f);
|
||||
|
||||
std::vector<CvPoint> maskFromTemplate(const std::vector<cv::linemod::Template>& templates,
|
||||
int num_modalities, cv::Point offset, cv::Size size,
|
||||
cv::Mat& mask, cv::Mat& dst);
|
||||
|
||||
void templateConvexHull(const std::vector<cv::linemod::Template>& templates,
|
||||
int num_modalities, cv::Point offset, cv::Size size,
|
||||
cv::Mat& dst);
|
||||
|
||||
void drawResponse(const std::vector<cv::linemod::Template>& templates,
|
||||
int num_modalities, cv::Mat& dst, cv::Point offset, int T);
|
||||
|
||||
cv::Mat displayQuantized(const cv::Mat& quantized);
|
||||
|
||||
// Copy of cv_mouse from cv_utilities
|
||||
class Mouse
|
||||
{
|
||||
public:
|
||||
static void start(const std::string& a_img_name)
|
||||
{
|
||||
cv::setMouseCallback(a_img_name.c_str(), Mouse::cv_on_mouse, 0);
|
||||
}
|
||||
static int event(void)
|
||||
{
|
||||
int l_event = m_event;
|
||||
m_event = -1;
|
||||
return l_event;
|
||||
}
|
||||
static int x(void)
|
||||
{
|
||||
return m_x;
|
||||
}
|
||||
static int y(void)
|
||||
{
|
||||
return m_y;
|
||||
}
|
||||
|
||||
private:
|
||||
static void cv_on_mouse(int a_event, int a_x, int a_y, int, void *)
|
||||
{
|
||||
m_event = a_event;
|
||||
m_x = a_x;
|
||||
m_y = a_y;
|
||||
}
|
||||
|
||||
static int m_event;
|
||||
static int m_x;
|
||||
static int m_y;
|
||||
};
|
||||
int Mouse::m_event;
|
||||
int Mouse::m_x;
|
||||
int Mouse::m_y;
|
||||
|
||||
static void help()
|
||||
{
|
||||
printf("Usage: openni_demo [templates.yml]\n\n"
|
||||
"Place your object on a planar, featureless surface. With the mouse,\n"
|
||||
"frame it in the 'color' window and right click to learn a first template.\n"
|
||||
"Then press 'l' to enter online learning mode, and move the camera around.\n"
|
||||
"When the match score falls between 90-95%% the demo will add a new template.\n\n"
|
||||
"Keys:\n"
|
||||
"\t h -- This help page\n"
|
||||
"\t l -- Toggle online learning\n"
|
||||
"\t m -- Toggle printing match result\n"
|
||||
"\t t -- Toggle printing timings\n"
|
||||
"\t w -- Write learned templates to disk\n"
|
||||
"\t [ ] -- Adjust matching threshold: '[' down, ']' up\n"
|
||||
"\t q -- Quit\n\n");
|
||||
}
|
||||
|
||||
// Adapted from cv_timer in cv_utilities
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
Timer() : start_(0), time_(0) {}
|
||||
|
||||
void start()
|
||||
{
|
||||
start_ = cv::getTickCount();
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
CV_Assert(start_ != 0);
|
||||
int64 end = cv::getTickCount();
|
||||
time_ += end - start_;
|
||||
start_ = 0;
|
||||
}
|
||||
|
||||
double time()
|
||||
{
|
||||
double ret = time_ / cv::getTickFrequency();
|
||||
time_ = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
int64 start_, time_;
|
||||
};
|
||||
|
||||
// Functions to store detector and templates in single XML/YAML file
|
||||
static cv::Ptr<cv::linemod::Detector> readLinemod(const std::string& filename)
|
||||
{
|
||||
cv::Ptr<cv::linemod::Detector> detector = cv::makePtr<cv::linemod::Detector>();
|
||||
cv::FileStorage fs(filename, cv::FileStorage::READ);
|
||||
detector->read(fs.root());
|
||||
|
||||
cv::FileNode fn = fs["classes"];
|
||||
for (cv::FileNodeIterator i = fn.begin(), iend = fn.end(); i != iend; ++i)
|
||||
detector->readClass(*i);
|
||||
|
||||
return detector;
|
||||
}
|
||||
|
||||
static void writeLinemod(const cv::Ptr<cv::linemod::Detector>& detector, const std::string& filename)
|
||||
{
|
||||
cv::FileStorage fs(filename, cv::FileStorage::WRITE);
|
||||
detector->write(fs);
|
||||
|
||||
std::vector<cv::String> ids = detector->classIds();
|
||||
fs << "classes" << "[";
|
||||
for (int i = 0; i < (int)ids.size(); ++i)
|
||||
{
|
||||
fs << "{";
|
||||
detector->writeClass(ids[i], fs);
|
||||
fs << "}"; // current class
|
||||
}
|
||||
fs << "]"; // classes
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
// Various settings and flags
|
||||
bool show_match_result = true;
|
||||
bool show_timings = false;
|
||||
bool learn_online = false;
|
||||
int num_classes = 0;
|
||||
int matching_threshold = 80;
|
||||
/// @todo Keys for changing these?
|
||||
cv::Size roi_size(200, 200);
|
||||
int learning_lower_bound = 90;
|
||||
int learning_upper_bound = 95;
|
||||
|
||||
// Timers
|
||||
Timer extract_timer;
|
||||
Timer match_timer;
|
||||
|
||||
// Initialize HighGUI
|
||||
help();
|
||||
cv::namedWindow("color");
|
||||
cv::namedWindow("normals");
|
||||
Mouse::start("color");
|
||||
|
||||
// Initialize LINEMOD data structures
|
||||
cv::Ptr<cv::linemod::Detector> detector;
|
||||
std::string filename;
|
||||
if (argc == 1)
|
||||
{
|
||||
filename = "linemod_templates.yml";
|
||||
detector = cv::linemod::getDefaultLINEMOD();
|
||||
}
|
||||
else
|
||||
{
|
||||
detector = readLinemod(argv[1]);
|
||||
|
||||
std::vector<cv::String> ids = detector->classIds();
|
||||
num_classes = detector->numClasses();
|
||||
printf("Loaded %s with %d classes and %d templates\n",
|
||||
argv[1], num_classes, detector->numTemplates());
|
||||
if (!ids.empty())
|
||||
{
|
||||
printf("Class ids:\n");
|
||||
std::copy(ids.begin(), ids.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
|
||||
}
|
||||
}
|
||||
int num_modalities = (int)detector->getModalities().size();
|
||||
|
||||
// Open Kinect sensor
|
||||
cv::VideoCapture capture( cv::CAP_OPENNI );
|
||||
if (!capture.isOpened())
|
||||
{
|
||||
printf("Could not open OpenNI-capable sensor\n");
|
||||
return -1;
|
||||
}
|
||||
capture.set(cv::CAP_PROP_OPENNI_REGISTRATION, 1);
|
||||
double focal_length = capture.get(cv::CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH);
|
||||
//printf("Focal length = %f\n", focal_length);
|
||||
|
||||
// Main loop
|
||||
cv::Mat color, depth;
|
||||
for(;;)
|
||||
{
|
||||
// Capture next color/depth pair
|
||||
capture.grab();
|
||||
capture.retrieve(depth, cv::CAP_OPENNI_DEPTH_MAP);
|
||||
capture.retrieve(color, cv::CAP_OPENNI_BGR_IMAGE);
|
||||
|
||||
std::vector<cv::Mat> sources;
|
||||
sources.push_back(color);
|
||||
sources.push_back(depth);
|
||||
cv::Mat display = color.clone();
|
||||
|
||||
if (!learn_online)
|
||||
{
|
||||
cv::Point mouse(Mouse::x(), Mouse::y());
|
||||
int event = Mouse::event();
|
||||
|
||||
// Compute ROI centered on current mouse location
|
||||
cv::Point roi_offset(roi_size.width / 2, roi_size.height / 2);
|
||||
cv::Point pt1 = mouse - roi_offset; // top left
|
||||
cv::Point pt2 = mouse + roi_offset; // bottom right
|
||||
|
||||
if (event == cv::EVENT_RBUTTONDOWN)
|
||||
{
|
||||
// Compute object mask by subtracting the plane within the ROI
|
||||
std::vector<CvPoint> chain(4);
|
||||
chain[0] = pt1;
|
||||
chain[1] = cv::Point(pt2.x, pt1.y);
|
||||
chain[2] = pt2;
|
||||
chain[3] = cv::Point(pt1.x, pt2.y);
|
||||
cv::Mat mask;
|
||||
subtractPlane(depth, mask, chain, focal_length);
|
||||
|
||||
cv::imshow("mask", mask);
|
||||
|
||||
// Extract template
|
||||
std::string class_id = cv::format("class%d", num_classes);
|
||||
cv::Rect bb;
|
||||
extract_timer.start();
|
||||
int template_id = detector->addTemplate(sources, class_id, mask, &bb);
|
||||
extract_timer.stop();
|
||||
if (template_id != -1)
|
||||
{
|
||||
printf("*** Added template (id %d) for new object class %d***\n",
|
||||
template_id, num_classes);
|
||||
//printf("Extracted at (%d, %d) size %dx%d\n", bb.x, bb.y, bb.width, bb.height);
|
||||
}
|
||||
|
||||
++num_classes;
|
||||
}
|
||||
|
||||
// Draw ROI for display
|
||||
cv::rectangle(display, pt1, pt2, CV_RGB(0,0,0), 3);
|
||||
cv::rectangle(display, pt1, pt2, CV_RGB(255,255,0), 1);
|
||||
}
|
||||
|
||||
// Perform matching
|
||||
std::vector<cv::linemod::Match> matches;
|
||||
std::vector<cv::String> class_ids;
|
||||
std::vector<cv::Mat> quantized_images;
|
||||
match_timer.start();
|
||||
detector->match(sources, (float)matching_threshold, matches, class_ids, quantized_images);
|
||||
match_timer.stop();
|
||||
|
||||
int classes_visited = 0;
|
||||
std::set<std::string> visited;
|
||||
|
||||
for (int i = 0; (i < (int)matches.size()) && (classes_visited < num_classes); ++i)
|
||||
{
|
||||
cv::linemod::Match m = matches[i];
|
||||
|
||||
if (visited.insert(m.class_id).second)
|
||||
{
|
||||
++classes_visited;
|
||||
|
||||
if (show_match_result)
|
||||
{
|
||||
printf("Similarity: %5.1f%%; x: %3d; y: %3d; class: %s; template: %3d\n",
|
||||
m.similarity, m.x, m.y, m.class_id.c_str(), m.template_id);
|
||||
}
|
||||
|
||||
// Draw matching template
|
||||
const std::vector<cv::linemod::Template>& templates = detector->getTemplates(m.class_id, m.template_id);
|
||||
drawResponse(templates, num_modalities, display, cv::Point(m.x, m.y), detector->getT(0));
|
||||
|
||||
if (learn_online == true)
|
||||
{
|
||||
/// @todo Online learning possibly broken by new gradient feature extraction,
|
||||
/// which assumes an accurate object outline.
|
||||
|
||||
// Compute masks based on convex hull of matched template
|
||||
cv::Mat color_mask, depth_mask;
|
||||
std::vector<CvPoint> chain = maskFromTemplate(templates, num_modalities,
|
||||
cv::Point(m.x, m.y), color.size(),
|
||||
color_mask, display);
|
||||
subtractPlane(depth, depth_mask, chain, focal_length);
|
||||
|
||||
cv::imshow("mask", depth_mask);
|
||||
|
||||
// If pretty sure (but not TOO sure), add new template
|
||||
if (learning_lower_bound < m.similarity && m.similarity < learning_upper_bound)
|
||||
{
|
||||
extract_timer.start();
|
||||
int template_id = detector->addTemplate(sources, m.class_id, depth_mask);
|
||||
extract_timer.stop();
|
||||
if (template_id != -1)
|
||||
{
|
||||
printf("*** Added template (id %d) for existing object class %s***\n",
|
||||
template_id, m.class_id.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (show_match_result && matches.empty())
|
||||
printf("No matches found...\n");
|
||||
if (show_timings)
|
||||
{
|
||||
printf("Training: %.2fs\n", extract_timer.time());
|
||||
printf("Matching: %.2fs\n", match_timer.time());
|
||||
}
|
||||
if (show_match_result || show_timings)
|
||||
printf("------------------------------------------------------------\n");
|
||||
|
||||
cv::imshow("color", display);
|
||||
cv::imshow("normals", quantized_images[1]);
|
||||
|
||||
cv::FileStorage fs;
|
||||
char key = (char)cv::waitKey(10);
|
||||
if( key == 'q' )
|
||||
break;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case 'h':
|
||||
help();
|
||||
break;
|
||||
case 'm':
|
||||
// toggle printing match result
|
||||
show_match_result = !show_match_result;
|
||||
printf("Show match result %s\n", show_match_result ? "ON" : "OFF");
|
||||
break;
|
||||
case 't':
|
||||
// toggle printing timings
|
||||
show_timings = !show_timings;
|
||||
printf("Show timings %s\n", show_timings ? "ON" : "OFF");
|
||||
break;
|
||||
case 'l':
|
||||
// toggle online learning
|
||||
learn_online = !learn_online;
|
||||
printf("Online learning %s\n", learn_online ? "ON" : "OFF");
|
||||
break;
|
||||
case '[':
|
||||
// decrement threshold
|
||||
matching_threshold = std::max(matching_threshold - 1, -100);
|
||||
printf("New threshold: %d\n", matching_threshold);
|
||||
break;
|
||||
case ']':
|
||||
// increment threshold
|
||||
matching_threshold = std::min(matching_threshold + 1, +100);
|
||||
printf("New threshold: %d\n", matching_threshold);
|
||||
break;
|
||||
case 'w':
|
||||
// write model to disk
|
||||
writeLinemod(detector, filename);
|
||||
printf("Wrote detector and templates to %s\n", filename.c_str());
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void reprojectPoints(const std::vector<cv::Point3d>& proj, std::vector<cv::Point3d>& real, double f)
|
||||
{
|
||||
real.resize(proj.size());
|
||||
double f_inv = 1.0 / f;
|
||||
|
||||
for (int i = 0; i < (int)proj.size(); ++i)
|
||||
{
|
||||
double Z = proj[i].z;
|
||||
real[i].x = (proj[i].x - 320.) * (f_inv * Z);
|
||||
real[i].y = (proj[i].y - 240.) * (f_inv * Z);
|
||||
real[i].z = Z;
|
||||
}
|
||||
}
|
||||
|
||||
static void filterPlane(IplImage * ap_depth, std::vector<IplImage *> & a_masks, std::vector<CvPoint> & a_chain, double f)
|
||||
{
|
||||
const int l_num_cost_pts = 200;
|
||||
|
||||
float l_thres = 4;
|
||||
|
||||
IplImage * lp_mask = cvCreateImage(cvGetSize(ap_depth), IPL_DEPTH_8U, 1);
|
||||
cvSet(lp_mask, cvRealScalar(0));
|
||||
|
||||
std::vector<CvPoint> l_chain_vector;
|
||||
|
||||
float l_chain_length = 0;
|
||||
float * lp_seg_length = new float[a_chain.size()];
|
||||
|
||||
for (int l_i = 0; l_i < (int)a_chain.size(); ++l_i)
|
||||
{
|
||||
float x_diff = (float)(a_chain[(l_i + 1) % a_chain.size()].x - a_chain[l_i].x);
|
||||
float y_diff = (float)(a_chain[(l_i + 1) % a_chain.size()].y - a_chain[l_i].y);
|
||||
lp_seg_length[l_i] = sqrt(x_diff*x_diff + y_diff*y_diff);
|
||||
l_chain_length += lp_seg_length[l_i];
|
||||
}
|
||||
for (int l_i = 0; l_i < (int)a_chain.size(); ++l_i)
|
||||
{
|
||||
if (lp_seg_length[l_i] > 0)
|
||||
{
|
||||
int l_cur_num = cvRound(l_num_cost_pts * lp_seg_length[l_i] / l_chain_length);
|
||||
float l_cur_len = lp_seg_length[l_i] / l_cur_num;
|
||||
|
||||
for (int l_j = 0; l_j < l_cur_num; ++l_j)
|
||||
{
|
||||
float l_ratio = (l_cur_len * l_j / lp_seg_length[l_i]);
|
||||
|
||||
CvPoint l_pts;
|
||||
|
||||
l_pts.x = cvRound(l_ratio * (a_chain[(l_i + 1) % a_chain.size()].x - a_chain[l_i].x) + a_chain[l_i].x);
|
||||
l_pts.y = cvRound(l_ratio * (a_chain[(l_i + 1) % a_chain.size()].y - a_chain[l_i].y) + a_chain[l_i].y);
|
||||
|
||||
l_chain_vector.push_back(l_pts);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<cv::Point3d> lp_src_3Dpts(l_chain_vector.size());
|
||||
|
||||
for (int l_i = 0; l_i < (int)l_chain_vector.size(); ++l_i)
|
||||
{
|
||||
lp_src_3Dpts[l_i].x = l_chain_vector[l_i].x;
|
||||
lp_src_3Dpts[l_i].y = l_chain_vector[l_i].y;
|
||||
lp_src_3Dpts[l_i].z = CV_IMAGE_ELEM(ap_depth, unsigned short, cvRound(lp_src_3Dpts[l_i].y), cvRound(lp_src_3Dpts[l_i].x));
|
||||
//CV_IMAGE_ELEM(lp_mask,unsigned char,(int)lp_src_3Dpts[l_i].Y,(int)lp_src_3Dpts[l_i].X)=255;
|
||||
}
|
||||
//cv_show_image(lp_mask,"hallo2");
|
||||
|
||||
reprojectPoints(lp_src_3Dpts, lp_src_3Dpts, f);
|
||||
|
||||
CvMat * lp_pts = cvCreateMat((int)l_chain_vector.size(), 4, CV_32F);
|
||||
CvMat * lp_v = cvCreateMat(4, 4, CV_32F);
|
||||
CvMat * lp_w = cvCreateMat(4, 1, CV_32F);
|
||||
|
||||
for (int l_i = 0; l_i < (int)l_chain_vector.size(); ++l_i)
|
||||
{
|
||||
CV_MAT_ELEM(*lp_pts, float, l_i, 0) = (float)lp_src_3Dpts[l_i].x;
|
||||
CV_MAT_ELEM(*lp_pts, float, l_i, 1) = (float)lp_src_3Dpts[l_i].y;
|
||||
CV_MAT_ELEM(*lp_pts, float, l_i, 2) = (float)lp_src_3Dpts[l_i].z;
|
||||
CV_MAT_ELEM(*lp_pts, float, l_i, 3) = 1.0f;
|
||||
}
|
||||
cvSVD(lp_pts, lp_w, 0, lp_v);
|
||||
|
||||
float l_n[4] = {CV_MAT_ELEM(*lp_v, float, 0, 3),
|
||||
CV_MAT_ELEM(*lp_v, float, 1, 3),
|
||||
CV_MAT_ELEM(*lp_v, float, 2, 3),
|
||||
CV_MAT_ELEM(*lp_v, float, 3, 3)};
|
||||
|
||||
float l_norm = sqrt(l_n[0] * l_n[0] + l_n[1] * l_n[1] + l_n[2] * l_n[2]);
|
||||
|
||||
l_n[0] /= l_norm;
|
||||
l_n[1] /= l_norm;
|
||||
l_n[2] /= l_norm;
|
||||
l_n[3] /= l_norm;
|
||||
|
||||
float l_max_dist = 0;
|
||||
|
||||
for (int l_i = 0; l_i < (int)l_chain_vector.size(); ++l_i)
|
||||
{
|
||||
float l_dist = l_n[0] * CV_MAT_ELEM(*lp_pts, float, l_i, 0) +
|
||||
l_n[1] * CV_MAT_ELEM(*lp_pts, float, l_i, 1) +
|
||||
l_n[2] * CV_MAT_ELEM(*lp_pts, float, l_i, 2) +
|
||||
l_n[3] * CV_MAT_ELEM(*lp_pts, float, l_i, 3);
|
||||
|
||||
if (fabs(l_dist) > l_max_dist)
|
||||
l_max_dist = l_dist;
|
||||
}
|
||||
//std::cerr << "plane: " << l_n[0] << ";" << l_n[1] << ";" << l_n[2] << ";" << l_n[3] << " maxdist: " << l_max_dist << " end" << std::endl;
|
||||
int l_minx = ap_depth->width;
|
||||
int l_miny = ap_depth->height;
|
||||
int l_maxx = 0;
|
||||
int l_maxy = 0;
|
||||
|
||||
for (int l_i = 0; l_i < (int)a_chain.size(); ++l_i)
|
||||
{
|
||||
l_minx = std::min(l_minx, a_chain[l_i].x);
|
||||
l_miny = std::min(l_miny, a_chain[l_i].y);
|
||||
l_maxx = std::max(l_maxx, a_chain[l_i].x);
|
||||
l_maxy = std::max(l_maxy, a_chain[l_i].y);
|
||||
}
|
||||
int l_w = l_maxx - l_minx + 1;
|
||||
int l_h = l_maxy - l_miny + 1;
|
||||
int l_nn = (int)a_chain.size();
|
||||
|
||||
CvPoint * lp_chain = new CvPoint[l_nn];
|
||||
|
||||
for (int l_i = 0; l_i < l_nn; ++l_i)
|
||||
lp_chain[l_i] = a_chain[l_i];
|
||||
|
||||
cvFillPoly(lp_mask, &lp_chain, &l_nn, 1, cvScalar(255, 255, 255));
|
||||
|
||||
delete[] lp_chain;
|
||||
|
||||
//cv_show_image(lp_mask,"hallo1");
|
||||
|
||||
std::vector<cv::Point3d> lp_dst_3Dpts(l_h * l_w);
|
||||
|
||||
int l_ind = 0;
|
||||
|
||||
for (int l_r = 0; l_r < l_h; ++l_r)
|
||||
{
|
||||
for (int l_c = 0; l_c < l_w; ++l_c)
|
||||
{
|
||||
lp_dst_3Dpts[l_ind].x = l_c + l_minx;
|
||||
lp_dst_3Dpts[l_ind].y = l_r + l_miny;
|
||||
lp_dst_3Dpts[l_ind].z = CV_IMAGE_ELEM(ap_depth, unsigned short, l_r + l_miny, l_c + l_minx);
|
||||
++l_ind;
|
||||
}
|
||||
}
|
||||
reprojectPoints(lp_dst_3Dpts, lp_dst_3Dpts, f);
|
||||
|
||||
l_ind = 0;
|
||||
|
||||
for (int l_r = 0; l_r < l_h; ++l_r)
|
||||
{
|
||||
for (int l_c = 0; l_c < l_w; ++l_c)
|
||||
{
|
||||
float l_dist = (float)(l_n[0] * lp_dst_3Dpts[l_ind].x + l_n[1] * lp_dst_3Dpts[l_ind].y + lp_dst_3Dpts[l_ind].z * l_n[2] + l_n[3]);
|
||||
|
||||
++l_ind;
|
||||
|
||||
if (CV_IMAGE_ELEM(lp_mask, unsigned char, l_r + l_miny, l_c + l_minx) != 0)
|
||||
{
|
||||
if (fabs(l_dist) < std::max(l_thres, (l_max_dist * 2.0f)))
|
||||
{
|
||||
for (int l_p = 0; l_p < (int)a_masks.size(); ++l_p)
|
||||
{
|
||||
int l_col = cvRound((l_c + l_minx) / (l_p + 1.0));
|
||||
int l_row = cvRound((l_r + l_miny) / (l_p + 1.0));
|
||||
|
||||
CV_IMAGE_ELEM(a_masks[l_p], unsigned char, l_row, l_col) = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int l_p = 0; l_p < (int)a_masks.size(); ++l_p)
|
||||
{
|
||||
int l_col = cvRound((l_c + l_minx) / (l_p + 1.0));
|
||||
int l_row = cvRound((l_r + l_miny) / (l_p + 1.0));
|
||||
|
||||
CV_IMAGE_ELEM(a_masks[l_p], unsigned char, l_row, l_col) = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cvReleaseImage(&lp_mask);
|
||||
cvReleaseMat(&lp_pts);
|
||||
cvReleaseMat(&lp_w);
|
||||
cvReleaseMat(&lp_v);
|
||||
}
|
||||
|
||||
void subtractPlane(const cv::Mat& depth, cv::Mat& mask, std::vector<CvPoint>& chain, double f)
|
||||
{
|
||||
mask = cv::Mat::zeros(depth.size(), CV_8U);
|
||||
std::vector<IplImage*> tmp;
|
||||
IplImage mask_ipl = mask;
|
||||
tmp.push_back(&mask_ipl);
|
||||
IplImage depth_ipl = depth;
|
||||
filterPlane(&depth_ipl, tmp, chain, f);
|
||||
}
|
||||
|
||||
std::vector<CvPoint> maskFromTemplate(const std::vector<cv::linemod::Template>& templates,
|
||||
int num_modalities, cv::Point offset, cv::Size size,
|
||||
cv::Mat& mask, cv::Mat& dst)
|
||||
{
|
||||
templateConvexHull(templates, num_modalities, offset, size, mask);
|
||||
|
||||
const int OFFSET = 30;
|
||||
cv::dilate(mask, mask, cv::Mat(), cv::Point(-1,-1), OFFSET);
|
||||
|
||||
CvMemStorage * lp_storage = cvCreateMemStorage(0);
|
||||
CvTreeNodeIterator l_iterator;
|
||||
CvSeqReader l_reader;
|
||||
CvSeq * lp_contour = 0;
|
||||
|
||||
cv::Mat mask_copy = mask.clone();
|
||||
IplImage mask_copy_ipl = mask_copy;
|
||||
cvFindContours(&mask_copy_ipl, lp_storage, &lp_contour, sizeof(CvContour),
|
||||
CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
|
||||
|
||||
std::vector<CvPoint> l_pts1; // to use as input to cv_primesensor::filter_plane
|
||||
|
||||
cvInitTreeNodeIterator(&l_iterator, lp_contour, 1);
|
||||
while ((lp_contour = (CvSeq *)cvNextTreeNode(&l_iterator)) != 0)
|
||||
{
|
||||
CvPoint l_pt0;
|
||||
cvStartReadSeq(lp_contour, &l_reader, 0);
|
||||
CV_READ_SEQ_ELEM(l_pt0, l_reader);
|
||||
l_pts1.push_back(l_pt0);
|
||||
|
||||
for (int i = 0; i < lp_contour->total; ++i)
|
||||
{
|
||||
CvPoint l_pt1;
|
||||
CV_READ_SEQ_ELEM(l_pt1, l_reader);
|
||||
/// @todo Really need dst at all? Can just as well do this outside
|
||||
cv::line(dst, l_pt0, l_pt1, CV_RGB(0, 255, 0), 2);
|
||||
|
||||
l_pt0 = l_pt1;
|
||||
l_pts1.push_back(l_pt0);
|
||||
}
|
||||
}
|
||||
cvReleaseMemStorage(&lp_storage);
|
||||
|
||||
return l_pts1;
|
||||
}
|
||||
|
||||
// Adapted from cv_show_angles
|
||||
cv::Mat displayQuantized(const cv::Mat& quantized)
|
||||
{
|
||||
cv::Mat color(quantized.size(), CV_8UC3);
|
||||
for (int r = 0; r < quantized.rows; ++r)
|
||||
{
|
||||
const uchar* quant_r = quantized.ptr(r);
|
||||
cv::Vec3b* color_r = color.ptr<cv::Vec3b>(r);
|
||||
|
||||
for (int c = 0; c < quantized.cols; ++c)
|
||||
{
|
||||
cv::Vec3b& bgr = color_r[c];
|
||||
switch (quant_r[c])
|
||||
{
|
||||
case 0: bgr[0]= 0; bgr[1]= 0; bgr[2]= 0; break;
|
||||
case 1: bgr[0]= 55; bgr[1]= 55; bgr[2]= 55; break;
|
||||
case 2: bgr[0]= 80; bgr[1]= 80; bgr[2]= 80; break;
|
||||
case 4: bgr[0]=105; bgr[1]=105; bgr[2]=105; break;
|
||||
case 8: bgr[0]=130; bgr[1]=130; bgr[2]=130; break;
|
||||
case 16: bgr[0]=155; bgr[1]=155; bgr[2]=155; break;
|
||||
case 32: bgr[0]=180; bgr[1]=180; bgr[2]=180; break;
|
||||
case 64: bgr[0]=205; bgr[1]=205; bgr[2]=205; break;
|
||||
case 128: bgr[0]=230; bgr[1]=230; bgr[2]=230; break;
|
||||
case 255: bgr[0]= 0; bgr[1]= 0; bgr[2]=255; break;
|
||||
default: bgr[0]= 0; bgr[1]=255; bgr[2]= 0; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// Adapted from cv_line_template::convex_hull
|
||||
void templateConvexHull(const std::vector<cv::linemod::Template>& templates,
|
||||
int num_modalities, cv::Point offset, cv::Size size,
|
||||
cv::Mat& dst)
|
||||
{
|
||||
std::vector<cv::Point> points;
|
||||
for (int m = 0; m < num_modalities; ++m)
|
||||
{
|
||||
for (int i = 0; i < (int)templates[m].features.size(); ++i)
|
||||
{
|
||||
cv::linemod::Feature f = templates[m].features[i];
|
||||
points.push_back(cv::Point(f.x, f.y) + offset);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<cv::Point> hull;
|
||||
cv::convexHull(points, hull);
|
||||
|
||||
dst = cv::Mat::zeros(size, CV_8U);
|
||||
const int hull_count = (int)hull.size();
|
||||
const cv::Point* hull_pts = &hull[0];
|
||||
cv::fillPoly(dst, &hull_pts, &hull_count, 1, cv::Scalar(255));
|
||||
}
|
||||
|
||||
void drawResponse(const std::vector<cv::linemod::Template>& templates,
|
||||
int num_modalities, cv::Mat& dst, cv::Point offset, int T)
|
||||
{
|
||||
static const cv::Scalar COLORS[5] = { CV_RGB(0, 0, 255),
|
||||
CV_RGB(0, 255, 0),
|
||||
CV_RGB(255, 255, 0),
|
||||
CV_RGB(255, 140, 0),
|
||||
CV_RGB(255, 0, 0) };
|
||||
|
||||
for (int m = 0; m < num_modalities; ++m)
|
||||
{
|
||||
// NOTE: Original demo recalculated max response for each feature in the TxT
|
||||
// box around it and chose the display color based on that response. Here
|
||||
// the display color just depends on the modality.
|
||||
cv::Scalar color = COLORS[m];
|
||||
|
||||
for (int i = 0; i < (int)templates[m].features.size(); ++i)
|
||||
{
|
||||
cv::linemod::Feature f = templates[m].features[i];
|
||||
cv::Point pt(f.x + offset.x, f.y + offset.y);
|
||||
cv::circle(dst, pt, T / 2, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 95 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 93 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 59 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 97 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 111 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 69 KiB |
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* textdetection.cpp
|
||||
*
|
||||
* A demo program of the Extremal Region Filter algorithm described in
|
||||
* Neumann L., Matas J.: Real-Time Scene Text Localization and Recognition, CVPR 2012
|
||||
*
|
||||
* Created on: Sep 23, 2013
|
||||
* Author: Lluis Gomez i Bigorda <lgomez AT cvc.uab.es>
|
||||
*/
|
||||
|
||||
#include "opencv2/opencv.hpp"
|
||||
#include "opencv2/objdetect.hpp"
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void show_help_and_exit(const char *cmd);
|
||||
void groups_draw(Mat &src, vector<Rect> &groups);
|
||||
void er_show(vector<Mat> &channels, vector<vector<ERStat> > ®ions);
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
cout << endl << argv[0] << endl << endl;
|
||||
cout << "Demo program of the Extremal Region Filter algorithm described in " << endl;
|
||||
cout << "Neumann L., Matas J.: Real-Time Scene Text Localization and Recognition, CVPR 2012" << endl << endl;
|
||||
|
||||
if (argc < 2) show_help_and_exit(argv[0]);
|
||||
|
||||
Mat src = imread(argv[1]);
|
||||
|
||||
// Extract channels to be processed individually
|
||||
vector<Mat> channels;
|
||||
computeNMChannels(src, channels);
|
||||
|
||||
int cn = (int)channels.size();
|
||||
// Append negative channels to detect ER- (bright regions over dark background)
|
||||
for (int c = 0; c < cn-1; c++)
|
||||
channels.push_back(255-channels[c]);
|
||||
|
||||
// Create ERFilter objects with the 1st and 2nd stage default classifiers
|
||||
Ptr<ERFilter> er_filter1 = createERFilterNM1(loadClassifierNM1("trained_classifierNM1.xml"),16,0.00015f,0.13f,0.2f,true,0.1f);
|
||||
Ptr<ERFilter> er_filter2 = createERFilterNM2(loadClassifierNM2("trained_classifierNM2.xml"),0.5);
|
||||
|
||||
vector<vector<ERStat> > regions(channels.size());
|
||||
// Apply the default cascade classifier to each independent channel (could be done in parallel)
|
||||
cout << "Extracting Class Specific Extremal Regions from " << (int)channels.size() << " channels ..." << endl;
|
||||
cout << " (...) this may take a while (...)" << endl << endl;
|
||||
for (int c=0; c<(int)channels.size(); c++)
|
||||
{
|
||||
er_filter1->run(channels[c], regions[c]);
|
||||
er_filter2->run(channels[c], regions[c]);
|
||||
}
|
||||
|
||||
// Detect character groups
|
||||
cout << "Grouping extracted ERs ... ";
|
||||
vector<Rect> groups;
|
||||
erGrouping(channels, regions, "trained_classifier_erGrouping.xml", 0.5, groups);
|
||||
|
||||
// draw groups
|
||||
groups_draw(src, groups);
|
||||
imshow("grouping",src);
|
||||
|
||||
cout << "Done!" << endl << endl;
|
||||
cout << "Press 'e' to show the extracted Extremal Regions, any other key to exit." << endl << endl;
|
||||
if( waitKey (-1) == 101)
|
||||
er_show(channels,regions);
|
||||
|
||||
// memory clean-up
|
||||
er_filter1.release();
|
||||
er_filter2.release();
|
||||
regions.clear();
|
||||
if (!groups.empty())
|
||||
{
|
||||
groups.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// helper functions
|
||||
|
||||
void show_help_and_exit(const char *cmd)
|
||||
{
|
||||
cout << " Usage: " << cmd << " <input_image> " << endl;
|
||||
cout << " Default classifier files (trained_classifierNM*.xml) must be in current directory" << endl << endl;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void groups_draw(Mat &src, vector<Rect> &groups)
|
||||
{
|
||||
for (int i=(int)groups.size()-1; i>=0; i--)
|
||||
{
|
||||
if (src.type() == CV_8UC3)
|
||||
rectangle(src,groups.at(i).tl(),groups.at(i).br(),Scalar( 0, 255, 255 ), 3, 8 );
|
||||
else
|
||||
rectangle(src,groups.at(i).tl(),groups.at(i).br(),Scalar( 255 ), 3, 8 );
|
||||
}
|
||||
}
|
||||
|
||||
void er_show(vector<Mat> &channels, vector<vector<ERStat> > ®ions)
|
||||
{
|
||||
for (int c=0; c<(int)channels.size(); c++)
|
||||
{
|
||||
Mat dst = Mat::zeros(channels[0].rows+2,channels[0].cols+2,CV_8UC1);
|
||||
for (int r=0; r<(int)regions[c].size(); r++)
|
||||
{
|
||||
ERStat er = regions[c][r];
|
||||
if (er.parent != NULL) // deprecate the root region
|
||||
{
|
||||
int newMaskVal = 255;
|
||||
int flags = 4 + (newMaskVal << 8) + FLOODFILL_FIXED_RANGE + FLOODFILL_MASK_ONLY;
|
||||
floodFill(channels[c],dst,Point(er.pixel%channels[c].cols,er.pixel/channels[c].cols),
|
||||
Scalar(255),0,Scalar(er.level),Scalar(0),flags);
|
||||
}
|
||||
}
|
||||
char buff[10]; char *buff_ptr = buff;
|
||||
sprintf(buff, "channel %d", c);
|
||||
imshow(buff_ptr, dst);
|
||||
}
|
||||
waitKey(-1);
|
||||
}
|
||||
Reference in New Issue
Block a user