Skip to content

Instantly share code, notes, and snippets.

@ksasao
Last active August 29, 2015 14:01
Show Gist options
  • Save ksasao/8832af0129febb40fca0 to your computer and use it in GitHub Desktop.
Save ksasao/8832af0129febb40fca0 to your computer and use it in GitHub Desktop.
C# から 顔認識によく用いられる OpenCV 2.4 の CascadeClassifier をつかうための C++/CLI のコード。System.Drawing の Bitmap が利用可能です。C++/CLI のプロジェクトを作ったら、まず System::Drawing の参照設定を行い、その後 nuget で OpenCV を追加してください。逆だとうまく参照設定できないようです (Visual Studio 2012, 2013)。このコードで作成した DLL のほかに、opencv_core24x.dll, opencv_highgui24x.dll, opencv_imgproc24x.dll, opencv_objdetect24x.dll だけあればうごきます。
#pragma once
#include <opencv2/opencv.hpp>
using namespace System;
using namespace System::Drawing;
using namespace System::Collections::Generic;
namespace OpenCv {
public ref class CascadeClassifier
{
public:
property bool Loaded{
bool get(){ return loaded; }
}
private:
cv::CascadeClassifier* cascade;
bool loaded;
public:
CascadeClassifier(System::String^ cascadeFileName){
std::string filename = convertToStdString(cascadeFileName);
cascade = new cv::CascadeClassifier();
loaded = cascade->load(filename);
}
public:
List<Rectangle>^ DetectMultiScale(Bitmap^ bitmap, double scaleFactor, int minNeighbors, Size minSize, Size maxSize){
auto iplImage = getIplImage(bitmap);
cv::Mat image = cv::cvarrToMat(iplImage);
cv::Mat gray;
cv::cvtColor(image, gray, CV_BGR2GRAY);
cvReleaseImage(&iplImage);
std::vector<cv::Rect> objs;
cascade->detectMultiScale(gray, objs,
scaleFactor, minNeighbors,
CV_HAAR_SCALE_IMAGE,
cv::Size(minSize.Width, minSize.Height),
cv::Size(maxSize.Width, maxSize.Height));
std::vector<cv::Rect>::const_iterator r = objs.begin();
List<Rectangle>^ rectangles = gcnew List<Rectangle>();
for (; r != objs.end(); ++r) {
Rectangle rect = Rectangle(r->x, r->y, r->width, r->height);
rectangles->Add(rect);
}
return rectangles;
}
private:
IplImage* getIplImage(Bitmap^ bitmap){
Drawing::Imaging::BitmapData^ data;
IplImage *image = cvCreateImage(cvSize(bitmap->Width, bitmap->Height), IPL_DEPTH_8U, 3);
data = bitmap->LockBits(
Drawing::Rectangle(0, 0, bitmap->Width, bitmap->Height),
Drawing::Imaging::ImageLockMode::ReadOnly,
Drawing::Imaging::PixelFormat::Format24bppRgb
);
memcpy(image->imageData, data->Scan0.ToPointer(), image->imageSize);
bitmap->UnlockBits(data);
return image;
}
private:
std::string convertToStdString(String^ str)
{
std::string stdStr;
if (str != nullptr && str->Length > 0){
array<Byte>^ data = System::Text::Encoding::Convert(
System::Text::Encoding::Unicode,
System::Text::Encoding::Default,
System::Text::Encoding::Unicode->GetBytes(str));
pin_ptr<Byte> pin = &data[0];
stdStr.assign(reinterpret_cast<char*>(pin), data->Length);
}
return stdStr;
}
};
}
using OpenCv;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace ObjectRecognitionTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
CascadeClassifier detector = new CascadeClassifier(@"cascade.xml");
if (detector.Loaded)
{
Bitmap bmp = new Bitmap("test.png");
List<Rectangle> rects = detector.DetectMultiScale(bmp, 1.1, 3, new Size(20,20), new Size(100,100));
using (Graphics g = Graphics.FromImage(bmp))
{
foreach (Rectangle r in rects)
{
g.DrawRectangle(Pens.Red, r);
}
}
this.pictureBox1.Image = bmp;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment