What am I doing wrong with my image denoising method? - java

I've been trying to denoise my image by using a median filter as described in this article
I'm only doing one pass until I get this thing working. The result is largely a washed out image, as seen below.
A minimal working version of my code is below:
import java.awt.image.BufferedImage;
import java.util.Arrays;
public class Denoise {
public static void main(String args[]) {
String directory = "C:\\Users\\Speedy Octopus\\Desktop\\Place Car Folders Here\\Original\\15.JPG";
BufferedImage image = ImageUtility.loadImage(directory);
for (int iterationCount = 0; iterationCount < 1; iterationCount++){
for (int i = 1; i < image.getWidth()-1; i++) {
for (int j = 1; j < image.getHeight()-1; j++) {
image.setRGB(i, j, getMedianPixelValue(image, i, j));
}
}
}
String directory2 = "C:\\Users\\Speedy Octopus\\Desktop\\Place Car Folders Here\\Original\\152.JPG";
Controller.saveImage(image, directory2);
}
public static int getMedianPixelValue(BufferedImage image, int i, int j) {
int[] surroundingPixels = new int[8];
int iter = 0;
for (int q = i-1; q<=i+1; q++) {
for (int r = j-1; r<=j+1;r++) {
if (!(q == i && r == j)) {
surroundingPixels[iter] = image.getRGB(q, r);
iter++;
}
}
}
Arrays.sort(surroundingPixels);
int medianIndex = surroundingPixels.length/2;
int medianPixel = surroundingPixels[medianIndex];
return medianPixel;
}
}

As I answered in this question Applying Mean filter on an image using java getRGB "Returns an integer pixel in the default RGB color model (TYPE_INT_ARGB)" so you have to extract and remove the alpha (A) component before you do any comparisons:
pixel=image.getRGB(i, j)&0x00ffffff;
in the media sorting etc
And you can extract the R, G, and B and process them separately, or do the comparison on the whole pixel RGB - you can experiment either way.

Related

Checking to see if two 2D boolean arrays are equal at a given interval: Java

