houghiris.cpp
来自「barcode readers [ from Image]」· C++ 代码 · 共 239 行
CPP
239 行
//
// HoughIris -- Iris detection using Hough transform.
//
// Copyright (C) 2003, 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 "HoughIris.h"
#include "BoxSmooth.h"
#include "HistMod.h"
#include "HoughCircle.h"
#include "HysterisisThreshold.h"
#include "Image.h"
#include "RgbAvg2Gray.h"
#include "RgbMin2Gray.h"
#include "Reduce.h"
#include "Sequence.h"
#include "Sobel.h"
#include "Threshold.h"
#include <coecntrl.h>
#include <coemain.h>
using namespace Core;
namespace Algorithm
{
EXPORT_C CHoughIris* CHoughIris::NewL()
{
return new (ELeave) CHoughIris();
}
CHoughIris::~CHoughIris()
{
}
CHoughIris::CHoughIris()
{
}
//
// The pipeline begins by discarding
// color information from the input image, converting it to a gray image by averaging the RGB values.
// The next step is to reduce the image size horizontally and vertically, in order
// to speed up processing time in later steps. The histogram of the image is then stretched to increase
// the contrast in the dark areas of the image and reduce the contrast in the light areas. The result
// is then smoothed with a square operator. A Sobel edge detector is used to identify the edge pixels between
// the pupil and the iris. Next, hysteresis thresholding is used to extract connected edge pixels that
// are at some point above a relatively high threshold, but everywhere above a relatively low threshold.
// The resulting edges are then passed to a Hough transform that counts the number of pixels that could
// lie on a circle centered at a particular center and radius. The result is the circle center and radius.
bool CHoughIris::FindPupilL(int& cx, int& cy, int& r, CImage image,
int nReduce, int nStretchLow, int nSmooth, int nThreshLow, int nThreshHi,
int nRadiusMin, int nRadiusMax)
{
// save image size for later
IImageSize rSize(image);
int nHeight = rSize.Height();
int nWidth = rSize.Width();
// Construct the image processing pipeline.
// Sequence is CRgbAvg2Gray, CReduce, CHistMod, CBoxSmooth, CSobel, CHysterisisThreshold
CRgbAvg2Gray* pRgbAvg2Gray = CRgbAvg2Gray::NewL();
CleanupStack::PushL(pRgbAvg2Gray);
CSequence* pSequence = CSequence::NewL(pRgbAvg2Gray);
CleanupStack::Check(pRgbAvg2Gray);
CleanupStack::Pop(); // owned by pSequence
CleanupStack::PushL(pSequence); // when this is deleted everything in the sequence is, too
CReduce* pReduce = CReduce::NewL(nReduce, nReduce);
pSequence->AddL(pReduce);
float fTargetHist[256];
HistStretchLow(fTargetHist, nStretchLow);
CHistMod* pHistMod = CHistMod::NewL(fTargetHist);
pSequence->AddL(pHistMod);
CBoxSmooth* pSmooth = CBoxSmooth::NewL(nSmooth, nSmooth);
pSequence->AddL(pSmooth);
CSobel* pSobel = CSobel::NewL();
pSequence->AddL(pSobel);
CHysterisisThreshold* pThreshold = CHysterisisThreshold::NewL(nThreshLow, nThreshHi);
pSequence->AddL(pThreshold);
// Actually process the image
pSequence->PushL(image);
// There should be a result...
if (pSequence->Empty()) {
User::Leave(KErrGeneral);
}
CImage resultImage = pSequence->FrontL();
// Now apply the FindCircle function to locate the pupil center
CHoughCircle* pHough = CHoughCircle::NewL();
CleanupStack::PushL(pHough);
int nPeak = 0;
pHough->FindCircleL(resultImage, nRadiusMin, nRadiusMax, cx, cy, r, nPeak);
// Compensate for image reduction factor
cx *= nReduce;
cy *= nReduce;
r *= nReduce;
// Free objects this routine is responsible for
CleanupStack::Check(pHough);
CleanupStack::PopAndDestroy(/* pHough */);
CleanupStack::Check(pSequence);
CleanupStack::PopAndDestroy(/* pSequence */);
// See if the pupil center is not too close to the image edge. The
// pupil should be between 25% and 75% of the image width and height.
if (cy < nWidth / 4 || cy > nWidth * 3 / 4 ||
cx < nHeight / 4 || cx > nHeight * 3 / 4) {
// too close -- we failed
return false;
} else {
// looks OK
return true;
}
}
// FindScleraL attempts to find the iris-sclera edge using a similar procedure to the FindPupilL
// routine above. Performance was not so good so a different routine is used now. But I left
// FindScleraL in case it becomes useful at some point in the future.
// The overall structure is similar to FindPupilL. Instead of taking the average RGB value to
// convert to gray we use the minimum -- this is intended to enhance the contrast between the
// colored iris (which will have at least one low R, G, or B value) and the white or near-white
// sclera (which should have all high values). We stretch the high histogram values, again to
// increase the contrast between the iris and the light sclera.
// We use a Hough circle routine that assumes a given center value because the pupil
// is assumed to be the center of the iris-sclera circle.
bool CHoughIris::FindScleraL(int cx, int cy, int& r, CImage image,
int nReduce, int nStretchHi, int nSmooth, int nThreshLow, int nThreshHi,
int nRadiusMin, int nRadiusMax)
{
// Build the pipeline.
// Order is CRgbMin2Gray, CReduce, CHistMod, CBoxSmooth, CSobel, CHysterisisThreshold
CRgbMin2Gray* pRgbMin2Gray = CRgbMin2Gray::NewL();
CleanupStack::PushL(pRgbMin2Gray);
CSequence* pSequence = CSequence::NewL(pRgbMin2Gray);
CleanupStack::Pop(); // pSequence takes responsibility for pRgbMin2Gray
CleanupStack::PushL(pSequence); // when this is deleted everything in the sequence is, too
CReduce* pReduce = CReduce::NewL(nReduce, nReduce);
pSequence->AddL(pReduce);
float fTargetHist[256];
HistStretchHi(fTargetHist, nStretchHi);
CHistMod* pHistMod = CHistMod::NewL(fTargetHist);
pSequence->AddL(pHistMod);
CBoxSmooth* pSmooth = CBoxSmooth::NewL(nSmooth, nSmooth);
pSequence->AddL(pSmooth);
CSobel* pSobel = CSobel::NewL();
pSequence->AddL(pSobel);
CHysterisisThreshold* pThreshold = CHysterisisThreshold::NewL(nThreshLow, nThreshHi);
pSequence->AddL(pThreshold);
// Process the image
pSequence->PushL(image);
// There should be a result...
__ASSERT_ALWAYS(!pSequence->Empty(), User::Leave(KErrGeneral));
CImage resultImage = pSequence->FrontL();
// Apply Hough circle finder given center from pupil routine
CHoughCircle* pHough = CHoughCircle::NewL();
CleanupStack::PushL(pHough);
int nPeak = 0;
// Adjust for image reduction
cx /= nReduce;
cy /= nReduce;
// Find the radius
pHough->FindCircleGivenCenterL(resultImage, nRadiusMin, nRadiusMax, cx, cy, r, nPeak);
// Adjust for image reduction
r *= nReduce;
// Destroy the objects this routine is responsible for.
CleanupStack::PopAndDestroy(); // pHough
CleanupStack::PopAndDestroy(); // pSequence
return true;
}
// Create a new target histogram that will stretch all values
// up to nStretchLow so they cover the full 0-255 range. Everything
// else is assigned 255.
void CHoughIris::HistStretchLow(float* pHist, int nStretchLow)
{
int i=0;
float fRemaining = 1.0f;
float fValue = 1.0f / (nStretchLow * 16.0f);
for (; i<nStretchLow; i++) {
pHist[i] = fValue;
fRemaining -= pHist[i];
}
for (; i<256; i++) {
pHist[i] = 0.0f;
}
pHist[255] = fRemaining;
}
// Create a new target histogram that will stretch all values
// above nStretchHigh so they cover the full 0-255 range. Everything
// else is assigned 0.
void CHoughIris::HistStretchHi(float* pHist, int nStretchHi)
{
int i=255;
float fRemaining = 1.0f;
float fValue = 1.0f / ((256-nStretchHi) * 16.0f);
for (; i>nStretchHi; i--) {
pHist[i] = fValue;
fRemaining -= pHist[i];
}
for (; i>0; i--) {
pHist[i] = 0.0f;
}
pHist[0] = fRemaining;
}
};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?