badpixels code: further cleanups
This commit is contained in:
@@ -26,7 +26,7 @@ namespace rtengine
|
|||||||
{
|
{
|
||||||
|
|
||||||
/* interpolateBadPixelsBayer: correct raw pixels looking at the bitmap
|
/* interpolateBadPixelsBayer: correct raw pixels looking at the bitmap
|
||||||
* takes into consideration if there are multiple bad pixels in the neighbourhood
|
* takes into consideration if there are multiple bad pixels in the neighborhood
|
||||||
*/
|
*/
|
||||||
int RawImageSource::interpolateBadPixelsBayer(const PixelsMap &bitmapBads, array2D<float> &rawData)
|
int RawImageSource::interpolateBadPixelsBayer(const PixelsMap &bitmapBads, array2D<float> &rawData)
|
||||||
{
|
{
|
||||||
@@ -37,8 +37,8 @@ int RawImageSource::interpolateBadPixelsBayer(const PixelsMap &bitmapBads, array
|
|||||||
#pragma omp parallel for reduction(+:counter) schedule(dynamic,16)
|
#pragma omp parallel for reduction(+:counter) schedule(dynamic,16)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(int row = 2; row < H - 2; ++row) {
|
for (int row = 2; row < H - 2; ++row) {
|
||||||
for(int col = 2; col < W - 2; ++col) {
|
for (int col = 2; col < W - 2; ++col) {
|
||||||
const int sk = bitmapBads.skipIfZero(col, row); //optimization for a stripe all zero
|
const int sk = bitmapBads.skipIfZero(col, row); //optimization for a stripe all zero
|
||||||
|
|
||||||
if (sk) {
|
if (sk) {
|
||||||
@@ -54,8 +54,8 @@ int RawImageSource::interpolateBadPixelsBayer(const PixelsMap &bitmapBads, array
|
|||||||
|
|
||||||
// diagonal interpolation
|
// diagonal interpolation
|
||||||
if (FC(row, col) == 1) {
|
if (FC(row, col) == 1) {
|
||||||
// green channel. We can use closer pixels than for red or blue channel. Distance to centre pixel is sqrt(2) => weighting is 0.70710678
|
// green channel. We can use closer pixels than for red or blue channel. Distance to center pixel is sqrt(2) => weighting is 0.70710678
|
||||||
// For green channel following pixels will be used for interpolation. Pixel to be interpolated is in centre.
|
// For green channel following pixels will be used for interpolation. Pixel to be interpolated is in center.
|
||||||
// 1 means that pixel is used in this step, if itself and his counterpart are not marked bad
|
// 1 means that pixel is used in this step, if itself and his counterpart are not marked bad
|
||||||
// 0 0 0 0 0
|
// 0 0 0 0 0
|
||||||
// 0 1 0 1 0
|
// 0 1 0 1 0
|
||||||
@@ -72,8 +72,8 @@ int RawImageSource::interpolateBadPixelsBayer(const PixelsMap &bitmapBads, array
|
|||||||
norm += dirwt;
|
norm += dirwt;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// red and blue channel. Distance to centre pixel is sqrt(8) => weighting is 0.35355339
|
// red and blue channel. Distance to center pixel is sqrt(8) => weighting is 0.35355339
|
||||||
// For red and blue channel following pixels will be used for interpolation. Pixel to be interpolated is in centre.
|
// For red and blue channel following pixels will be used for interpolation. Pixel to be interpolated is in center.
|
||||||
// 1 means that pixel is used in this step, if itself and his counterpart are not marked bad
|
// 1 means that pixel is used in this step, if itself and his counterpart are not marked bad
|
||||||
// 1 0 0 0 1
|
// 1 0 0 0 1
|
||||||
// 0 0 0 0 0
|
// 0 0 0 0 0
|
||||||
@@ -91,8 +91,8 @@ int RawImageSource::interpolateBadPixelsBayer(const PixelsMap &bitmapBads, array
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// channel independent. Distance to centre pixel is 2 => weighting is 0.5
|
// channel independent. Distance to center pixel is 2 => weighting is 0.5
|
||||||
// Additionally for all channel following pixels will be used for interpolation. Pixel to be interpolated is in centre.
|
// Additionally for all channel following pixels will be used for interpolation. Pixel to be interpolated is in center.
|
||||||
// 1 means that pixel is used in this step, if itself and his counterpart are not marked bad
|
// 1 means that pixel is used in this step, if itself and his counterpart are not marked bad
|
||||||
// 0 0 1 0 0
|
// 0 0 1 0 0
|
||||||
// 0 0 0 0 0
|
// 0 0 0 0 0
|
||||||
@@ -143,10 +143,10 @@ int RawImageSource::interpolateBadPixelsBayer(const PixelsMap &bitmapBads, array
|
|||||||
return counter; // Number of interpolated pixels.
|
return counter; // Number of interpolated pixels.
|
||||||
}
|
}
|
||||||
|
|
||||||
/* interpolateBadPixelsNColours: correct raw pixels looking at the bitmap
|
/* interpolateBadPixelsNcolors: correct raw pixels looking at the bitmap
|
||||||
* takes into consideration if there are multiple bad pixels in the neighbourhood
|
* takes into consideration if there are multiple bad pixels in the neighborhood
|
||||||
*/
|
*/
|
||||||
int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, const int colours)
|
int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, const int colors)
|
||||||
{
|
{
|
||||||
constexpr float eps = 1.f;
|
constexpr float eps = 1.f;
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
@@ -168,8 +168,8 @@ int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, co
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float wtdsum[colours] = {};
|
float wtdsum[colors] = {};
|
||||||
float norm[colours] = {};
|
float norm[colors] = {};
|
||||||
|
|
||||||
// diagonal interpolation
|
// diagonal interpolation
|
||||||
for (int dx = -1; dx <= 1; dx += 2) {
|
for (int dx = -1; dx <= 1; dx += 2) {
|
||||||
@@ -177,40 +177,40 @@ int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, co
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int c = 0; c < colours; ++c) {
|
for (int c = 0; c < colors; ++c) {
|
||||||
const float dirwt = 0.70710678f / (fabsf(rawData[row - 1][(col + dx) * colours + c] - rawData[row + 1][(col - dx) * colours + c]) + eps);
|
const float dirwt = 0.70710678f / (fabsf(rawData[row - 1][(col + dx) * colors + c] - rawData[row + 1][(col - dx) * colors + c]) + eps);
|
||||||
wtdsum[c] += dirwt * (rawData[row - 1][(col + dx) * colours + c] + rawData[row + 1][(col - dx) * colours + c]);
|
wtdsum[c] += dirwt * (rawData[row - 1][(col + dx) * colors + c] + rawData[row + 1][(col - dx) * colors + c]);
|
||||||
norm[c] += dirwt;
|
norm[c] += dirwt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// horizontal interpolation
|
// horizontal interpolation
|
||||||
if (!(bitmapBads.get(col - 1, row) || bitmapBads.get(col + 1, row))) {
|
if (!(bitmapBads.get(col - 1, row) || bitmapBads.get(col + 1, row))) {
|
||||||
for (int c = 0; c < colours; ++c) {
|
for (int c = 0; c < colors; ++c) {
|
||||||
const float dirwt = 1.f / (fabsf(rawData[row][(col - 1) * colours + c] - rawData[row][(col + 1) * colours + c]) + eps);
|
const float dirwt = 1.f / (fabsf(rawData[row][(col - 1) * colors + c] - rawData[row][(col + 1) * colors + c]) + eps);
|
||||||
wtdsum[c] += dirwt * (rawData[row][(col - 1) * colours + c] + rawData[row][(col + 1) * colours + c]);
|
wtdsum[c] += dirwt * (rawData[row][(col - 1) * colors + c] + rawData[row][(col + 1) * colors + c]);
|
||||||
norm[c] += dirwt;
|
norm[c] += dirwt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// vertical interpolation
|
// vertical interpolation
|
||||||
if (!(bitmapBads.get(col, row - 1) || bitmapBads.get(col, row + 1))) {
|
if (!(bitmapBads.get(col, row - 1) || bitmapBads.get(col, row + 1))) {
|
||||||
for (int c = 0; c < colours; ++c) {
|
for (int c = 0; c < colors; ++c) {
|
||||||
const float dirwt = 1.f / (fabsf(rawData[row - 1][col * colours + c] - rawData[row + 1][col * colours + c]) + eps);
|
const float dirwt = 1.f / (fabsf(rawData[row - 1][col * colors + c] - rawData[row + 1][col * colors + c]) + eps);
|
||||||
wtdsum[c] += dirwt * (rawData[row - 1][col * colours + c] + rawData[row + 1][col * colours + c]);
|
wtdsum[c] += dirwt * (rawData[row - 1][col * colors + c] + rawData[row + 1][col * colors + c]);
|
||||||
norm[c] += dirwt;
|
norm[c] += dirwt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LIKELY(norm[0] > 0.f)) { // This means, we found at least one pair of valid pixels in the steps above, likelihood of this case is about 99.999%
|
if (LIKELY(norm[0] > 0.f)) { // This means, we found at least one pair of valid pixels in the steps above, likelihood of this case is about 99.999%
|
||||||
for (int c = 0; c < colours; ++c) {
|
for (int c = 0; c < colors; ++c) {
|
||||||
rawData[row][col * colours + c] = wtdsum[c] / (2.f * norm[c]); //gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps
|
rawData[row][col * colors + c] = wtdsum[c] / (2.f * norm[c]); //gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps
|
||||||
}
|
}
|
||||||
|
|
||||||
counter++;
|
counter++;
|
||||||
} else { //backup plan -- simple average. Same method for all channels. We could improve this, but it's really unlikely that this case happens
|
} else { //backup plan -- simple average. Same method for all channels. We could improve this, but it's really unlikely that this case happens
|
||||||
int tot = 0;
|
int tot = 0;
|
||||||
float sum[colours] = {};
|
float sum[colors] = {};
|
||||||
|
|
||||||
for (int dy = -2; dy <= 2; dy += 2) {
|
for (int dy = -2; dy <= 2; dy += 2) {
|
||||||
for (int dx = -2; dx <= 2; dx += 2) {
|
for (int dx = -2; dx <= 2; dx += 2) {
|
||||||
@@ -218,8 +218,8 @@ int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, co
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int c = 0; c < colours; ++c) {
|
for (int c = 0; c < colors; ++c) {
|
||||||
sum[c] += rawData[row + dy][(col + dx) * colours + c];
|
sum[c] += rawData[row + dy][(col + dx) * colors + c];
|
||||||
}
|
}
|
||||||
|
|
||||||
tot++;
|
tot++;
|
||||||
@@ -227,8 +227,8 @@ int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, co
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tot > 0) {
|
if (tot > 0) {
|
||||||
for (int c = 0; c < colours; ++c) {
|
for (int c = 0; c < colors; ++c) {
|
||||||
rawData[row][col * colours + c] = sum[c] / tot;
|
rawData[row][col * colors + c] = sum[c] / tot;
|
||||||
}
|
}
|
||||||
|
|
||||||
counter ++;
|
counter ++;
|
||||||
@@ -241,7 +241,7 @@ int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, co
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* interpolateBadPixelsXtrans: correct raw pixels looking at the bitmap
|
/* interpolateBadPixelsXtrans: correct raw pixels looking at the bitmap
|
||||||
* takes into consideration if there are multiple bad pixels in the neighbourhood
|
* takes into consideration if there are multiple bad pixels in the neighborhood
|
||||||
*/
|
*/
|
||||||
int RawImageSource::interpolateBadPixelsXtrans(const PixelsMap &bitmapBads)
|
int RawImageSource::interpolateBadPixelsXtrans(const PixelsMap &bitmapBads)
|
||||||
{
|
{
|
||||||
@@ -266,15 +266,15 @@ int RawImageSource::interpolateBadPixelsXtrans(const PixelsMap &bitmapBads)
|
|||||||
}
|
}
|
||||||
|
|
||||||
float wtdsum = 0.f, norm = 0.f;
|
float wtdsum = 0.f, norm = 0.f;
|
||||||
unsigned int pixelColor = ri->XTRANSFC(row, col);
|
const unsigned int pixelColor = ri->XTRANSFC(row, col);
|
||||||
|
|
||||||
if (pixelColor == 1) {
|
if (pixelColor == 1) {
|
||||||
// green channel. A green pixel can either be a solitary green pixel or a member of a 2x2 square of green pixels
|
// green channel. A green pixel can either be a solitary green pixel or a member of a 2x2 square of green pixels
|
||||||
if (ri->XTRANSFC(row, col - 1) == ri->XTRANSFC(row, col + 1)) {
|
if (ri->XTRANSFC(row, col - 1) == ri->XTRANSFC(row, col + 1)) {
|
||||||
// If left and right neighbour have same colour, then this is a solitary green pixel
|
// If left and right neighbor have same color, then this is a solitary green pixel
|
||||||
// For these the following pixels will be used for interpolation. Pixel to be interpolated is in centre and marked with a P.
|
// For these the following pixels will be used for interpolation. Pixel to be interpolated is in center and marked with a P.
|
||||||
// Pairs of pixels used in this step are numbered. A pair will be used if none of the pixels of the pair is marked bad
|
// Pairs of pixels used in this step are numbered. A pair will be used if none of the pixels of the pair is marked bad
|
||||||
// 0 means, the pixel has a different colour and will not be used
|
// 0 means, the pixel has a different color and will not be used
|
||||||
// 0 1 0 2 0
|
// 0 1 0 2 0
|
||||||
// 3 5 0 6 4
|
// 3 5 0 6 4
|
||||||
// 0 0 P 0 0
|
// 0 0 P 0 0
|
||||||
@@ -313,7 +313,7 @@ int RawImageSource::interpolateBadPixelsXtrans(const PixelsMap &bitmapBads)
|
|||||||
// this is a member of a 2x2 square of green pixels
|
// this is a member of a 2x2 square of green pixels
|
||||||
// For these the following pixels will be used for interpolation. Pixel to be interpolated is at position P in the example.
|
// For these the following pixels will be used for interpolation. Pixel to be interpolated is at position P in the example.
|
||||||
// Pairs of pixels used in this step are numbered. A pair will be used if none of the pixels of the pair is marked bad
|
// Pairs of pixels used in this step are numbered. A pair will be used if none of the pixels of the pair is marked bad
|
||||||
// 0 means, the pixel has a different colour and will not be used
|
// 0 means, the pixel has a different color and will not be used
|
||||||
// 1 0 0 3
|
// 1 0 0 3
|
||||||
// 0 P 2 0
|
// 0 P 2 0
|
||||||
// 0 2 1 0
|
// 0 2 1 0
|
||||||
@@ -352,9 +352,9 @@ int RawImageSource::interpolateBadPixelsXtrans(const PixelsMap &bitmapBads)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// red and blue channel.
|
// red and blue channel.
|
||||||
// Each red or blue pixel has exactly one neighbour of same colour in distance 2 and four neighbours of same colour which can be reached by a move of a knight in chess.
|
// Each red or blue pixel has exactly one neighbor of same color in distance 2 and four neighbors of same color which can be reached by a move of a knight in chess.
|
||||||
// For the distance 2 pixel (marked with an X) we generate a virtual counterpart (marked with a V)
|
// For the distance 2 pixel (marked with an X) we generate a virtual counterpart (marked with a V)
|
||||||
// For red and blue channel following pixels will be used for interpolation. Pixel to be interpolated is in centre and marked with a P.
|
// For red and blue channel following pixels will be used for interpolation. Pixel to be interpolated is in center and marked with a P.
|
||||||
// Pairs of pixels used in this step are numbered except for distance 2 pixels which are marked X and V. A pair will be used if none of the pixels of the pair is marked bad
|
// Pairs of pixels used in this step are numbered except for distance 2 pixels which are marked X and V. A pair will be used if none of the pixels of the pair is marked bad
|
||||||
// 0 1 0 0 0 0 0 X 0 0 remaining cases are symmetric
|
// 0 1 0 0 0 0 0 X 0 0 remaining cases are symmetric
|
||||||
// 0 0 0 0 2 1 0 0 0 2
|
// 0 0 0 0 2 1 0 0 0 2
|
||||||
@@ -362,9 +362,9 @@ int RawImageSource::interpolateBadPixelsXtrans(const PixelsMap &bitmapBads)
|
|||||||
// 0 0 0 0 1 0 0 0 0 0
|
// 0 0 0 0 1 0 0 0 0 0
|
||||||
// 0 2 0 0 0 0 2 V 1 0
|
// 0 2 0 0 0 0 2 V 1 0
|
||||||
|
|
||||||
// Find two knight moves landing on a pixel of same colour as the pixel to be interpolated.
|
// Find two knight moves landing on a pixel of same color as the pixel to be interpolated.
|
||||||
// If we look at first and last row of 5x5 square, we will find exactly two knight pixels.
|
// If we look at first and last row of 5x5 square, we will find exactly two knight pixels.
|
||||||
// Additionally we know that the column of this pixel has 1 or -1 horizontal distance to the centre pixel
|
// Additionally we know that the column of this pixel has 1 or -1 horizontal distance to the center pixel
|
||||||
// When we find a knight pixel, we get its counterpart, which has distance (+-3,+-3), where the signs of distance depend on the corner of the found knight pixel.
|
// When we find a knight pixel, we get its counterpart, which has distance (+-3,+-3), where the signs of distance depend on the corner of the found knight pixel.
|
||||||
// These pixels are marked 1 or 2 in above examples. Distance to P is sqrt(5) => weighting is 0.44721359f
|
// These pixels are marked 1 or 2 in above examples. Distance to P is sqrt(5) => weighting is 0.44721359f
|
||||||
// The following loop simply scans the four possible places. To keep things simple, it does not stop after finding two knight pixels, because it will not find more than two
|
// The following loop simply scans the four possible places. To keep things simple, it does not stop after finding two knight pixels, because it will not find more than two
|
||||||
@@ -380,12 +380,12 @@ int RawImageSource::interpolateBadPixelsXtrans(const PixelsMap &bitmapBads)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now scan for the pixel of same colour in distance 2 in each direction (marked with an X in above examples).
|
// now scan for the pixel of same color in distance 2 in each direction (marked with an X in above examples).
|
||||||
bool distance2PixelFound = false;
|
bool distance2PixelFound = false;
|
||||||
int dx, dy;
|
int dx, dy;
|
||||||
|
|
||||||
// check horizontal
|
// check horizontal
|
||||||
for (dx = -2, dy = 0; dx <= 2 && !distance2PixelFound; dx += 4) {
|
for (dx = -2, dy = 0; dx <= 2; dx += 4) {
|
||||||
if (ri->XTRANSFC(row, col + dx) == pixelColor) {
|
if (ri->XTRANSFC(row, col + dx) == pixelColor) {
|
||||||
distance2PixelFound = true;
|
distance2PixelFound = true;
|
||||||
break;
|
break;
|
||||||
@@ -394,7 +394,7 @@ int RawImageSource::interpolateBadPixelsXtrans(const PixelsMap &bitmapBads)
|
|||||||
|
|
||||||
if (!distance2PixelFound) {
|
if (!distance2PixelFound) {
|
||||||
// no distance 2 pixel on horizontal, check vertical
|
// no distance 2 pixel on horizontal, check vertical
|
||||||
for (dx = 0, dy = -2; dy <= 2 && !distance2PixelFound; dy += 4) {
|
for (dx = 0, dy = -2; dy <= 2; dy += 4) {
|
||||||
if (ri->XTRANSFC(row + dy, col) == pixelColor) {
|
if (ri->XTRANSFC(row + dy, col) == pixelColor) {
|
||||||
distance2PixelFound = true;
|
distance2PixelFound = true;
|
||||||
break;
|
break;
|
||||||
@@ -428,7 +428,7 @@ int RawImageSource::interpolateBadPixelsXtrans(const PixelsMap &bitmapBads)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Search for hot or dead pixels in the image and update the map
|
/* Search for hot or dead pixels in the image and update the map
|
||||||
* For each pixel compare its value to the average of similar colour surrounding
|
* For each pixel compare its value to the average of similar color surrounding
|
||||||
* (Taken from Emil Martinec idea)
|
* (Taken from Emil Martinec idea)
|
||||||
* (Optimized by Ingo Weyrich 2013 and 2015)
|
* (Optimized by Ingo Weyrich 2013 and 2015)
|
||||||
*/
|
*/
|
||||||
|
@@ -39,7 +39,7 @@ class PixelsMap :
|
|||||||
int w; // line width in base_t units
|
int w; // line width in base_t units
|
||||||
int h; // height
|
int h; // height
|
||||||
typedef unsigned long base_t;
|
typedef unsigned long base_t;
|
||||||
static const size_t base_t_size = sizeof(base_t);
|
static constexpr size_t base_t_size = sizeof(base_t);
|
||||||
base_t *pm;
|
base_t *pm;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@@ -102,7 +102,7 @@ protected:
|
|||||||
void transformRect (const PreviewProps &pp, int tran, int &sx1, int &sy1, int &width, int &height, int &fw);
|
void transformRect (const PreviewProps &pp, int tran, int &sx1, int &sy1, int &width, int &height, int &fw);
|
||||||
void transformPosition (int x, int y, int tran, int& tx, int& ty);
|
void transformPosition (int x, int y, int tran, int& tx, int& ty);
|
||||||
|
|
||||||
unsigned FC(int row, int col)
|
unsigned FC(int row, int col) const
|
||||||
{
|
{
|
||||||
return ri->FC(row, col);
|
return ri->FC(row, col);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user