cannyhoriz.cpp
来自「barcode readers [ from Image]」· C++ 代码 · 共 190 行
CPP
190 行
//
// CannyHoriz
// Applies the horizontal Canny operator to an unsigned byte image. The
// output is signed byte.
// The coefficients of the Canny operator were calculated using the formula
// from http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MARBLE/low/edges/canny.htm
//
// Copyright (C) 2006 by Jon A. Webb (Contact via GMail; username is jonawebb)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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 GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#include "Array.h"
#include "CannyHoriz.h"
#include "Debug.h"
#include "Image.h"
#include "GrayImageIter.h"
#include "GrayIndex.h"
#include "ImageSize.h"
#include "Replicate.h"
#include <e32math.h>
#include <e32std.h>
#include <fbs.h>
using namespace Core;
namespace Algorithm
{
EXPORT_C CCannyHoriz* CCannyHoriz::NewL(TReal sigma)
{
CCannyHoriz* pMe = new (ELeave) CCannyHoriz(sigma);
CleanupStack::PushL(pMe);
pMe->ConstructL();
CleanupStack::Pop();
return pMe;
}
CCannyHoriz::~CCannyHoriz()
{
if (ipfCoeff) {
ipfCoeff->Reset();
delete ipfCoeff;
}
delete ipnCoeff;
}
CCannyHoriz::CCannyHoriz(TReal sigma) :
ibEmpty(true),
ifSigma(sigma),
ipfCoeff(NULL),
ipnCoeff(NULL)
{
}
void CCannyHoriz::ConstructL()
{
ComputeCoefficientsL();
}
CImage CCannyHoriz::FrontL()
{
if (ibEmpty) {
User::Leave(KErrGeneral);
return CImage();
}
ibEmpty = true;
return iImage;
}
void CCannyHoriz::PushL(CImage image)
{
IReplicate rRepl(image);
rRepl.CastL(iImage);
image.LockLC();
IGrayImageIter itIn(image);
IGrayImageIter itOut(iImage);
IImageSize size(image);
int nWidth = ipfCoeff->Count();
for (; !itIn.End(); itIn.NextRow(), itOut.NextRow()) {
// initially assign 0 (as signed char) to the output row
Mem::Fill(&itOut(), size.Width(), 128);
for (; !itIn.REnd(); itIn++, itOut++) {
IGrayImageIter itIn2 = itIn;
IGrayImageIter itOut2 = itOut;
// first step in the width of the Canny filter, accumulating the
// sum on the left side of the filter
TInt32 sum = 0;
int nPos;
for (nPos=nWidth-1; nPos>0; nPos--, ++itIn2, ++itOut2) {
if (itIn2.REnd()) {
break;
}
sum += TInt32((*ipnCoeff)[nPos]) * itIn2();
}
// now step through the right side of the Canny filter
for (nPos = 0; nPos < nWidth; nPos++, ++itIn2) {
if (itIn2.REnd()) {
break;
}
sum += TInt32((*ipnCoeff)[nPos]) * itIn2();
}
sum /= 256; // coefficients are scaled when converted to int
// convert to unsigned (really, signed) character
if (sum > 127) sum = 127;
if (sum < -128) sum = -128;
itOut2() = (unsigned char) (sum + 128);
}
}
CleanupStack::PopAndDestroy(); // unlock bitmaps
CDebug::ShowImage(iImage);
ibEmpty = false;
}
bool CCannyHoriz::Empty() const
{
return ibEmpty;
}
// operations
void CCannyHoriz::ComputeCoefficientsL()
{
ipfCoeff = new CArrayFixFlat<TReal>(128);
const TReal threshold = 0.05;
// = Sqrt(2*Pi)
const TReal Sqrt2Pi = 2.506628274631000;
TReal denom1 = 1.0 / (Sqrt2Pi * ifSigma * ifSigma * ifSigma);
TReal denom2 = 1.0 / (2.0 * ifSigma * ifSigma);
TReal denom3 = 1.0 / (ifSigma * ifSigma);
int x = 0;
int nMinTail = 99;
TReal coeff;
do {
TReal exp;
Math::Exp(exp, -x * x * denom2);
coeff = - denom1 * exp * (1 - x * x * denom3);
ipfCoeff->AppendL(coeff);
x += 1;
if (coeff > 0 && nMinTail == 99) {
nMinTail = 2*x;
}
// note on condition below: the coefficients start out negative, then
// turn positive and tail off to zero. We don't know the exact shape of
// the curve but look for the zero crossing above and keep generating coefficients
// until we reach twice that point. Then we look for the point where the
// coefficients fall below the threshold.
} while (coeff < 0 || x < nMinTail || coeff > threshold); // track through end of negative tail
// normalize so sum is zero. remember that element 0
// is the central element so counted once the others twice
int i;
TReal sum = ipfCoeff->At(0);
for (i=1; i<ipfCoeff->Count(); i++) {
sum += ipfCoeff->At(i) * 2;
}
sum /= 1 + 2*(ipfCoeff->Count() - 1);
for (i=0; i<ipfCoeff->Count(); i++) {
ipfCoeff->At(i) -= sum;
}
// now normalize so the sum of absolute values is 1
sum = Abs(ipfCoeff->At(0));
for (i=1; i<ipfCoeff->Count(); i++) {
sum += Abs(ipfCoeff->At(i) * 2);
}
for (i=0; i<ipfCoeff->Count(); i++) {
ipfCoeff->At(i) /= sum;
}
// finally, convert to int (we do computation in int
// to avoid floating point)
ipnCoeff = CArray<TInt16>::NewL(ipfCoeff->Count());
for (i=0; i<ipfCoeff->Count(); i++) {
Math::Int((*ipnCoeff)[i], ipfCoeff->At(i) * 256.0);
}
}
};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?