I have two 2d boolean arrays, the smaller array (shape) is going over the larger array (world).
I am having trouble to find a method to find out when the smaller array can "fit" into the larger one.
When I run the code it either just goes through the larger array, never stopping, or stops after one step (incorrectly).
public void solve() {
ArrayList<Boolean> worldList=new ArrayList<>();
ArrayList<Boolean> shapeList=new ArrayList<>();
for (int i = 0; i < world.length; i++) {
for (int k = 0; k < world[i].length; k++) {
worldList.add(world[i][k]);
display(i, k, Orientation.ROTATE_NONE);
for (int j = 0; j < shape.length; j++) {
for (int l = 0; l < shape[j].length; l++) {
shapeList.add(shape[j][l]);
if(shapeList.equals(worldList)) {
return;
}
}
}
}
}
}
A good place to start with a problem like this is brute force for the simplest case. So, for each index in the world list, just check to see if every following index of world and shapes match.
Notice we only iterate to world.size()-shapes.size(), because naturally if shapes is longer than the portion of world we haven't checked, it won't fit.
import java.util.ArrayList;
public class Test {
ArrayList<Boolean> world = new ArrayList<>();
ArrayList<Boolean> shapes = new ArrayList<>();
public static void main(String[] args) {
new Work();
}
public Test() {
world.add(true);
world.add(false);
world.add(false);
world.add(true);
shapes.add(false);
shapes.add(true);
// Arraylists initialized to these values:
// world: T F F T
// shapes: F T
System.out.println(getFitIndex());
}
/**
* Get the index of the fit, -1 if it won't fit.
* #return
*/
public int getFitIndex() {
for (int w = 0; w <= world.size()-shapes.size(); w++) {
boolean fits = true;
for (int s = 0; s < shapes.size(); s++) {
System.out.println("Compare shapes[" + s + "] and world["+ (w+s) + "]: " +
shapes.get(s).equals(world.get(w+s)));
if (!shapes.get(s).equals(world.get(w+s))) fits = false;
}
System.out.println();
if (fits) return w;
}
return -1;
}
}
When we run this code, we get a value of 2 printed to the console, since shapes does indeed fit inside world, starting at world[2].
You can find the row and column of fitting like this
public void fit() {
int h = world.length - shape.length;
int w = world[0].length - shape[0].length;
for (int i = 0; i <= h; i++) {
for (int k = 0; k <= w; k++) {
boolean found = true;
for (int j = 0; j < shape.length && found; j++) {
for (int l = 0; l < shape[j].length && found; l++) {
if (shape[j][l] != world[i + j][k + l])
found = false;
}
}
if (found) {
//Your shape list fit the world list at starting index (i, k)
//You can for example save the i, k variable in instance variable
//Or return then as an object for further use
return;
}
}
}

How to print a matrix in clockwise order

There is matrix for [x][y] order. i want to print its value in clockwise order
I have tried several methods but unable to write the logic of the code. I'm trying it in java but logic is important so you can help me in any language.
When I read your post I've started to play so I'll post you my code maybe it will be halpful for you. I've did it for square if you want for rectangle one need separate stepX and stepY. SIZE would be input parameter in your case, I have it final static for test.
public class clockwise {
private static final int SIZE = 3;
public static void main(String[] args) {
// int[][] test_matrix = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int[][] test_matrix = {{1,2,3},{5,6,7},{9,10,11}};
int[][] direction = {{1, 0},{0, 1},{-1, 0},{0, -1}}; //{x,y}
for(int i = 0; i < SIZE; i++) {
for(int j = 0; j < SIZE; j++)
System.out.print(test_matrix[i][j] + " ");
System.out.println("");
}
int x = 0;
int y = 0;
int directionMove = 0;
int stepSize = SIZE;
boolean changeStep = true;
int stepCounter = 0;
for(int i = 0; i < SIZE*SIZE; i++) {
System.out.print(test_matrix[x][y] + " ");
stepCounter++;
if (stepCounter % stepSize == 0) {
directionMove++;
directionMove = directionMove%4;
if(changeStep) { //after first edge one need to decrees step after passing two edges
stepSize--;
changeStep = false;
} else {
changeStep = true;
}
stepCounter = 0;
}
x += direction[directionMove][0];
y += direction[directionMove][1];
}
}
}

ImageJ - Cumulative histograms and Histograms

I have run into a small problem with my program as it seems unable to find the highest value in a histogram to calculate the scale the histogram is supposed to be so now the entire histogram is way out of bounds
I really hope someone can help me out since it's driving me crazy
import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;
public class Oblig3_Oppg2 implements PlugInFilter {
public int setup(String arg, ImagePlus im) {;
return DOES_8G + NO_CHANGES;
}
public void run(ImageProcessor ip) {
final int W = 256;
final int H = 100;
final int H1 = 140;
int[] hist = ip.getHistogram();
int[] KH = new int[W]; //Cumulative Histogram Array
int maxVal;
//Calculates the highest pixel count in the Histogram
for (int i = 0; i < W; i++){
if (hist[i] > maxVal){
maxVal = i;
}
}
KH[0] = hist[0];
for(int i = 1; i < W; i++) {
KH[i] = KH[i-1] + hist[i];
}
ImageProcessor histIp = new ByteProcessor(W, H1);
histIp.setValue(255);
histIp.fill();
int max = KH[255];
for(int j = 0; j < W; j++){
KH[j] = (KH[j]*100)/max; //Scales the Cumulative Histogram
hist[j] = (hist[j]*100)/maxVal; // Scales the Histogram
}
for (int k = 0; k < W; k++){
histIp.setValue(0);
histIp.drawLine(k, H, k, H-KH[k]);
}
for (int k = 0; k < W; k++){
histIp.setValue(0);
histIp.drawLine(k, H, k, H-hist[k]);
}
for (int l = 0; l < W; l++){
histIp.setValue(l);
histIp.drawLine(l, 140, l, 102);
}
histIp.setValue(0);
histIp.drawLine(W, H, W, 0);
// Display the histogram image:
String hTitle = "Histogram";
ImagePlus histIm = new ImagePlus(hTitle, histIp);
histIm.show();
}
}
You should set maxVal to the actual value, not the current index in your loop:
for (int i = 0; i < W; i++){
if (hist[i] > maxVal){
maxVal = hist[i]; // <-- here
}
}
Furthermore, it might be better to limit the loop to hist.length instead of W. That would prevent errors in case you set W to some value different from the array length that ip.getHistogram() returns.
Since you don't provide a runnable example (i.e. the entire Java class; I assume you implement ij.plugin.filter.PlugInFilter), I didn't test the code, and it's not entirely clear to me what you want to achieve.

Image filter - Convolution

I am trying to implement image filter ( using convulution). I've spent all day trying to figure out what's going on and I cannot find a mistake. The filter works only when I use it to blur the image. In other cases it doesn't work properly: For example this is the original picture(before filtering):
And this is the picture after filtering with this matrix:
I use Marvin Image Processing Framework and jblas library in my code:
public class FiltrySploty extends MarvinAbstractImagePlugin {
#Override
public void load() {
}
#Override
public MarvinAttributesPanel getAttributesPanel() {
return null;
}
#Override
public void process(
MarvinImage imageIn,
MarvinImage imageOut,
MarvinAttributes attributesOut,
MarvinImageMask mask,
boolean previewMode) {
double norm=0;
DoubleMatrix filter = (DoubleMatrix)getAttribute("filter");
for ( int i = 0; i < filter.getRows();i++)
{
for ( int j = 0; j < filter.getColumns();j++)
{
norm=norm+filter.get(i, j);
}
}
int marginx = ((filter.getRows()-1)/2);
int marginy = ((filter.getColumns()-1)/2);
for (int x = marginx; x < imageIn.getWidth()-marginx; x++) {
for (int y = marginy; y < imageIn.getHeight()-marginy; y++) {
double SumRed=0;
double SumGreen=0;
double SumBlue=0;
for ( int i = x-marginx,k=0 ; k < filter.getRows();i++,k++)
{
for ( int j = y-marginy, l=0 ; l <filter.getColumns();j++,l++)
{
SumRed= SumRed+(filter.get(k, l)*imageIn.getIntComponent0(i, j));
SumGreen= SumGreen+(filter.get(k, l)*imageIn.getIntComponent1(i, j));
SumBlue= SumBlue+(filter.get(k, l)*imageIn.getIntComponent2(i, j));
}
}
SumRed = SumRed/norm;
SumGreen = SumGreen/norm;
SumBlue = SumBlue/norm; // normalization
if(SumRed>255.0) SumRed=255.0;
else if(SumRed<0.0) SumRed=0.0;
if(SumGreen>255.0) SumGreen=255.0;
else if(SumGreen<0.0) SumGreen=0.0;
if(SumBlue>255.0) SumBlue=255.0;
else if(SumBlue<0.0) SumBlue=0.0;
imageOut.setIntColor(x, y, (int)(SumRed), (int)(SumGreen), (int)(SumBlue));
}
}
}
}
Seeing the effect of filtering I suppose that the SumRed, SumGreen and SumBlue are out of range and they are setting to 255 or 0 values. But I have no idea why.

converting a matrix to string

I am working on writing a matrix, but unfortunately I am stuck with the output.
Instead of showing a matrix, it shows me something like:
actual matrix is
Matrix#512fb063
I need to convert the matrix to a string so that the output will look like this:
expected the matrix:
3 8 72
4 6 60
253 2 1
the code that I've written is this:
import java.util.Random;
final public class Matrix {
private final int size1; // number of rows
private final int size2; // number of columns
private final int[][] data; // M-by-N array
// create size1-by-size2 matrix of 0's
public Matrix(int size1, int size2) {
this.size1 = size1;
this.size2 = size2;
data = new int[size1][size2];
}
// create matrix based on 2d array
public Matrix(int[][] data) {
size1 = data.length;
size2 = data[0].length;
this.data = new int[size1][size2];
for (int i = 0; i < size1; i++)
for (int j = 0; j < size2; j++)
this.data[i][j] = data[i][j];
}
// creates and returns a random size1-by-size1 matrix with values between 0 and 255
public String toString(int size1, int size2) {
Matrix A = new Matrix(size1, size2);
String str = " ";
final int white = 0;
final int black = 255;
for (int i = 0; i < size1; i++)
for (int j = 0; j < size2; j++)
{
A.data[i][j] = white + (int)(Math.random() * ((black ) ));
str = (A.data[i][j]+"\t"+A.data[i][j+1]);
if (i==size1 &&j==size2) str = (A.data[i][j]+"\n");
}
return str;
}
You need to override the public String toString() function. What you are doing now is creating a new function called String toString(int size1, int size2).
Your new function is not called when writing:
System.out.println(myMatrix);
You could either do:
System.out.println(myMatrix.toString(2, 2));
or override the default toString() function.
So the following code should work:
#Override
public String toString() {
Matrix A = new Matrix(size1, size2);
String str = " ";
final int white = 0;
final int black = 255;
for (int i = 0; i < size1; i++)
for (int j = 0; j < size2; j++)
{
A.data[i][j] = white + (int)(Math.random() * ((black ) ));
str = (A.data[i][j]+"\t"+A.data[i][j+1]);
if (i==size1 &&j==size2) str = (A.data[i][j]+"\n");
}
return str;
}
where size1 and size2 are variables in the class.
Your output of actual matrix is Matrix#512fb063 is actually the memory address in Java that your instance of the class Matrix sits in. That's because your program doesn't know how to "print" this class - it doesn't magically know that you want a row/column representation of it.
You've got a number of options:
Your toString(int size1, int size2) is perfect. So when you want to print your matrix, you can go System.out.println(someMatrix.toString(2,2)) will work where someMatrix is an instance of your Matrix class.
If you want it to work properly by you just going System.out.println(someMatrix) then you will need to overwrite your Matrix class' toString() function. You -almost- did that in your toString(int size1, int size2) function but it didn't work because it needs to match exactly the parameters, ie: toString() should take 0 parameters. You will need to write a toString() method which can then call your toString(int size1, int size2)
Somehow you get the hashcode. Maybe you can use http://math.nist.gov/javanumerics/jama/doc/ matrix implementation.
I think this line is not working
str = (A.data[i][j]+"\t"+A.data[i][j+1]);
Don't you get an IndexOutOfBoundexception? Anyway A.data[i][j+1] is always empty within the loop. By the way, Variables in Java are always lower case.
You can simply do :
#Override
public String toString()
{
return toString(size1,size2);
}
Edit : If you want to reflect the real content of your current Matrix :
#Override
public String toString()
{
StringBuilder sbResult = new StringBuilder();
for(int i = 0; i < size1;i++)
{
for(int j = 0; j < size2;j++)
{
sbResult.append(A.data[i][j]);
sbResult.append("\t");
sbResult.append(A.data[i][j+1]);
if(i == size1 && j == size2)
{
sbResult.append("\n");
}
}
}
return sbResult.toString();
}

Categories