【发布时间】:2015-10-05 05:19:22
【问题描述】:
所以,我的任务是创建一个矢量中值过滤器来帮助清理嘈杂的图像。这背后的逻辑并不太复杂。首先,只是为了平衡支付领域,所有图像都作为 3d 值数组进入 java。红色、绿色和蓝色值存储在一种行/列情况中。所以它在引用像素值时就像这样:
[Color Component (Red, green, or blue)][Row][Col]
这将向您显示图像特定位置的确切像素值。我想象一个正方形,当做这些时类似于矩阵的东西。
所以...到过滤器..
来自一篇学术文章:“此过滤器通过在具有 RGB 值的目标像素上移动一个窗口 [a mask] 来执行非线性过滤,并将该像素的值重置为与另一个像素的距离之和最小的像素窗口中的像素。”
如果您没有做过任何图像处理工作,这可能看起来有些令人困惑,但实际上非常简单。您的蒙版本质上是一个框,它在图像中移动并创建一个具有预定约束大小的像素“邻域”(我通常使用 3x3 “邻域”,因此我将有 9 个值 - 就像我在下面的代码中一样。 )
要点是选择邻域中的目标像素 - 通常是中心(在本示例中,始终是中心)并根据周围像素计算它的值。非常简单,而且在消除图像中的噪点方面也非常令人印象深刻。
所以创建新像素值的逻辑是最重要的部分。获取“邻域”值相当容易,我也会将其包括在内,但我遇到的问题是我认为我没有正确计算逻辑。如上所述,逻辑比较每个“邻域”像素值彼此并创建每个像素相对于其余像素的距离的运行总和。运行总和为 LOWEST 的像素将成为目标像素的新值。
我遵循的步骤(带有代码示例):
-
获取邻域值:
//First two for loops will travel through column and row of image array. //The third will travel through the RGB values (This is 4 values because Transparency is also accounted for here.) for (int row = 1; row < imageInDimension.getHeight() - 1; row++) { for (int column = 1; column < imageInDimension.getWidth() - 1; column++) { for (int ColComp = 1; ColComp < 4; ColComp++) { ////////////////////////// //The Neighborhood//////// ////////////////////////// int pixelNeighbors[] = new int[9]; //Assign values to neighborhood pixelNeighbors[0] = OldImageTGRB[ColComp][column - 1][row - 1]; pixelNeighbors[1] = OldImageTGRB[ColComp][column - 1][row]; pixelNeighbors[2] = OldImageTGRB[ColComp][column - 1][row + 1]; pixelNeighbors[3] = OldImageTGRB[ColComp][column][row - 1]; pixelNeighbors[4] = OldImageTGRB[ColComp][column][row]; pixelNeighbors[5] = OldImageTGRB[ColComp][column][row + 1]; pixelNeighbors[6] = OldImageTGRB[ColComp][column + 1][row - 1]; pixelNeighbors[7] = OldImageTGRB[ColComp][column + 1][row]; pixelNeighbors[8] = OldImageTGRB[ColComp][column + 1][row + 1]; -
对“邻居”中的每个像素相对于“邻居”中的其他像素执行距离计算,并将每个值存储在运行总和中(此处使用绝对值,因为它是距离公式)
//Calculate distances for (int i = 0; i < 8; i++) { runningSumPixel0 += Math.abs(pixelNeighbors[0] - pixelNeighbors[i]); runningSumPixel1 += Math.abs(pixelNeighbors[1] - pixelNeighbors[i]); runningSumPixel2 += Math.abs(pixelNeighbors[2] - pixelNeighbors[i]); runningSumPixel3 += Math.abs(pixelNeighbors[3] - pixelNeighbors[i]); runningSumPixel4 += Math.abs(pixelNeighbors[4] - pixelNeighbors[i]); runningSumPixel5 += Math.abs(pixelNeighbors[5] - pixelNeighbors[i]); runningSumPixel6 += Math.abs(pixelNeighbors[6] - pixelNeighbors[i]); runningSumPixel7 += Math.abs(pixelNeighbors[7] - pixelNeighbors[i]); runningSumPixel8 += Math.abs(pixelNeighbors[8] - pixelNeighbors[i]); } -
这就是我认为我要么让它太复杂要么搞乱逻辑的地方。我需要资助最低的运行总和并将目标像素设置为该值。我现在将每个单独的运行总和与所有值进行比较,并验证它是否是最低的。如果是最低的,则成为目标像素值。这是一篇很长的文章,我很抱歉。
//Determine lowest distance value and set target pixel to lowest distance value original value if (runningSumPixel0 < runningSumPixel1 & runningSumPixel0 < runningSumPixel2 & runningSumPixel0 < runningSumPixel3 & runningSumPixel0 < runningSumPixel4 & runningSumPixel0 < runningSumPixel5 & runningSumPixel0 < runningSumPixel6 & runningSumPixel0 < runningSumPixel7 & runningSumPixel0 < runningSumPixel8) { System.out.println("Target set to o position"); newImageTRGB[ColComp][column][row] = pixelNeighbors[0]; } else if (runningSumPixel1 < runningSumPixel0 & runningSumPixel1 < runningSumPixel2 & runningSumPixel1 < runningSumPixel3 & runningSumPixel1 < runningSumPixel4 & runningSumPixel1 < runningSumPixel5 & runningSumPixel1 < runningSumPixel6 & runningSumPixel1 < runningSumPixel7 & runningSumPixel1 < runningSumPixel8) { System.out.println("Target set to 1 position"); newImageTRGB[ColComp][column][row] = pixelNeighbors[1]; } else if (runningSumPixel2 < runningSumPixel0 & runningSumPixel2 < runningSumPixel1 & runningSumPixel2 < runningSumPixel3 & runningSumPixel2 < runningSumPixel4 & runningSumPixel2 < runningSumPixel5 & runningSumPixel2 < runningSumPixel6 & runningSumPixel2 < runningSumPixel7 & runningSumPixel2 < runningSumPixel8) { System.out.println("Target set to 2 position"); newImageTRGB[ColComp][column][row] = pixelNeighbors[2]; } else if (runningSumPixel3 < runningSumPixel0 & runningSumPixel3 < runningSumPixel1 & runningSumPixel3 < runningSumPixel3 & runningSumPixel3 < runningSumPixel4 & runningSumPixel3 < runningSumPixel5 & runningSumPixel3 < runningSumPixel6 & runningSumPixel3 < runningSumPixel7 & runningSumPixel3 < runningSumPixel8) { System.out.println("Target set to 3 position"); newImageTRGB[ColComp][column][row] = pixelNeighbors[3]; } else if (runningSumPixel4 < runningSumPixel0 & runningSumPixel4 < runningSumPixel2 & runningSumPixel4 < runningSumPixel3 & runningSumPixel4 < runningSumPixel1 & runningSumPixel4 < runningSumPixel5 & runningSumPixel4 < runningSumPixel6 & runningSumPixel4 < runningSumPixel7 & runningSumPixel4 < runningSumPixel8) { System.out.println("Target set to 4 position"); newImageTRGB[ColComp][column][row] = pixelNeighbors[4]; } else if (runningSumPixel5 < runningSumPixel0 & runningSumPixel5 < runningSumPixel2 & runningSumPixel5 < runningSumPixel3 & runningSumPixel5 < runningSumPixel4 & runningSumPixel5 < runningSumPixel1 & runningSumPixel5 < runningSumPixel6 & runningSumPixel5 < runningSumPixel7 & runningSumPixel5 < runningSumPixel8) { System.out.println("Target set to 5 position"); newImageTRGB[ColComp][column][row] = pixelNeighbors[5]; } else if (runningSumPixel6 < runningSumPixel0 & runningSumPixel6 < runningSumPixel2 & runningSumPixel6 < runningSumPixel3 & runningSumPixel6 < runningSumPixel4 & runningSumPixel6 < runningSumPixel5 & runningSumPixel6 < runningSumPixel1 & runningSumPixel6 < runningSumPixel7 & runningSumPixel6 < runningSumPixel8) { System.out.println("Target set to 6 position"); newImageTRGB[ColComp][column][row] = pixelNeighbors[6]; } else if (runningSumPixel7 < runningSumPixel0 & runningSumPixel7 < runningSumPixel2 & runningSumPixel7 < runningSumPixel3 & runningSumPixel7 < runningSumPixel4 & runningSumPixel7 < runningSumPixel5 & runningSumPixel7 < runningSumPixel6 & runningSumPixel7 < runningSumPixel1 & runningSumPixel7 < runningSumPixel8) { System.out.println("Target set to 7 position"); newImageTRGB[ColComp][column][row] = pixelNeighbors[7]; } else if (runningSumPixel8 < runningSumPixel0 & runningSumPixel8 < runningSumPixel2 & runningSumPixel8 < runningSumPixel3 & runningSumPixel8 < runningSumPixel4 & runningSumPixel8 < runningSumPixel5 & runningSumPixel8 < runningSumPixel6 & runningSumPixel8 < runningSumPixel7 & runningSumPixel8 < runningSumPixel1) { System.out.println("Target set to 8 position"); newImageTRGB[ColComp][column][row] = pixelNeighbors[8]; } } } } 返回新图像。
我相当确定我的邻域是正确的,因为我使用相同的算法在不同的过滤器上找到邻域,并且它完美无缺。
问题:本质上,代码根本没有减少噪音。事实上,它对图像没有任何作用。这没有任何意义,因为理论上我正在改变每个像素值..
有什么建议吗?希望这不是一个特定的问题。提前致谢!
建议更新后的整个方法:
protected Image VMFilter (Image imageIn) {
//Get Image Dimensions
Dimension imageInDimension = getImageDimension(imageIn);
//calculate total number of pixels
double totalPixels = imageInDimension.getHeight() * imageInDimension.getWidth();
//Move image into an array.."old image"
int OldImageTGRB[][][] = pixelsArrayToTRGBArray(imageToPixelsArray(imageIn), imageInDimension);
//Create new image where new values will be stored
int newImageTRGB[][][] = pixelsArrayToTRGBArray(imageToPixelsArray(imageIn), imageInDimension);
//////////////////////////////////
//////////THE LOGIC///////////////
//////////////////////////////////
//Sort through oldImage TRGB and create the neighborhood from values
for (int row = 1; row < imageInDimension.getHeight() - 1; row++) {
for (int column = 1; column < imageInDimension.getWidth() - 1; column++) {
//Will Cycle through the color components assigning values to the neighborhood
for (int ColComp = 1; ColComp < 4; ColComp++) {
//////////////////////////
//The Neighborhood////////
//////////////////////////
int pixelNeighbors[] = new int[9];
//Assign values to neighborhood
pixelNeighbors[0] = OldImageTGRB[ColComp][column - 1][row - 1];
pixelNeighbors[1] = OldImageTGRB[ColComp][column - 1][row];
pixelNeighbors[2] = OldImageTGRB[ColComp][column - 1][row + 1];
pixelNeighbors[3] = OldImageTGRB[ColComp][column][row - 1];
pixelNeighbors[4] = OldImageTGRB[ColComp][column][row];
pixelNeighbors[5] = OldImageTGRB[ColComp][column][row + 1];
pixelNeighbors[6] = OldImageTGRB[ColComp][column + 1][row - 1];
pixelNeighbors[7] = OldImageTGRB[ColComp][column + 1][row];
pixelNeighbors[8] = OldImageTGRB[ColComp][column + 1][row + 1];
//Create running sum variables to keep track of distance calculation sums
int runningSumPixels[] = new int[9];
//Calculate distances
for (int i = 0; i < 9; i++) {
runningSumPixels[i] += Math.abs(pixelNeighbors[i] - pixelNeighbors[i]);
}
int iLow = Integer.MAX_VALUE;
int lowest = Integer.MAX_VALUE;
for (int i = 0; i < 9; ++i) {
if (runningSumPixels[i] < lowest) {
iLow = i;
lowest = runningSumPixels[i];
}
System.out.println("Old Value:" + newImageTRGB[ColComp][column][row]);
newImageTRGB[ColComp][column][row] = pixelNeighbors[iLow];
System.out.println("New Value:" + newImageTRGB[ColComp][column][row]);
}
}
}
}
//Return new image..
return pixelsArrayToImage(
TRGBArrayToPixelsArray(newImageTRGB, imageInDimension), imageInDimension);
}
【问题讨论】:
-
如果您能准确地告诉我们您得到了令您惊讶的结果,那就太好了。还有一种更简单的方法来执行第 3 步,我会在找到问题后向您描述。
-
警告! 上面的代码不计算向量中值。这是对分别计算每个通道的中位数的一种昂贵方式的尝试。向量中值需要使用每个像素的 RGB 值作为向量,并计算向量距离。
标签: java image-processing