코드는 일본인이 작성한것 같고 라이센스는 LGPL로 배포되었다.
(추가) 자세히 살펴보니 논문이랑 다른 부분도 있는것 같다. 그냥 참고용으로만 사용하자.
more..
/**
* (C) 2008 Schima
* This code is licenced under the LGPL.
*/
#include "StdAfx.h"
#include "Extras.h"
using namespace System;
using namespace System::Runtime::InteropServices;
namespace N = KwsmLab::OpenCvSharp;
namespace KwsmLab {
namespace OpenCvSharp
{
/// <summary>
/// Niblackの手法による二値化?理を行う。
/// </summary>
/// <param name="src">入力?像</param>
/// <param name="dst">出力?像</param>
/// <param name="size">局所領域のサイズ</param>
/// <param name="k">係?</param>
void Extras::BinarizeNiblack(N::IplImage^ src, N::IplImage^ dst, Int32 size, Double k)
{
CHECK_NULL(src);
CHECK_NULL(dst);
// グレ?スケ?ルのみ
if(src->NChannels != 1){
throw gcnew ArgumentException("入力?像はグレ?スケ?ル?像でなければなりません。");
}
if(dst->NChannels != 1){
throw gcnew ArgumentException("出力?像はグレ?スケ?ル?像でなければなりません。");
}
// サイズのチェック
if(size >= 3 == 0){
throw gcnew ArgumentException("局所領域のサイズは3以上でなければなりません。");
}
if(size % 2 == 0){
throw gcnew ArgumentException("局所領域のサイズは奇?でなければなりません。");
}
N::IplImage^ gray = src->Clone();
gray->EqualizeHist();
Byte* p = dst->ImageDataPtr;
double m, s;
for (int y = 0; y < gray->Height; y++) {
for (int x = 0; x < gray->Width; x++) {
MeanStddev(gray, x, y, size, &m, &s);
int offset = (dst->WidthStep * y) + x;
p[offset] = (Byte)(m + k*s);
}
}
}
/// <summary>
/// Sauvolaの手法による二値化?理を行う。
/// </summary>
/// <param name="src">入力?像</param>
/// <param name="dst">出力?像</param>
/// <param name="size">局所領域のサイズ</param>
/// <param name="k">係?</param>
/// <param name="r">係?</param>
void Extras::BinarizeSauvola(N::IplImage^ src, N::IplImage^ dst, Int32 size, Double k, Double r)
{
CHECK_NULL(src);
CHECK_NULL(dst);
// グレ?スケ?ルのみ
if(src->NChannels != 1){
throw gcnew ArgumentException("入力?像はグレ?スケ?ル?像でなければなりません。");
}
if(dst->NChannels != 1){
throw gcnew ArgumentException("出力?像はグレ?スケ?ル?像でなければなりません。");
}
if(src->Width != dst->Width || src->Height != dst->Height){
throw gcnew ArgumentException("入力?像と出力?像のサイズが違います。");
}
// サイズのチェック
if(size >= 3 == 0){
throw gcnew ArgumentException("局所領域のサイズは3以上でなければなりません。");
}
if(size % 2 == 0){
throw gcnew ArgumentException("局所領域のサイズは奇?でなければなりません。");
}
N::IplImage^ gray = src->Clone();
gray->EqualizeHist();
Byte* p = dst->ImageDataPtr;
double m, s;
int offset;
for (int y = 0; y < gray->Height; y++) {
for (int x = 0; x < gray->Width; x++) {
MeanStddev(gray, x, y, size, &m, &s);
offset = (dst->WidthStep * y) + x;
p[offset] = (Byte)(m + (1 + k*(s/r - 1)));
}
}
}
/// <summary>
/// 注目?素の周??素の平均値と標準偏差を求める
/// </summary>
/// <param name="img">?像の?素デ?タ</param>
/// <param name="x">x座標</param>
/// <param name="y">y座標</param>
/// <param name="size">周??素の探索サイズ。奇?でなければならない</param>
/// <param name="mean">出力される平均</param>
/// <param name="stddev">出力される標準偏差</param>
void Extras::MeanStddev(N::IplImage^ img, Int32 x, Int32 y, Int32 size, Double* mean, Double* stddev)
{
int count = 0;
int sum = 0;
int sum2 = 0;
Byte* p = img->ImageDataPtr;
int xxx, yyy;
int size2 = size / 2;
int widthStep = img->Width;
Byte v;
for(int xx = 0; xx<size; xx++){
for(int yy = 0; yy<size; yy++){
xxx = x + xx - size2;
yyy = y + yy - size2;
if(xxx < 0 || xxx >= img->Width || yyy < 0 || yyy >= img->Height){
continue;
}
v = p[widthStep * yyy + xxx];
sum += v;
sum2 += v * v;
count++;
}
}
*mean = (double)sum / count;
double var = (double)sum2 / count - (*mean)*(*mean);
if(var < 0.0) var = 0.0;
*stddev = sqrt(var);
}
}
}
* (C) 2008 Schima
* This code is licenced under the LGPL.
*/
#include "StdAfx.h"
#include "Extras.h"
using namespace System;
using namespace System::Runtime::InteropServices;
namespace N = KwsmLab::OpenCvSharp;
namespace KwsmLab {
namespace OpenCvSharp
{
/// <summary>
/// Niblackの手法による二値化?理を行う。
/// </summary>
/// <param name="src">入力?像</param>
/// <param name="dst">出力?像</param>
/// <param name="size">局所領域のサイズ</param>
/// <param name="k">係?</param>
void Extras::BinarizeNiblack(N::IplImage^ src, N::IplImage^ dst, Int32 size, Double k)
{
CHECK_NULL(src);
CHECK_NULL(dst);
// グレ?スケ?ルのみ
if(src->NChannels != 1){
throw gcnew ArgumentException("入力?像はグレ?スケ?ル?像でなければなりません。");
}
if(dst->NChannels != 1){
throw gcnew ArgumentException("出力?像はグレ?スケ?ル?像でなければなりません。");
}
// サイズのチェック
if(size >= 3 == 0){
throw gcnew ArgumentException("局所領域のサイズは3以上でなければなりません。");
}
if(size % 2 == 0){
throw gcnew ArgumentException("局所領域のサイズは奇?でなければなりません。");
}
N::IplImage^ gray = src->Clone();
gray->EqualizeHist();
Byte* p = dst->ImageDataPtr;
double m, s;
for (int y = 0; y < gray->Height; y++) {
for (int x = 0; x < gray->Width; x++) {
MeanStddev(gray, x, y, size, &m, &s);
int offset = (dst->WidthStep * y) + x;
p[offset] = (Byte)(m + k*s);
}
}
}
/// <summary>
/// Sauvolaの手法による二値化?理を行う。
/// </summary>
/// <param name="src">入力?像</param>
/// <param name="dst">出力?像</param>
/// <param name="size">局所領域のサイズ</param>
/// <param name="k">係?</param>
/// <param name="r">係?</param>
void Extras::BinarizeSauvola(N::IplImage^ src, N::IplImage^ dst, Int32 size, Double k, Double r)
{
CHECK_NULL(src);
CHECK_NULL(dst);
// グレ?スケ?ルのみ
if(src->NChannels != 1){
throw gcnew ArgumentException("入力?像はグレ?スケ?ル?像でなければなりません。");
}
if(dst->NChannels != 1){
throw gcnew ArgumentException("出力?像はグレ?スケ?ル?像でなければなりません。");
}
if(src->Width != dst->Width || src->Height != dst->Height){
throw gcnew ArgumentException("入力?像と出力?像のサイズが違います。");
}
// サイズのチェック
if(size >= 3 == 0){
throw gcnew ArgumentException("局所領域のサイズは3以上でなければなりません。");
}
if(size % 2 == 0){
throw gcnew ArgumentException("局所領域のサイズは奇?でなければなりません。");
}
N::IplImage^ gray = src->Clone();
gray->EqualizeHist();
Byte* p = dst->ImageDataPtr;
double m, s;
int offset;
for (int y = 0; y < gray->Height; y++) {
for (int x = 0; x < gray->Width; x++) {
MeanStddev(gray, x, y, size, &m, &s);
offset = (dst->WidthStep * y) + x;
p[offset] = (Byte)(m + (1 + k*(s/r - 1)));
}
}
}
/// <summary>
/// 注目?素の周??素の平均値と標準偏差を求める
/// </summary>
/// <param name="img">?像の?素デ?タ</param>
/// <param name="x">x座標</param>
/// <param name="y">y座標</param>
/// <param name="size">周??素の探索サイズ。奇?でなければならない</param>
/// <param name="mean">出力される平均</param>
/// <param name="stddev">出力される標準偏差</param>
void Extras::MeanStddev(N::IplImage^ img, Int32 x, Int32 y, Int32 size, Double* mean, Double* stddev)
{
int count = 0;
int sum = 0;
int sum2 = 0;
Byte* p = img->ImageDataPtr;
int xxx, yyy;
int size2 = size / 2;
int widthStep = img->Width;
Byte v;
for(int xx = 0; xx<size; xx++){
for(int yy = 0; yy<size; yy++){
xxx = x + xx - size2;
yyy = y + yy - size2;
if(xxx < 0 || xxx >= img->Width || yyy < 0 || yyy >= img->Height){
continue;
}
v = p[widthStep * yyy + xxx];
sum += v;
sum2 += v * v;
count++;
}
}
*mean = (double)sum / count;
double var = (double)sum2 / count - (*mean)*(*mean);
if(var < 0.0) var = 0.0;
*stddev = sqrt(var);
}
}
}
촐처: http://coderepos.org/share/browser/lang/cpluspluscli/OpenCvSharp/trunk/OpenCvSharp/Extras.cpp?rev=20977

comments
comments rss (+댓글 쓰러가기)