VectorInt ClassSummaryList::LLoydsBinSizes () const { VectorInt binSizes; ClassSummaryList::const_iterator idx; for (idx = begin (); idx != end (); idx++) { const ClassSummaryPtr cs = *idx; for (kkuint32 lloydsEntryIdx = 0; lloydsEntryIdx < cs->NumOfLLoydsEntries (); lloydsEntryIdx++) { LLoydsEntryPtr lloydsEntry = cs->LLoydsEntryByIndex (lloydsEntryIdx); if (lloydsEntry) { kkuint32 zed = 0; kkint32 binSize = lloydsEntry->LLoydsBinSize (); // if 'binSize' not in 'binSizes' then add for (zed = 0; zed < kkuint32 (binSizes.size ()); zed++) { if (binSizes[zed] == binSize) break; } if (zed >= binSizes.size ()) binSizes.push_back (binSize); } } } sort (binSizes.begin (), binSizes.end ()); return binSizes; } /* LLoydsBinSizes */
float KKB::LLoydsIndexOfPatchiness (const VectorInt& bins) { // As defined by Andrew Remsen // also look at http://www.pmel.noaa.gov/pubs/outstand/stab1646/statistics.shtml if (bins.size () < 1) return 0.0f; kkuint32 x; double total = 0.0; double mean = 0.0; for (x = 0; x < bins.size (); x++) total += bins[x]; mean = total / double (bins.size ()); double totalDeltaSquared = 0.0; for (x = 0; x < bins.size (); x++) { double delta = double (bins[x]) - mean; totalDeltaSquared += delta * delta; } double var = totalDeltaSquared / bins.size (); double varDivMean = var / mean; double oneDivMean = 1.0 / mean; float p = float ((varDivMean - 1.0 + mean) * oneDivMean); return p; } /* LLoydsIndexOfPatchiness */
void ClassSummaryList::SummaryReport (ostream& r) const { kkuint32 binSizeIDX = 0; r << "Statistic Summary by Class" << endl << endl; VectorInt binSizes = LLoydsBinSizes (); r << "" << "\t" << "" << "\t" << "" << "\t" << "LLoydsIndex's" << endl; r << "ClassName" << "\t" << "U2Stat" << "\t" << "Z-Score"; for (binSizeIDX = 0; binSizeIDX < binSizes.size (); binSizeIDX++) r << "\t" << binSizes[binSizeIDX]; r << endl; const_iterator idx; for (idx = begin (); idx != end (); idx++) { ClassSummaryPtr cs = *idx; r << cs->ClassName () << "\t" << cs->U2Stat () << "\t" << cs->ZScore (); for (binSizeIDX = 0; binSizeIDX < binSizes.size (); binSizeIDX++) { kkint32 binSize = binSizes[binSizeIDX]; LLoydsEntryPtr lloydsEntry = cs->LLoydsEntryByBinSize (binSize); if (lloydsEntry == NULL) r << "\t" << "-"; else r << "\t" << lloydsEntry->LLoydsIndex (); } r << endl; } } /* SummaryReport */
void ClassSummaryList::SpatialOverlapReport (ostream& o) const { KKStr classTitle1, classTitle2; MLClassListPtr classes = GetListOfClasses (); classes->ExtractTwoTitleLines (classTitle1, classTitle2); VectorInt binSizes = LLoydsBinSizes (); for (kkuint32 binSizeIdx = 0; binSizeIdx < kkuint32 (binSizes.size ()); binSizeIdx++) { kkint32 binSize = binSizes[binSizeIdx]; o << endl << endl << endl << "Spatial Overlap Indexes for BinSize[" << binSize << "]" << endl << endl << "Class" << "\t" << classTitle1 << endl << "Name" << "\t" << classTitle2 << endl; ClassSummaryList::const_iterator idx; for (idx = begin (); idx != end (); idx++) { ClassSummaryPtr cs1 = *idx; o << cs1->ClassName (); ClassSummaryList::const_iterator idx2; for (idx2 = begin (); idx2 != end (); idx2++) { ClassSummaryPtr cs2 = *idx2; if (idx == idx2) o << "\t" << "-"; else { double spatialIndex = SpatialOverlapIndex (binSize, cs1, cs2); o << "\t" << spatialIndex; } } o << endl; } } delete classes; } /* SpatialOverlapReport */
RasterPtr SegmentorOTSU::SegmentImage (RasterPtr srcImage, kkint32 numClasses, double& sep ) { /* function [IDX,sep] = otsu (srcImage, numClasses) %OTSU Global image thresholding/segmentation using Otsu's method. % IDX = OTSU(srcImage,N) segments the image srcImage into N classes by means of Otsu's % N-thresholding method. OTSU returns an array IDX containing the cluster % indexes (from 1 to N) of each point. Zero values are assigned to % non-finite (NaN or Inf) pixels. % % IDX = OTSU(srcImage) uses two classes (N=2, default value). % % [IDX,sep] = OTSU(...) also returns the value (sep) of the separability % criterion within the range [0 1]. Zero is obtained only with data % having less than N values, whereas one (optimal value) is obtained only % with N-valued arrays. % % Notes: % ----- % It should be noticed that the thresholds generally become less credible % as the number of classes (N) to be separated increases (see Otsu's % paper for more details). % % If srcImage is an RGB image, a Karhunen-Loeve transform is first performed on % the three R,G,B channels. The segmentation is then carried out on the % image component that contains most of the energy. % % Example: % ------- % load clown % subplot(221) % X = ind2rgb(X,map); % imshow(X) % title('Original','FontWeight','bold') % for numClasses = 2:4 % IDX = otsu(X,numClasses); % subplot(2,2,numClasses) % imagesc(IDX), axis image off % title(['numClasses = ' int2str(numClasses)],'FontWeight','bold') % end % colormap(gray) % % Reference: % --------- % Otsu N, <a href="matlab:web('http://dx.doi.org/doi:10.1109/TSMC.1979.4310076')">A Threshold Selection Method from Gray-Level Histograms</a>, % IEEE Trans. Syst. Man Cybern. 9:62-66;1979 % % See also GRAYTHRESH, IM2BW % % -- Damien Garcia -- 2007/08, revised 2010/03 % Visit my <a % href="matlab:web('http://www.biomecardio.com/matlab/otsu.html')">website</a> for more details about OTSU */ kkint32 pixelIdx = 0; kkint32 x = 0; bool isColorImage = srcImage->Color (); // Checking numClasses (number of classes) if (numClasses == 1) { //IDX = NaN(size(srcImage)); //sep = 0; return NULL; } else if ((numClasses < 1) || (numClasses > 255)) { log.Level (-1) << "SegmentorOTSU::SegmentImage ***ERROR*** 'numClasses must be a between 1 and 255 !'" << endl; sep = 0; return NULL; } if (isColorImage) { srcImage = srcImage->CreateGrayScaleKLT (); } else { srcImage = new Raster (*srcImage); } kkint32 totPixels = srcImage->TotPixels (); kkint32 pixelsCounted = 0; VectorInt unI; VectorInt unICounts; VectorInt32 counts (256, 0); { // %% Convert to 256 levels // srcImage = srcImage-min(srcImage(:)); // srcImage = round(srcImage/max(srcImage(:))*255); // Re-scale Source Image to utilize range of 0 through 255. //%% Probability dCistribution //unI = sort(unique(srcImage)); //nbins = min(length(unI),256); uchar* greenArea = srcImage->GreenArea (); uchar pixelMin = 255; uchar pixelMax = 1; for (pixelIdx = 1; pixelIdx < totPixels; ++pixelIdx) { if (greenArea[pixelIdx] < 1) continue; pixelsCounted++; if (greenArea[pixelIdx] < pixelMin) pixelMin = greenArea[pixelIdx]; if (greenArea[pixelIdx] > pixelMax) pixelMax = greenArea[pixelIdx]; } VectorInt counts (256, 0); for (pixelIdx = 0; pixelIdx < totPixels; ++pixelIdx) { /* double pixelFraction = (double)((double)(greenArea[pixelIdx]) - pixelMin) / (double)srcRange; kkuint32 newPixelVal = (uchar)(pixelFraction * 256.0 + 0.5); if (newPixelVal > 255) newPixelVal = 255; greenArea[pixelIdx] = (uchar)newPixelVal; counts[newPixelVal]++; */ counts[greenArea[pixelIdx]]++; } for (x = 1; x < (kkint32)counts.size (); ++x) { if (counts[x] > 0) { unI.push_back (x); unICounts.push_back (counts[x]); } } } kkint32 nbins = (kkint32)unI.size (); if (nbins <= numClasses) { // IDX = ones (size(srcImage)); //for i = 1:numClasses, IDX(srcImage==unI(i)) = i; end //sep = 1; RasterPtr result = new Raster (srcImage->Height (), srcImage->Width (), false); for (x = 0; x < nbins; ++x) { LabelRaster (result, unI[x], x, srcImage); } sep = 1; delete srcImage; srcImage = NULL; return result; } //elseif (nbins < 256) // [histo,pixval] = hist(srcImage(:),unI); //else // [histo,pixval] = hist(srcImage(:),256); VectorInt histo = unICounts; VectorInt pixval = unI; //P = histo/sum(histo); VectorDouble P (histo.size (), 0.0); for (x = 0; x < (kkint32)histo.size (); ++x) P[x] = (double)(histo[x]) / (double)pixelsCounted; //clear unI unI.clear (); //%% Zeroth- and first-order cumulative moments //w = cumsum(P); VectorDouble w (P.size (), 0.0); w[0] = P[0]; for (x = 1; x < (kkint32)P.size (); ++x) w[x] = w[x - 1] + P[x]; //mu = cumsum((1:nbins).*P); VectorDouble mu (P.size (), 0.0); mu[0] = 1.0 * P[0]; for (x = 1; x < (kkint32)P.size (); ++x) mu[x] = mu[x - 1] + ((x + 1) * P[x]); double muEnd = mu[mu.size () - 1]; //%% Maximal sigmaB^2 and Segmented image if (numClasses == 2) { //sigma2B =... // (mu(end) * w(2:end-1) - mu(2:end-1)) .^2 ./ w(2:end-1)./(1-w(2:end-1)); // ------------------- P1 ----------------- ----------- P2 ----------- //[maxsig,k] = max(sigma2B); VectorDouble wSubSet = SubSet (w, 1, (kkint32)w.size () - 2); VectorDouble muSubSet = SubSet (mu, 1, (kkint32)mu.size () - 2); VectorDouble P1 = Power (Subt (muEnd * wSubSet, muSubSet), 2.0); VectorDouble P2 = DotDiv (wSubSet, Subt (1.0, wSubSet)); VectorDouble sigma2B = DotDiv (P1, P2); double maxSig = sigma2B[0]; kkint32 maxSigIdx = 0; for (x = 1; x < (kkint32)sigma2B.size (); ++x) { if (sigma2B[x] > maxSig) { maxSig = sigma2B[x]; maxSigIdx = x; } } //[maxsig,k] = max(sigma2B); kkint32 k = maxSigIdx; //% segmented image //IDX = ones(size(srcImage)); //IDX(srcImage>pixval(k+1)) = 2; threshold1 = pixval[k + 1]; RasterPtr result = new Raster (srcImage->Height (), srcImage->Width (), false); uchar* resultArea = result->GreenArea (); uchar* srcArea = srcImage->GreenArea (); while (true) { kkuint32 numClass2Pixs = 0; for (x = 0; x < totPixels; ++x) { if (srcArea[x] > threshold1) { resultArea[x] = 2; ++numClass2Pixs; } else { resultArea[x] = 1; } } if ((threshold1 < 1) || (numClass2Pixs >100)) break; --threshold1; } //% separability criterion //sep = maxsig/sum(((1:nbins)-mu(end)).^2.*P); double sum = 0.0; kkint32 y = 0; muEnd = mu[mu.size () - 1]; for (x = 0, y = 1; x < nbins; ++x, ++y) sum = pow (((double)y - muEnd), 2.0) * P[x]; sep = maxSig / sum; delete srcImage; srcImage = NULL; return result; } if (numClasses == 3) { //w0 = w; //w2 = fliplr(cumsum(fliplr(P))); VectorDouble w0 = w; VectorDouble w2 = FlipLeftRight (CumSum (FlipLeftRight (P))); //[w0,w2] = ndgrid(w0,w2); Matrix w0M ((kkint32)w0.size (), (kkint32)w0.size ()); Matrix w2M ((kkint32)w2.size (), (kkint32)w2.size ()); NdGrid (w0, w2, w0M, w2M); //mu0 = mu./w; VectorDouble mu0 = DotDiv (mu, w); //mu2 = fliplr(cumsum(fliplr((1:nbins).*P)) ./ cumsum(fliplr(P))); // 1 2 34 4 32 3 4 321 // ---------- P1 ------------- ------ P2 -------- VectorDouble P1 = CumSum (FlipLeftRight (DotMult (BDV (1.0, 1.0, (double)nbins), P))); VectorDouble P2 = CumSum (FlipLeftRight (P)); VectorDouble mu2 = FlipLeftRight (DotDiv (P1, P2)); // TODO //[mu0,mu2] = ndgrid(mu0,mu2); Matrix mu0M ((kkint32)mu0.size (), (kkint32)mu0.size ()); Matrix mu2M ((kkint32)mu2.size (), (kkint32)mu2.size ()); NdGrid (mu0, mu2, mu0M, mu2M); //w1 = 1-w0-w2; Matrix w1M = 1.0 - w0M - w2M; //w1(w1<=0) = NaN; MakeNanWhenLesOrEqualZero (w1M); //sigma2B =... // w0.*(mu0-mu(end)).^2 + w2.*(mu2-mu(end)).^2 +... // (w0.*(mu0-mu(end)) + w2.*(mu2-mu(end))).^2./w1; Matrix P1M = (DotMult (w0M, Power ((mu0M - muEnd), 2.0))) + (DotMult (w2M, Power ((mu2M - muEnd), 2.0))); Matrix P2M = DotDiv (Power ((DotMult (w0M, (mu0M - muEnd)) + DotMult (w2M, (mu2M - muEnd))), 2.0), w1M); Matrix sigma2B = P1M + P2M; //sigma2B(isnan(sigma2B)) = 0; % zeroing if k1 >= k2 ZeroOutNaN (sigma2B); //[maxsig,k] = max(sigma2B(:)); % Turns sigma2B into 1D Array then locates largest value and index. // [k1,k2] = ind2sub([nbins nbins],k); % Sets k1 and k2 to the indexes for k mapped into a 2D square matrix that is (nbins x nbins) kkint32 k1, k2; double maxsig = 0.0; sigma2B.FindMaxValue (maxsig, k1, k2); //% segmented image RasterPtr result = new Raster (srcImage->Height (), srcImage->Width (), false); { //IDX = ones(size(srcImage))*3; //IDX(srcImage<=pixval(k1)) = 1; //IDX(srcImage>pixval(k1) & srcImage<=pixval(k2)) = 2; uchar* srcData = srcImage->GreenArea (); uchar* data = result->GreenArea (); threshold1 = pixval[k1]; threshold2 = pixval[k2]; for (x = 0; x < totPixels; ++x) { if (srcData[x] <= threshold1) data[x] = 1; else if (srcData[x] <= threshold2) data[x] = 2; else data[x] = 3; } } //% separability criterion //sep = maxsig / sum (((1:nbins)-mu(end)).^2.*P); //VectorDouble xxx = BDV (1.0, 1.0, (double)nbins); //VectorDouble yyy = Subt (xxx, muEnd); //VectorDouble zzz = Power (yyy, 2.0); sep = maxsig / Sum (DotMult (Power (Subt (BDV (1.0, 1.0, (double)nbins), muEnd), 2.0), P)); delete srcImage; srcImage = NULL; return result; } { /* //k0 = linspace(0,1,numClasses+1); % k0 = row vector of linear spaced points between 0 and 1 with (numClasses + 1) points VectorDouble k0 = LinSpace (0, 1, numClasses + 1); //k0 = k0(2:numClasses); [k,y] = fminsearch(@sig_func,k0,optimset('TolX',1)); k = round(k*(nbins-1)+1); % segmented image IDX = ones(size(srcImage))*numClasses; IDX(srcImage<=pixval(k(1))) = 1; for i = 1:numClasses-2 IDX(srcImage>pixval(k(i)) & srcImage<=pixval(k(i+1))) = i+1; end % separability criterion sep = 1-y; */ } delete srcImage; srcImage = NULL; return NULL; } /* SegmentImage */
/** *@brief Segments image into 'numClasses' taking into account only pixels * indicated by 'mask' image. *@param[in] srcImage Image to segment. If it is a color image will be * converted to GrayScale using 'CreateGrayScaleKLTOnMaskedArea' *@param[in] mask Indicates which pixels to consider when thresholding image. Pixels * that are not part of mask will be assigned label '0'. *@param[in] numClasses Number of classes to segment image into. Current only '2' and '3' are supported. *@param[out] sep *@return Labeled GrayScale image where pixels will be label into their respective class; between '1' and 'numClasses'. */ RasterPtr SegmentorOTSU::SegmentMaskedImage (RasterPtr srcImage, RasterPtr mask, kkint32 numClasses, double& sep ) { kkint32 pixelIdx = 0; kkint32 x = 0; bool isColorImage = srcImage->Color (); uchar* maskArea = NULL; uchar maskTh = 0; if (mask) { maskArea = mask->GreenArea (); maskTh = mask->BackgroundPixelTH (); } if (numClasses == 1) { return NULL; } else if ((numClasses < 1) || (numClasses > 255)) { log.Level (-1) << endl << endl << "SegmentorOTSU::SegmentMaskedImage ***ERROR*** 'numClasses must be a between 1 and 255 !'" << endl << endl; sep = 0; return NULL; } if (isColorImage) { if (mask) srcImage = srcImage->CreateGrayScaleKLTOnMaskedArea (*mask); else srcImage = srcImage->CreateGrayScaleKLT (); } else { srcImage = new Raster (*srcImage); } kkint32 totPixels = srcImage->TotPixels (); kkint32 totMaskPixels = totPixels; if (mask) totMaskPixels = mask->TotalBackgroundPixels (); VectorInt unI; VectorInt unICounts; { uchar* greenArea = srcImage->GreenArea (); uchar pixelMin = greenArea[0]; uchar pixelMax = greenArea[0]; for (pixelIdx = 1; pixelIdx < totPixels; ++pixelIdx) { if ((!mask) || (maskArea[pixelIdx] > maskTh)) { if (greenArea[pixelIdx] < pixelMin) pixelMin = greenArea[pixelIdx]; if (greenArea[pixelIdx] > pixelMax) pixelMax = greenArea[pixelIdx]; } } //kkint32 srcRange = pixelMax - pixelMin + 1; VectorInt counts (256, 0); for (pixelIdx = 0; pixelIdx < totPixels; ++pixelIdx) { if ((!mask) || (maskArea[pixelIdx] > maskTh)) counts[greenArea[pixelIdx]]++; } for (x = 0; x < (kkint32)counts.size (); ++x) { if (counts[x] > 0) { unI.push_back (x); unICounts.push_back (counts[x]); } } } kkint32 nbins = (kkint32)unI.size (); if (nbins <= numClasses) { RasterPtr result = new Raster (srcImage->Height (), srcImage->Width (), false); for (x = 0; x < nbins; ++x) { LabelRaster (result, mask, unI[x], x, srcImage); } sep = 1; delete srcImage; srcImage = NULL; return result; } VectorInt histo = unICounts; VectorInt pixval = unI; VectorDouble P (histo.size (), 0.0); for (x = 0; x < (kkint32)histo.size (); ++x) P[x] = (double)(histo[x]) / (double)totMaskPixels; unI.clear (); //%% Zeroth- and first-order cumulative moments //w = cumsum(P); VectorDouble w (P.size (), 0.0); w[0] = P[0]; for (x = 1; x < (kkint32)P.size (); ++x) w[x] = w[x - 1] + P[x]; //mu = cumsum((1:nbins).*P); VectorDouble mu (P.size (), 0.0); mu[0] = 1.0 * P[0]; for (x = 1; x < (kkint32)P.size (); ++x) mu[x] = mu[x - 1] + ((x + 1) * P[x]); double muEnd = mu[mu.size () - 1]; //%% Maximal sigmaB^2 and Segmented image if (numClasses == 2) { //sigma2B =... // (mu(end) * w(2:end-1) - mu(2:end-1)) .^2 ./ w(2:end-1)./(1-w(2:end-1)); // ------------------- P1 ----------------- ----------- P2 ----------- //[maxsig,k] = max(sigma2B); VectorDouble wSubSet = SubSet (w, 1, (kkint32)w.size () - 2); VectorDouble muSubSet = SubSet (mu, 1, (kkint32)mu.size () - 2); VectorDouble P1 = Power (Subt (muEnd * wSubSet, muSubSet), 2.0); VectorDouble P2 = DotDiv (wSubSet, Subt (1.0, wSubSet)); VectorDouble sigma2B = DotDiv (P1, P2); double maxSig = sigma2B[0]; kkint32 maxSigIdx = 0; for (x = 1; x < (kkint32)sigma2B.size (); ++x) { if (sigma2B[x] > maxSig) { maxSig = sigma2B[x]; maxSigIdx = x; } } //[maxsig,k] = max(sigma2B); kkint32 k = maxSigIdx; //% segmented image //IDX = ones(size(srcImage)); //IDX(srcImage>pixval(k+1)) = 2; kkint32 threshold = pixval[k + 1]; RasterPtr result = new Raster (srcImage->Height (), srcImage->Width (), false); uchar* resultArea = result->GreenArea (); uchar* srcArea = srcImage->GreenArea (); for (x = 0; x < totPixels; ++x) { if ((!maskArea) || (maskArea[x] > maskTh)) { if (srcArea[x] > threshold) resultArea[x] = 2; else resultArea[x] = 1; } else { resultArea[x] = 0; } } //% separability criterion //sep = maxsig/sum(((1:nbins)-mu(end)).^2.*P); double sum = 0.0; kkint32 y = 0; muEnd = mu[mu.size () - 1]; for (x = 0, y = 1; x < nbins; ++x, ++y) sum = pow (((double)y - muEnd), 2.0) * P[x]; sep = maxSig / sum; delete srcImage; srcImage = NULL; return result; } if (numClasses == 3) { VectorDouble w0 = w; VectorDouble w2 = FlipLeftRight (CumSum (FlipLeftRight (P))); Matrix w0M ((kkint32)w0.size (), (kkint32)w0.size ()); Matrix w2M ((kkint32)w2.size (), (kkint32)w2.size ()); NdGrid (w0, w2, w0M, w2M); VectorDouble mu0 = DotDiv (mu, w); //mu2 = fliplr(cumsum(fliplr((1:nbins).*P)) ./ cumsum(fliplr(P))); // 1 2 34 4 32 3 4 321 // ---------- P1 ------------- ------ P2 -------- VectorDouble P1 = CumSum (FlipLeftRight (DotMult (BDV (1.0, 1.0, (double)nbins), P))); VectorDouble P2 = CumSum (FlipLeftRight (P)); VectorDouble mu2 = FlipLeftRight (DotDiv (P1, P2)); //[mu0,mu2] = ndgrid(mu0,mu2); Matrix mu0M ((kkint32)mu0.size (), (kkint32)mu0.size ()); Matrix mu2M ((kkint32)mu2.size (), (kkint32)mu2.size ()); NdGrid (mu0, mu2, mu0M, mu2M); //w1 = 1-w0-w2; Matrix w1M = 1.0 - w0M - w2M; //w1(w1<=0) = NaN; MakeNanWhenLesOrEqualZero (w1M); //sigma2B =... // w0.*(mu0-mu(end)).^2 + w2.*(mu2-mu(end)).^2 +... // (w0.*(mu0-mu(end)) + w2.*(mu2-mu(end))).^2./w1; Matrix P1M = (DotMult (w0M, Power ((mu0M - muEnd), 2.0))) + (DotMult (w2M, Power ((mu2M - muEnd), 2.0))); Matrix P2M = DotDiv (Power ((DotMult (w0M, (mu0M - muEnd)) + DotMult (w2M, (mu2M - muEnd))), 2.0), w1M); Matrix sigma2B = P1M + P2M; //sigma2B(isnan(sigma2B)) = 0; % zeroing if k1 >= k2 ZeroOutNaN (sigma2B); //[maxsig,k] = max(sigma2B(:)); % Turns sigma2B into 1D Array then locates largest value and index. // [k1,k2] = ind2sub([nbins nbins],k); % Sets k1 and k2 to the indexes for k mapped into a 2D square matrix that is (nbins x nbins) kkint32 k1, k2; double maxsig = 0.0; sigma2B.FindMaxValue (maxsig, k1, k2); //% segmented image RasterPtr result = new Raster (srcImage->Height (), srcImage->Width (), false); { //IDX = ones(size(srcImage))*3; //IDX(srcImage<=pixval(k1)) = 1; //IDX(srcImage>pixval(k1) & srcImage<=pixval(k2)) = 2; uchar* srcData = srcImage->GreenArea (); uchar* data = result->GreenArea (); double th1 = pixval[k1]; double th2 = pixval[k2]; for (x = 0; x < totPixels; ++x) { if ((!maskArea) || (maskArea[x] > maskTh)) { if (srcData[x] <= th1) data[x] = 1; else if (srcData[x] <= th2) data[x] = 2; else data[x] = 3; } else { data[x] = 0; } } } sep = maxsig / Sum (DotMult (Power (Subt (BDV (1.0, 1.0, (double)nbins), muEnd), 2.0), P)); delete srcImage; srcImage = NULL; return result; } delete srcImage; srcImage = NULL; return NULL; } /* SegmentMaskedImage */
void ClassSummaryList::SaveLLoydsBinsData (const KKStr& fileName, const KKStr& srcDirName, kkint32 lastScanLine, kkint32 baseLLoydsBinSize ) { ofstream o (fileName.Str (), ios::out); if (!o.is_open ()) { log.Level (-1) << endl << endl << endl << "ClassSummaryList::SaveLLoydsBinsData *** Invalid File[" << fileName << "]." << endl << endl; return; } ClassSummaryList::const_iterator idx; o << "// LLoyds Bins Data" << endl << "//" << endl << "// Run Date [" << osGetLocalDateTime () << "]" << endl << "// SrcDir [" << srcDirName << "]" << endl << "// LastScanLin [" << lastScanLine << "]" << endl << "// Base Bin Size [" << baseLLoydsBinSize << "]" << endl << "//" << endl; o << "BinSize" << "\t" << "BinNum" << "\t" << "ScanLines"; kkuint32 numOfBins = NumOfLLoydsBins (); for (idx = begin (); idx != end (); idx++) { ClassSummaryPtr cs = *idx; o << "\t" << cs->ClassName (); } o << endl; VectorInt binSizes = LLoydsBinSizes (); size_t binSizeIndex = 0; for (binSizeIndex = 0; binSizeIndex < binSizes.size (); binSizeIndex++) { kkint32 binSize = binSizes[binSizeIndex]; kkint32 startScanLinNum = 0; kkint32 endScanLineNum = startScanLinNum + binSize - 1; kkuint32 binNum = 0; for (binNum = 0; binNum < numOfBins; binNum++) { o << binSize << "\t" << binNum <<"\t" << startScanLinNum << "-" << endScanLineNum; for (idx = begin (); idx != end (); idx++) { kkint32 lloydsBin = 0; ClassSummaryPtr cs = *idx; LLoydsEntryPtr lloydsEntry = cs->LLoydsEntryByBinSize (binSize); if (lloydsEntry != NULL) lloydsBin = lloydsEntry->LLoydsBin (binNum); o << "\t" << lloydsBin; } startScanLinNum += binSize; endScanLineNum += binSize; o << endl; } } o.close (); } /* SaveLLoydsBinsData */