23 #include "bias_config.h"
25 #include <Base/Image/ImageIO.hh>
26 #include <Base/Image/ImageConvert.hh>
27 #include <MathAlgo/Median1D.hh>
34 template<
class InputStorageType,
class OutputStorageType>
36 :
FilterNToN<InputStorageType,OutputStorageType>()
43 template<
class InputStorageType,
class OutputStorageType>
46 FilterNToN<InputStorageType, OutputStorageType>(other),
47 _MedianSize(other._MedianSize)
52 template<
class InputStorageType,
class OutputStorageType>
57 int comp(
const void *a,
const void *b)
59 if (*(
float*) a < *(
float*) b)
61 else if (*(
float*) a > *(
float*) b)
67 template<
class InputStorageType,
class OutputStorageType>
71 unsigned int halfsizeX = _MedianSize;
72 unsigned int halfsizeY = _secondSize;
76 BIASERR(
"Median() not implemented for more than one channel");
86 bool identimg =
false;
87 int sizeX = 2 * halfsizeX + 1;
88 int sizeY = 2 * halfsizeY + 1;
108 int startx, starty, endx, endy;
111 z =
new float[sizeX * sizeY];
112 unsigned int ULx, ULy, LRx, LRy, width, height;
116 for (
unsigned int j = ULy; j < LRy; j++)
119 for (
unsigned int i = ULx; i < LRx; i++)
122 startx = int(i) - (sizeX - 1) / 2;
123 endx = int(i) + (sizeX - 1) / 2;
124 starty = int(j) - (sizeY - 1) / 2;
125 endy = int(j) + (sizeY - 1) / 2;
130 if (endx >
int(width - 1))
132 if (endy >
int(height - 1))
134 for (
int y = starty; y <= endy; y++)
135 for (
int x = startx; x <= endx; x++)
137 zvalue = (float) srcida[y][x];
138 if (zvalue > _MinValue)
146 qsort(z, found,
sizeof(
float), comp);
147 dstida[j][i] = (OutputStorageType) z[found / 2];
151 dstida[j][i] = (OutputStorageType) 0.0;
164 template<
class InputStorageType,
class OutputStorageType>
168 BIASERR(
"FilterInt makes no sense here, using general Filter interface.");
169 return Filter(src, dst);
172 template<
class InputStorageType,
class OutputStorageType>
176 BIASERR(
"FilterFloat makes no sense here, using general Filter interface.");
177 return Filter(src, dst);
180 template<
class InputStorageType,
class OutputStorageType>
187 BIASERR(
"Median() not implemented for more than one channel");
192 unsigned found, xm, x2m, xp, x2p, ym, y2m, yp, y2p, w, maxwidth, maxheight,
205 memset((
void*) dstida[0], 0,
sizeof(OutputStorageType)
212 for (y = 2; y < maxheight; y++)
214 for (x = 2; x < maxwidth; x++)
216 if ((zvalue = (
float) srcida[y][x]) != 0.0)
228 if ((zvalue = (
float) srcida[y2m][x2m]) > 0.0)
233 if ((zvalue = (
float) srcida[y2m][xm]) > 0.0)
238 if ((zvalue = (
float) srcida[y2m][x]) > 0.0)
243 if ((zvalue = (
float) srcida[y2m][xp]) > 0.0)
248 if ((zvalue = (
float) srcida[y2m][x2p]) > 0.0)
253 if ((zvalue = (
float) srcida[ym][x2m]) > 0.0)
258 if ((zvalue = (
float) srcida[ym][xm]) > 0.0)
263 if ((zvalue = (
float) srcida[ym][x]) > 0.0)
268 if ((zvalue = (
float) srcida[ym][xp]) > 0.0)
273 if ((zvalue = (
float) srcida[ym][x2p]) > 0.0)
278 if ((zvalue = (
float) srcida[y][x2m]) > 0.0)
283 if ((zvalue = (
float) srcida[y][xm]) > 0.0)
289 if ((zvalue = (
float) srcida[y][xp]) > 0.0)
294 if ((zvalue = (
float) srcida[y][x2p]) > 0.0)
299 if ((zvalue = (
float) srcida[yp][x2m]) > 0.0)
304 if ((zvalue = (
float) srcida[yp][xm]) > 0.0)
309 if ((zvalue = (
float) srcida[yp][x]) > 0.0)
314 if ((zvalue = (
float) srcida[yp][xp]) > 0.0)
319 if ((zvalue = (
float) srcida[yp][x2p]) > 0.0)
324 if ((zvalue = (
float) srcida[y2p][x2m]) > 0.0)
329 if ((zvalue = (
float) srcida[y2p][xm]) > 0.0)
334 if ((zvalue = (
float) srcida[y2p][x]) > 0.0)
339 if ((zvalue = (
float) srcida[y2p][xp]) > 0.0)
344 if ((zvalue = (
float) srcida[y2p][x2p]) > 0.0)
352 qsort(z, found,
sizeof(
float), comp);
353 dstida[y][x] = (OutputStorageType) (0.33 * z[(found >> 1) - 1] + 0.34 * z[found >> 1] + 0.33
354 * z[(found >> 1) + 1]);
364 template<
class InputStorageType,
class OutputStorageType>
368 const float& Threshold)
const
373 BIASERR(
"Median() not implemented for more than one channel");
378 unsigned found, xm, x2m, xp, x2p, ym, y2m, yp, y2p, w, maxwidth, maxheight,
391 memset((
void*) dstida[0], 0,
sizeof(OutputStorageType)
398 for (y = 2; y < maxheight; y++)
400 for (x = 2; x < maxwidth; x++)
402 if ((zvalue = (
float) srcida[y][x]) <= Threshold)
413 if ((zvalue = (
float) srcida[y2m][x2m]) > Threshold)
418 if ((zvalue = (
float) srcida[y2m][xm]) > Threshold)
423 if ((zvalue = (
float) srcida[y2m][x]) > Threshold)
428 if ((zvalue = (
float) srcida[y2m][xp]) > Threshold)
433 if ((zvalue = (
float) srcida[y2m][x2p]) > Threshold)
438 if ((zvalue = (
float) srcida[ym][x2m]) > Threshold)
443 if ((zvalue = (
float) srcida[ym][xm]) > Threshold)
448 if ((zvalue = (
float) srcida[ym][x]) > Threshold)
453 if ((zvalue = (
float) srcida[ym][xp]) > Threshold)
458 if ((zvalue = (
float) srcida[ym][x2p]) > Threshold)
463 if ((zvalue = (
float) srcida[y][x2m]) > Threshold)
468 if ((zvalue = (
float) srcida[y][xm]) > Threshold)
474 if ((zvalue = (
float) srcida[y][xp]) > Threshold)
479 if ((zvalue = (
float) srcida[y][x2p]) > Threshold)
484 if ((zvalue = (
float) srcida[yp][x2m]) > Threshold)
489 if ((zvalue = (
float) srcida[yp][xm]) > Threshold)
494 if ((zvalue = (
float) srcida[yp][x]) > Threshold)
499 if ((zvalue = (
float) srcida[yp][xp]) > Threshold)
504 if ((zvalue = (
float) srcida[yp][x2p]) > Threshold)
509 if ((zvalue = (
float) srcida[y2p][x2m]) > Threshold)
514 if ((zvalue = (
float) srcida[y2p][xm]) > Threshold)
519 if ((zvalue = (
float) srcida[y2p][x]) > Threshold)
524 if ((zvalue = (
float) srcida[y2p][xp]) > Threshold)
529 if ((zvalue = (
float) srcida[y2p][x2p]) > Threshold)
538 qsort(z, found,
sizeof(
float), comp);
539 dstida[y][x] = (OutputStorageType) (0.33 * z[(found >> 1) - 1] + 0.34 * z[found >> 1] + 0.33
540 * z[(found >> 1) + 1]);
544 dstida[y][x] = (OutputStorageType) Threshold;
549 dstida[y][x] = (OutputStorageType) zvalue;
557 template<
class InputStorageType,
class OutputStorageType>
565 BIASERR(
"Median() not implemented for more than one channel");
570 unsigned found, xm, xp, ym, yp, w, maxwidth, maxheight, h, x, y;
581 memset((
void*) dstida[0], 0,
sizeof(OutputStorageType)
588 for (y = 1; y < maxheight; y++)
590 for (x = 1; x < maxwidth; x++)
592 if ((zvalue = (
float) srcida[y][x]) <= Threshold)
599 if ((zvalue = (
float) srcida[ym][xm]) > Threshold)
604 if ((zvalue = (
float) srcida[ym][x]) > Threshold)
609 if ((zvalue = (
float) srcida[ym][xp]) > Threshold)
614 if ((zvalue = (
float) srcida[y][xm]) > Threshold)
620 if ((zvalue = (
float) srcida[y][xp]) > Threshold)
625 if ((zvalue = (
float) srcida[yp][xm]) > Threshold)
630 if ((zvalue = (
float) srcida[yp][x]) > Threshold)
635 if ((zvalue = (
float) srcida[yp][xp]) > Threshold)
643 qsort(z, found,
sizeof(
float), comp);
645 dstida[y][x] = (OutputStorageType) (0.33 * z[(found >> 1) - 1] + 0.34 * z[found >> 1] + 0.33
646 * z[(found >> 1) + 1]);
655 dstida[y][x] = (OutputStorageType) zvalue;
662 template<
class InputStorageType,
class OutputStorageType>
666 const float &threshold,
const unsigned &min_support)
const
670 BIASERR(
"Median() not implemented for more than one channel");
675 int found, xm, xp, ym, yp, x, y;
686 const int maxheight = h - 1, maxwidth = w - 1;
690 for (y = 1; y < maxheight; y++)
692 for (x = 1; x < maxwidth; x++)
694 if ((zvalue = (
float) srcida[y][x]) < threshold)
701 if ((zvalue = (
float) srcida[ym][xm]) > threshold)
706 if ((zvalue = (
float) srcida[ym][x]) > threshold)
711 if ((zvalue = (
float) srcida[ym][xp]) > threshold)
716 if ((zvalue = (
float) srcida[y][xm]) > threshold)
722 if ((zvalue = (
float) srcida[y][xp]) > threshold)
727 if ((zvalue = (
float) srcida[yp][xm]) > threshold)
732 if ((zvalue = (
float) srcida[yp][x]) > threshold)
737 if ((zvalue = (
float) srcida[yp][xp]) > threshold)
743 if (found >= (
int) min_support)
745 qsort(z, found,
sizeof(
float), comp);
747 dstida[y][x] = (OutputStorageType) (z[(found >> 1)]);
751 dstida[y][x] = (OutputStorageType) zvalue;
756 dstida[y][x] = (OutputStorageType) zvalue;
763 template<
class InputStorageType,
class OutputStorageType>
770 BIASERR(
"Median() not implemented for more than one channel");
775 int x, y, found, minx, miny, maxx, maxy, xx, yy;
792 for (y = 0; y < h; y++)
794 miny = (y - 1 < 0) ? (0) : (y - 1);
795 maxy = (y + 1 < h) ? (y + 1) : (h - 1);
796 for (x = 0; x < w; x++)
798 minx = (x - 1 < 0) ? (0) : (x - 1);
799 maxx = (x + 1 < w) ? (x + 1) : (w - 1);
802 for (yy = miny; yy <= maxy; yy++)
804 for (xx = minx; xx <= maxx; xx++)
806 if ((zvalue = (
float) srcida[yy][xx]) > threshold)
816 dstida[y][x] = (OutputStorageType) (srcida[y][x]);
820 qsort(z, found,
sizeof(
float), comp);
821 dstida[y][x] = (OutputStorageType) (z[found >> 1]);
829 template<
class InputStorageType,
class OutputStorageType>
833 const float &Threshold)
const
835 unsigned int halfsizeX = _MedianSize;
836 unsigned int halfsizeY = _secondSize;
840 BIASERR(
"No channels found");
845 BIASERR(
"RemoveSaltAndPepper() not implemented for more than two channels");
848 if (channels > 1 && !src.
IsPlanar())
850 BIASERR(
"Image is not planar, Median::FilterRemoveSaltAndPepper can only "
851 <<
"handle planar images with more than one channel\n");
862 bool identimg =
false;
863 int sizeX = 2 * halfsizeX + 1;
864 int sizeY = 2 * halfsizeY + 1;
888 float zvalue_ch1, zvalue_ch2, poi;
889 int startx, starty, endx, endy;
890 unsigned int found, count, output;
891 vector<float> foundvec1, foundvec2;
896 for (
unsigned int j = 0; j < src.
GetHeight(); j++)
898 for (
unsigned int i = 0; i < src.
GetWidth(); i++)
901 poi = (float) src_ida[j][i];
908 startx = int(i) - (sizeX - 1) / 2;
909 endx = int(i) + (sizeX - 1) / 2;
910 starty = int(j) - (sizeY - 1) / 2;
911 endy = int(j) + (sizeY - 1) / 2;
921 for (
int y = starty; y <= endy; y++)
923 for (
int x = startx; x <= endx; x++)
925 zvalue_ch1 = (float) src_ida[y][x];
927 zvalue_ch2 = (float) src_ida[y + imageheight][x];
931 if (zvalue_ch1 > _MinValue)
933 foundvec1.push_back(zvalue_ch1);
935 foundvec2.push_back(zvalue_ch2);
945 float x84_fp1 = med.
GetX84();
946 float median_fp2 = 0.0f;
963 if (poi < (median_fp1 - Threshold * x84_fp1) ||
964 poi > (median_fp1 + Threshold * x84_fp1))
968 dest_ida[starty + _secondSize][startx + _MedianSize]
969 = (OutputStorageType) median_fp1;
971 dest_ida[starty + imageheight + _secondSize][startx + _MedianSize]
972 = (OutputStorageType) median_fp2;
976 dest_ida[starty + _secondSize][startx + _MedianSize]
977 = (OutputStorageType) (src_ida[starty + _secondSize][startx + _MedianSize]);
979 dest_ida[starty + imageheight + _secondSize][startx + _MedianSize]
980 = (OutputStorageType) (src_ida[starty + imageheight + _secondSize][startx + _MedianSize]);
985 dest_ida[j][i] = (OutputStorageType) src_ida[j][i];
987 dest_ida[starty + imageheight + _secondSize][startx + _MedianSize]
988 = (OutputStorageType) (src_ida[starty + imageheight + _secondSize][startx + _MedianSize]);
995 dest_ida[j][i] = (OutputStorageType) src_ida[j][i];
997 dest_ida[j + imageheight][i] = (OutputStorageType) src_ida[j + imageheight][i];
1008 cerr <<
"FilterRemoveSaltAndPepper touched " << count <<
" of "
1014 template<
class InputStorageType,
class OutputStorageType>
1018 if (_secondSize > _MedianSize)
1020 border_x = border_y = _secondSize;
1024 border_x = border_y = _MedianSize;
1028 template<
class InputStorageType,
class OutputStorageType>
1058 Filter(green, greenG);
1059 Filter(blue, blueG);
1062 for (
int i = 0; i < width; i++)
1064 for (
int j = 0; j < height; j++)
1075 template<
class InputStorageType,
class OutputStorageType>
1079 unsigned int px,
unsigned int py,
1082 unsigned int width = src.
GetWidth();
1089 dst.
Init(width, height, channels);
1093 float minSum = FLT_MAX;
1095 int minX = px, minY = py;
1097 if (px >= 0 && px < width && py >= 0 && py < height)
1100 int x1 = max(0, (
int) px - _MedianSize);
1101 int y1 = max(0, (
int) py - _secondSize);
1103 int x2 = min(width - 1, px + _MedianSize);
1104 int y2 = min(height - 1, py + _secondSize);
1106 for (
int x = x1; x <= x2; x++)
1108 for (
int y = y1; y <= y2; y++)
1110 unsigned char ignoreFlag = 0;
1111 if (ignorePixels != NULL)
1116 if (ignoreFlag == 0)
1121 for (
int tmp_x = x1; tmp_x <= x2; tmp_x++)
1124 for (
int tmp_y = y1; tmp_y <= y2; tmp_y++)
1127 if (ignorePixels != NULL)
1133 if (ignoreFlag == 0)
1137 for (
unsigned short ch = 0; ch < channels; ch++)
1143 float diff = pow(fabs(val1 - val2), 2);
1147 sum += sqrt(tmp_sum);
1165 for (
unsigned short ch = 0; ch < channels; ch++)
1167 OutputStorageType val = (OutputStorageType) src.
PixelValue(minX,
1174 BIASERR(
"pixel coordinates "<< px <<
" , "<<py<<
" exceed image range");
1179 template<
class InputStorageType,
class OutputStorageType>
1186 unsigned int width = src.
GetWidth();
1193 dst.
Init(width, height, channels);
1197 #pragma omp parallel for private(x,y)
1198 for (y = 0; y < (int) height; y++)
1200 for (x = 0; x < (int) width; x++)
1202 unsigned char ignoreValue = 0;
1203 if (ignorePixels != NULL)
1205 ignoreValue = ignorePixels->
PixelValue(x, y);
1208 if (ignoreValue == 0)
1210 FilterColorImgVec(src, dst, x, y, ignorePixels);
1217 template<
class InputStorageType,
class OutputStorageType>
1224 int size = width*height;
1226 if (dest.
GetWidth() != (
unsigned int) width || dest.
GetHeight() != (
unsigned int)height ||
1229 dest.
Init(width,height,1);
1232 InputStorageType* source_data = (InputStorageType*) source.
GetImageData();
1233 OutputStorageType* dest_data = (OutputStorageType*) dest.
GetImageData();
1236 vector<InputStorageType*> sort_vector(numberOfThreads);
1237 for(
unsigned int i = 0; i < sort_vector.size(); i++) {
1238 sort_vector[i] =
new InputStorageType[(2*_MedianSize+1)*(2*_secondSize+1)];
1240 #pragma omp parallel for num_threads(numberOfThreads)
1242 #define omp_get_thread_num() 0
1243 vector<InputStorageType*> sort_vector(numberOfThreads);
1244 sort_vector[0] =
new InputStorageType[(2*_MedianSize+1)*(2*_secondSize+1)];
1246 for (
int i = 0; i < size; i++) {
1249 int x = i - y*width;
1251 int start_x = max((
int)0,x - _MedianSize);
1252 int start_y = max((
int)0,y - _secondSize);
1253 int end_x = min(width -1,x + _MedianSize);
1254 int end_y = min(height - 1,y + _secondSize);
1257 int array_width = end_x - start_x + 1;
1258 int array_height = end_y - start_y + 1;
1259 int array_size = array_width* array_height;
1261 unsigned int th_num = omp_get_thread_num();
1263 InputStorageType* sort_array = sort_vector[th_num];
1265 for (
int tmp_x = start_x, array_x = 0; array_x < array_width; tmp_x++, array_x++) {
1266 for (
int tmp_y = start_y, array_y =0; array_y < array_height; tmp_y++, array_y++) {
1267 int index = tmp_y * width + tmp_x;
1268 int array_index = array_y * array_width + array_x;
1269 sort_array[array_index] = source_data[index];
1273 sort(sort_array,sort_array+array_size);
1275 int med = min(array_size / 2+1, array_size - 1);
1277 dest_data[i] = (OutputStorageType) sort_array[med];
1282 for(
unsigned int i = 0; i < sort_vector.size(); i++) {
1283 delete sort_vector[i];
1289 template<
class InputStorageType,
class OutputStorageType>
1294 if (srcs.size() != 3)
1296 BIASERR(
"Number of input images not 3!");
1300 unsigned int height = srcs[0].GetHeight();
1301 unsigned int width = srcs[0].GetWidth();
1303 for (
int i = 0; i < 3; i++)
1307 BIASERR(
"Images not grey!");
1310 if (srcs[i].GetHeight() != height || srcs[i].GetWidth() != width)
1312 BIASERR(
"Image size is not consistent!");
1320 InputStorageType** imData[3];
1325 std::vector<InputStorageType> m;
1327 for (
unsigned int w = 1; w < width - 1; w++)
1329 for (
unsigned int h = 1; h < height - 1; h++)
1331 for (
int i = 0; i < 3; i++)
1333 m.push_back(imData[i][h - 1][w - 1]);
1334 m.push_back(imData[i][h - 1][w - 0]);
1335 m.push_back(imData[i][h - 1][w + 1]);
1336 m.push_back(imData[i][h - 0][w - 1]);
1337 m.push_back(imData[i][h - 0][w - 0]);
1338 m.push_back(imData[i][h - 0][w + 1]);
1339 m.push_back(imData[i][h + 1][w - 1]);
1340 m.push_back(imData[i][h + 1][w - 0]);
1341 m.push_back(imData[i][h + 1][w + 1]);
1344 sort(m.begin(), m.end());
1346 dst.
SetPixel((OutputStorageType) m[13], w, h, 0);
1353 template<
class InputStorageType,
class OutputStorageType>
1357 if (srcs.size() != 3)
1359 BIASERR(
"Number of input images not 3!");
1363 unsigned int height = srcs[0].GetHeight();
1364 unsigned int width = srcs[0].GetWidth();
1366 std::vector<Image<InputStorageType> > ImsRed, ImsGreen, ImsBlue;
1369 for (
int i = 0; i < 3; i++)
1371 if (srcs[i].GetHeight() != height || srcs[i].GetWidth() != width)
1373 BIASERR(
"Image size is not consistent!");
1378 && srcs[i].IsPlanar()))
1394 ImsRed.push_back(red);
1395 ImsGreen.push_back(green);
1396 ImsBlue.push_back(blue);
1403 Filter3x3x3Grey(ImsRed, redG);
1404 Filter3x3x3Grey(ImsGreen, greenG);
1405 Filter3x3x3Grey(ImsBlue, blueG);
1408 for (
unsigned int i = 0; i < width; i++)
1410 for (
unsigned int j = 0; j < height; j++)
1427 #define FILTER_INSTANTIATION_CLASS Median
1428 #include "Filterinst.hh"
void Release()
reimplemented from ImageBase
int SetCorners(unsigned UpperLeftX, unsigned UpperLeftY, unsigned LowerRightX, unsigned LowerRightY)
Sets a rectangular region of interest.
void GetCorners(unsigned &UpperLeftX, unsigned &UpperLeftY, unsigned &LowerRightX, unsigned &LowerRightY) const
Return the region of interest, by saving the coordinates within the variables defined by the paramete...
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
void SetColorModel(EColorModel Model)
unsigned int GetWidth() const
StorageType PixelValue(const unsigned int x, const unsigned int y, const unsigned short int channel=0) const
Returns value of pixel at specific position, using specific channel as offset.
int GetChannel(const ImageBase &source, const unsigned int channel)
copies one specific channel from source to Image can only be called from an planar image...
void Clear(const StorageType value=0)
sets all pixels to zero/value
ROI * GetROI()
Returns a pointer to the roi object.
int StealImage(ImageBase &source)
steals the image data array from source, after releasing the actual image data and sets source image ...
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
color values, 3 channels, order: red,green,blue
base class for simple n->n filter implementations
unsigned int GetHeight() const
bool SamePixelAndChannelCount(const ImageBase &Image) const
checks if data area has same "size" as Image of other type
void SetPixel(const StorageType &value, const unsigned int &x, const unsigned int &y, const unsigned short int channel=0)
Set the value of a given pixel (x,y) in channel to value.
void Init(unsigned int Width, unsigned int Height, unsigned int channels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
calls Init from ImageBase storageType is ignored, just dummy argument
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
enum EColorModel GetColorModel() const
static int Convert(BIAS::ImageBase &source, BIAS::ImageBase &dest, enum BIAS::ImageBase::EColorModel targetColorModel, bool bPlanar=false)
main general conversion function, calls desired specialized functions, always initializes the destIma...
enum EStorageType GetStorageType() const
unsigned long int GetPixelCount() const
returns number of pixels in image
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase