54 for (
kkint32 x = 0; x < totPixels; ++x)
56 if (srcArea[x] == pixelValue)
58 resultArea[x] = label;
78 for (
kkint32 x = 0; x < totPixels; ++x)
80 if ((srcArea[x] == pixelValue) && (maskArea[x] > maskTh))
82 resultArea[x] = label;
88 for (
kkint32 x = 0; x < totPixels; ++x)
89 if (srcArea[x] == pixelValue)
90 resultArea[x] = label;
121 for (kkuint32 x = 0; x < v.size (); ++x)
136 kkuint32 lenMax = (kkuint32)Max (left.size (), right.size ());
137 kkuint32 lenMin = (kkuint32)Min (left.size (), right.size ());
140 for (kkuint32 x = 0; x < lenMin; ++x)
141 r[x] = left[x] * right[x];
152 kkint32 maxNumOfRows = Max (left.NumOfRows (), right.NumOfRows ());
153 kkint32 maxNumOfCols = Max (left.NumOfCols (), right.NumOfCols ());
155 kkint32 minNumOfRows = Min (left.NumOfRows (), right.NumOfRows ());
156 kkint32 minNumOfCols = Min (left.NumOfCols (), right.NumOfCols ());
158 Matrix result
(maxNumOfRows
, maxNumOfCols
);
160 double** leftData = left
.Data ();
161 double** rightData = right
.Data ();
162 double** resultData = result
.Data ();
166 for (r = 0; r < minNumOfRows; ++r)
168 double* leftDataRow = leftData[r];
169 double* rightDataRow = rightData[r];
170 double* resultDataRow = resultData[r];
172 for (c = 0; c < minNumOfCols; ++c)
173 resultDataRow[c] = leftDataRow[c] * rightDataRow[c];
176 for (r = minNumOfRows; r < maxNumOfRows; ++r)
178 double* resultDataRow = resultData[r];
179 for (c = minNumOfCols; c < maxNumOfCols; ++c)
180 resultDataRow[c] = 0.0;
191 kkuint32 lenMax = (kkuint32)Max (left.size (), right.size ());
192 kkuint32 lenMin = (kkuint32)Min (left.size (), right.size ());
195 for (x = 0; x < lenMin; ++x)
197 double rs = right[x];
204 for (x = lenMin; x < lenMax; ++x)
216 kkint32 maxNumOfRows = Max (left.NumOfRows (), right.NumOfRows ());
217 kkint32 maxNumOfCols = Max (left.NumOfCols (), right.NumOfCols ());
219 kkint32 minNumOfRows = Min (left.NumOfRows (), right.NumOfRows ());
220 kkint32 minNumOfCols = Min (left.NumOfCols (), right.NumOfCols ());
222 Matrix result
(maxNumOfRows
, maxNumOfCols
);
224 double** leftData = left
.Data ();
225 double** rightData = right
.Data ();
226 double** resultData = result
.Data ();
230 for (r = 0; r < minNumOfRows; ++r)
232 double* leftDataRow = leftData[r];
233 double* rightDataRow = rightData[r];
234 double* resultDataRow = resultData[r];
236 for (c = 0; c < minNumOfCols; ++c)
237 resultDataRow[c] = leftDataRow[c] / rightDataRow[c];
240 for (r = minNumOfRows; r < maxNumOfRows; ++r)
242 double* resultDataRow = resultData[r];
243 for (c = minNumOfCols; c < maxNumOfCols; ++c)
246 resultDataRow[c] = NaN;
248 else if (rightData[r][c] == 0.0)
249 resultDataRow[c] = NaN;
252 resultDataRow[c] = 0.0;
265 vector<T> r(v.size (), (T)0);
266 reverse_copy (v.begin (), v.end (), r.begin ());
278 kkuint32 len = (kkuint32)left.size ();
281 for (x = 0; x < len; ++x)
284 double z2 = z1 + right;
299 kkuint32 lenMax = (kkuint32)Max (left.size (), right.size ());
300 kkuint32 lenMin = (kkuint32)Min (left.size (), right.size ());
303 for (x = 0; x < lenMin; ++x)
304 r[x] = left[x] - right[x];
306 for (x = lenMin; x < lenMax; ++x)
308 if (x < left.size ())
311 r[x] = 0.0 - right[x];
324 kkuint32 len = (kkuint32)left.size ();
327 for (x = 0; x < len; ++x)
330 double z2 = z1 - right;
345 kkuint32 len = (kkuint32)right.size ();
348 for (x = 0; x < len; ++x)
350 r[x] = left - right[x];
365 kkuint32 len = (kkuint32)left.size ();
368 for (x = 0; x < len; ++x)
371 double z2 = z1 - right;
388 kkuint32 len = right.size ();
390 vector<T> r (len, (T)0);
391 for (x = 0; x < len; ++x)
392 r[x] = left - right[r];
405 for (kkuint32 x = 0; x < left.size (); ++x)
406 result[x] = left[x] * right;
418 for (kkuint32 x = 0; x < right.size (); ++x)
419 result[x] = left * right[x];
432 kkuint32 len = (kkuint32)left.size ();
434 for (x = 0; x < len; ++x)
435 r[x] = pow (left[x], right);
450 double** leftData = left
.Data ();
451 double** resultData = result
.Data ();
454 for (r = 0; r < numOfRows; ++r)
456 double* leftDataRow = leftData[r];
457 double* resultDataRow = resultData[r];
458 for (c = 0; c < numOfCols; ++c)
459 resultDataRow[c] = pow (leftDataRow[c], right);
470 for (
kkuint32 x = 0; x < v.size (); ++x)
472 r[x] = (kkint32)(v[x] + 0.5f);
486 for (x = 0; x < v.size (); ++x)
499 kkuint32 xLen = (kkuint32)x.size ();
500 kkuint32 yLen = (kkuint32)y.size ();
507 for (row = 0; row < xLen; ++row)
509 for (col = 0; col < yLen; ++col)
510 xm[row][col] = x[row];
513 for (row = 0; row < xLen; ++row)
515 for (col = 0; col < yLen; ++col)
516 ym[row][col] = y[col];
528 double* dataRow = data[r];
531 if (dataRow[c] <= 0.0)
546 for (kkint32 i = start; i <= end; ++i)
547 subSet.push_back (P[i]);
560 for (kkint32 i = start; i <= end; ++i)
570 for (x = 0; x < v.size (); ++x)
578 bool _isnan (
double& d)
580 return !(isnan (d) == 0);
593 for (r = 0; r < numOfRows; ++r)
595 double* dataRow = data[r];
596 for (c = 0; c < numOfCols; ++c)
612 double inc = (end - start) / (
double)(numPoints - 1);
614 while (result.size () < (kkuint32)numPoints)
616 result.push_back (start);
635 for (x = 0, y = 1; x < nbins; ++x, ++y)
639 double sigma2T = 0.0;
640 for (x = 0, y = 1; x < nbins; ++x, ++y)
641 sigma2T += (pow ((y - muT), 2.0) * P[x]);
644 for (x = 0; x < (kkint32)k.size (); ++x)
645 k[x] = floor (k[x] * (nbins - 1) + 1.0 + 0.5);
648 sort (k.begin (), k.end ());
651 if ((k[0] < 1.0) || (k[k.size () - 1] > nbins))
655 k.insert (k.begin (), 0.0);
659 double sigma2B = 0.0;
662 for (
kkint32 j = 0; j < numClasses; ++j)
665 double wj = SumSubSet (P, (kkint32)(k[j] + 1), (kkint32)k[j + 1]);
672 kkint32 idxStart = (kkint32)(k[j] + 1);
673 kkint32 idxEnd = (kkint32)(k[j + 1]);
675 for (kkint32 i = idxStart; i <= idxEnd; ++i)
676 muj += (i * P[i] / wj);
679 sigma2B = sigma2B + wj * pow ((muj - muT), 2.0);
683 return 1.0 - sigma2B / sigma2T;
761 else if ((numClasses < 1) || (numClasses > 255))
763 log.Level (-1) <<
"SegmentorOTSU::SegmentImage ***ERROR*** 'numClasses must be a between 1 and 255 !'" << endl;
795 uchar pixelMin = 255;
798 for (pixelIdx = 1; pixelIdx < totPixels; ++pixelIdx)
800 if (greenArea[pixelIdx] < 1)
805 if (greenArea[pixelIdx] < pixelMin)
806 pixelMin = greenArea[pixelIdx];
808 if (greenArea[pixelIdx] > pixelMax)
809 pixelMax = greenArea[pixelIdx];
814 for (pixelIdx = 0; pixelIdx < totPixels; ++pixelIdx)
825 counts[greenArea[pixelIdx]]++;
828 for (x = 1; x < (kkint32)counts.size (); ++x)
833 unICounts.push_back (counts[x]);
838 kkint32 nbins = (kkint32)unI.size ();
840 if (nbins <= numClasses)
846 for (x = 0; x < nbins; ++x)
848 LabelRaster (result, unI[x], x, srcImage);
865 for (x = 0; x < (kkint32)histo.size (); ++x)
866 P[x] = (
double)(histo[x]) / (
double)pixelsCounted;
875 for (x = 1; x < (kkint32)P.size (); ++x)
876 w[x] = w[x - 1] + P[x];
881 for (x = 1; x < (kkint32)P.size (); ++x)
882 mu[x] = mu[x - 1] + ((x + 1) * P[x]);
883 double muEnd = mu[mu.size () - 1];
893 VectorDouble wSubSet = SubSet (w, 1, (kkint32)w.size () - 2);
894 VectorDouble muSubSet = SubSet (mu, 1, (kkint32)mu.size () - 2);
896 VectorDouble P1 = Power (Subt (muEnd * wSubSet, muSubSet), 2.0);
897 VectorDouble P2 = DotDiv (wSubSet, Subt (1.0, wSubSet));
899 double maxSig = sigma2B[0];
901 for (x = 1; x < (kkint32)sigma2B.size (); ++x)
903 if (sigma2B[x] > maxSig)
916 threshold1 = pixval[k + 1];
924 for (x = 0; x < totPixels; ++x)
926 if (srcArea[x] > threshold1)
937 if ((threshold1 < 1) || (numClass2Pixs >100))
946 muEnd = mu[mu.size () - 1];
947 for (x = 0, y = 1; x < nbins; ++x, ++y)
948 sum = pow (((
double)y - muEnd), 2.0) * P[x];
961 VectorDouble w2 = FlipLeftRight (CumSum (FlipLeftRight (P)));
965 Matrix w0M ((kkint32)w0.size (), (kkint32)w0.size ());
966 Matrix w2M ((kkint32)w2.size (), (kkint32)w2.size ());
967 NdGrid (w0, w2, w0M, w2M);
976 VectorDouble P1 = CumSum (FlipLeftRight (DotMult (BDV (1.0, 1.0, (
double)nbins), P)));
982 Matrix mu0M ((kkint32)mu0.size (), (kkint32)mu0.size ());
983 Matrix mu2M ((kkint32)mu2.size (), (kkint32)mu2.size ());
984 NdGrid (mu0, mu2, mu0M, mu2M);
990 MakeNanWhenLesOrEqualZero (w1M);
995 Matrix P1M = (DotMult (w0M, Power ((mu0M
- muEnd), 2.0)))
+ (DotMult (w2M, Power ((mu2M
- muEnd), 2.0)));
996 Matrix P2M = DotDiv (Power ((DotMult (w0M, (mu0M
- muEnd))
+ DotMult (w2M, (mu2M
- muEnd))), 2.0), w1M);
1001 ZeroOutNaN (sigma2B);
1006 double maxsig = 0.0;
1017 threshold1 = pixval[k1];
1018 threshold2 = pixval[k2];
1019 for (x = 0; x < totPixels; ++x)
1021 if (srcData[x] <= threshold1)
1023 else if (srcData[x] <= threshold2)
1036 sep = maxsig / Sum (DotMult (Power (Subt (BDV (1.0, 1.0, (
double)nbins), muEnd), 2.0), P));
1095 uchar* maskArea = NULL;
1103 if (numClasses == 1)
1108 else if ((numClasses < 1) || (numClasses > 255))
1110 log.Level (-1) << endl << endl
1111 <<
"SegmentorOTSU::SegmentMaskedImage ***ERROR*** 'numClasses must be a between 1 and 255 !'" << endl
1130 kkint32 totMaskPixels = totPixels;
1140 uchar pixelMin = greenArea[0];
1141 uchar pixelMax = greenArea[0];
1143 for (pixelIdx = 1; pixelIdx < totPixels; ++pixelIdx)
1145 if ((!mask) || (maskArea[pixelIdx] > maskTh))
1147 if (greenArea[pixelIdx] < pixelMin)
1148 pixelMin = greenArea[pixelIdx];
1150 if (greenArea[pixelIdx] > pixelMax)
1151 pixelMax = greenArea[pixelIdx];
1158 for (pixelIdx = 0; pixelIdx < totPixels; ++pixelIdx)
1160 if ((!mask) || (maskArea[pixelIdx] > maskTh))
1161 counts[greenArea[pixelIdx]]++;
1164 for (x = 0; x < (kkint32)counts.size (); ++x)
1169 unICounts.push_back (counts[x]);
1174 kkint32 nbins = (kkint32)unI.size ();
1176 if (nbins <= numClasses)
1179 for (x = 0; x < nbins; ++x)
1181 LabelRaster (result, mask, unI[x], x, srcImage);
1193 for (x = 0; x < (kkint32)histo.size (); ++x)
1194 P[x] = (
double)(histo[x]) / (
double)totMaskPixels;
1202 for (x = 1; x < (kkint32)P.size (); ++x)
1203 w[x] = w[x - 1] + P[x];
1208 for (x = 1; x < (kkint32)P.size (); ++x)
1209 mu[x] = mu[x - 1] + ((x + 1) * P[x]);
1210 double muEnd = mu[mu.size () - 1];
1213 if (numClasses == 2)
1220 VectorDouble wSubSet = SubSet (w, 1, (kkint32)w.size () - 2);
1221 VectorDouble muSubSet = SubSet (mu, 1, (kkint32)mu.size () - 2);
1223 VectorDouble P1 = Power (Subt (muEnd * wSubSet, muSubSet), 2.0);
1224 VectorDouble P2 = DotDiv (wSubSet, Subt (1.0, wSubSet));
1226 double maxSig = sigma2B[0];
1228 for (x = 1; x < (kkint32)sigma2B.size (); ++x)
1230 if (sigma2B[x] > maxSig)
1232 maxSig = sigma2B[x];
1243 kkint32 threshold = pixval[k + 1];
1247 for (x = 0; x < totPixels; ++x)
1249 if ((!maskArea) || (maskArea[x] > maskTh))
1251 if (srcArea[x] > threshold)
1266 muEnd = mu[mu.size () - 1];
1267 for (x = 0, y = 1; x < nbins; ++x, ++y)
1268 sum = pow (((
double)y - muEnd), 2.0) * P[x];
1276 if (numClasses == 3)
1279 VectorDouble w2 = FlipLeftRight (CumSum (FlipLeftRight (P)));
1281 Matrix w0M ((kkint32)w0.size (), (kkint32)w0.size ());
1282 Matrix w2M ((kkint32)w2.size (), (kkint32)w2.size ());
1283 NdGrid (w0, w2, w0M, w2M);
1290 VectorDouble P1 = CumSum (FlipLeftRight (DotMult (BDV (1.0, 1.0, (
double)nbins), P)));
1295 Matrix mu0M ((kkint32)mu0.size (), (kkint32)mu0.size ());
1296 Matrix mu2M ((kkint32)mu2.size (), (kkint32)mu2.size ());
1297 NdGrid (mu0, mu2, mu0M, mu2M);
1303 MakeNanWhenLesOrEqualZero (w1M);
1308 Matrix P1M = (DotMult (w0M, Power ((mu0M
- muEnd), 2.0)))
+ (DotMult (w2M, Power ((mu2M
- muEnd), 2.0)));
1309 Matrix P2M = DotDiv (Power ((DotMult (w0M, (mu0M
- muEnd))
+ DotMult (w2M, (mu2M
- muEnd))), 2.0), w1M);
1313 ZeroOutNaN (sigma2B);
1318 double maxsig = 0.0;
1329 double th1 = pixval[k1];
1330 double th2 = pixval[k2];
1331 for (x = 0; x < totPixels; ++x)
1333 if ((!maskArea) || (maskArea[x] > maskTh))
1335 if (srcData[x] <= th1)
1337 else if (srcData[x] <= th2)
1349 sep = maxsig / Sum (DotMult (Power (Subt (BDV (1.0, 1.0, (
double)nbins), muEnd), 2.0), P));
1364 const RasterPtr segmentedImage,
1365 uchar segmentedClass
1378 bool origImageColor = origImage
->Color ();
1382 for (
kkuint32 x = 0; x < totalPixels; ++x)
1384 if (mask[x] == segmentedClass)
1386 totalGreen += origGreen[x];
1389 totalRed += origRed [x];
1390 totalBlue += origBlue [x];
1395 totalGreen = (
uchar)(0.5 + (
double)totalGreen / (
double)totalPixels);
1398 totalRed = (
uchar)(0.5 + (
double)totalRed / (
double)totalPixels);
1399 totalBlue = (
uchar)(0.5 + (
double)totalBlue / (
double)totalPixels);
1408 const RasterPtr segmentedImage,
1417 uchar largestClass = 2;
1425 bool origImageColor = origImage
->Color ();
1429 uchar classValue = 0;
1431 for (
kkuint32 x = 0; x < totalPixels; ++x)
1433 classValue = mask[x];
1434 while (classValue > largestClass)
1436 totalReds.push_back (0);
1437 totalGreens.push_back (0);
1438 totalBlues.push_back (0);
1442 totalGreens[classValue] += origGreen[x];
1445 totalReds[classValue] += origRed [x];
1446 totalBlues[classValue] += origBlue[x];
1450 VectorFloat distFromTarget (largestClass + 1, 0.0f);
1452 double closestDistFound = 99999999.99;
1453 uchar closestClass = 255;
1455 for (
uint x = 1; x <= largestClass; ++x)
1457 double avgRed = (
double)totalReds [x] / (
double)totalPixels;
1458 double avgGreen = (
double)totalGreens[x] / (
double)totalPixels;
1459 double avgBlue = (
double)totalBlues [x] / (
double)totalPixels;
1461 double deltaRed = fabs (targetColor.r - avgRed);
1462 double deltaGreen = fabs (targetColor.g - avgGreen);
1463 double deltaBlue = fabs (targetColor.b - avgBlue);
1464 double distToTarget = sqrt (deltaRed * deltaRed + deltaGreen * deltaGreen + deltaBlue * deltaBlue);
1466 if (distToTarget < closestDistFound)
1468 closestDistFound = distToTarget;
1473 return closestClass;
std::vector< kkuint32 > VectorUint32
Vector of unsigned 32 bit integers.
bool IsNaN(const double &d)
kkint32 NumOfRows() const
RasterPtr CreateGrayScaleKLT() const
Creates a image using a KLT Transform with the goal of weighting in favor the color channels with gre...
Matrix operator-(double right)
Matrix(kkint32 _numOfRows, kkint32 _numOfCols)
std::vector< int > VectorInt
PixelValue ClassAverageRGB(const RasterPtr origImage, const RasterPtr segmentedImage, uchar segmentedClass)
Will compute the average RGB values of the region indicated by the segmented image.
A class that is used by to represent a single image in memory.
Supports two dimensional matrices.
SegmentorOTSU(RunLog &_log)
uchar GetClassClosestToTargetColor(const RasterPtr origImage, const RasterPtr segmentedImage, const PixelValue &targetColor)
Determines which class in the segmented image is closet in RGB color space to the specified target co...
unsigned int uint
Unsigned integer.
unsigned __int32 kkuint32
kkint32 NumOfCols() const
VectorDouble operator-(const VectorDouble &left, double right)
PixelValue(uchar _r, uchar _g, uchar _b)
Constructs a 'PixelValue' instance using the provided values for the color components.
std::vector< float > VectorFloat
void FindMaxValue(double &maxVal, kkint32 &row, kkint32 &col)
Locates the maximum value in a matrix along with the row and column that is located.
VectorDouble operator*(const VectorDouble &left, double right)
Matrix operator+(const Matrix &right)
unsigned char uchar
Unsigned character.
uchar BackgroundPixelTH() const
std::vector< kkint32 > VectorInt32
Vector of signed 32 bit integers.
vector< T > operator-(T left, const vector< T > &right)
kkint32 TotPixels() const
kkint32 TotalBackgroundPixels() const
RasterPtr SegmentImage(RasterPtr srcImage, kkint32 numClasses, double &sep)
Segments image into 'numClasses'.
Raster(kkint32 _height, kkint32 _width, bool _color)
Constructs a blank image with given dimensions.
uchar * GreenArea() const
Matrix operator-(const Matrix &right)
VectorDouble operator*(double left, const VectorDouble &right)
Used for logging messages.
void ReSize(kkint32 _numOfRows, kkint32 _numOfCols)
Raster(const Raster &_raster)
Copy Constructor.
Matrix operator-(double left, const Matrix &right)
RasterPtr CreateGrayScaleKLTOnMaskedArea(const Raster &mask) const
Same as 'CreateKLT' except it will only take into account pixels specified by the 'mask' image...
double **const Data() const
Used by the Raster Class to represent the contents of one pixel.
std::vector< double > VectorDouble
Vector of doubles.
RasterPtr SegmentMaskedImage(RasterPtr srcImage, RasterPtr mask, kkint32 numClasses, double &sep)
Segments image into 'numClasses' taking into account only pixels indicated by 'mask' image...