Why the picture is black? [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Write a method Picture emboss to add an emboss style effect to a picture by applying the following kernel.
| -2 -1 0 |
| -1 1 1 |
| 0 1 2 |
(it is a 3*3 matrix)
When applying a kernel filter to a pixel near the boundary, some of its neighboring pixels may not exist. In such cases, assume the leftmost column wraps around to the rightmost column, and vice versa; and the top row wraps around to the bottom row, and vice versa.
Below is part of my code, but I find that the picture I get is all black. I only have a limited knowledge of java. So after checking for some time, I still can not find the error.
public static Picture emboss(Picture picture) {
int width= picture.width();
int height= picture.height();
int[][] matrix1 = new int[height][width];
int[][] matrix2 = new int[height][width];
int[][] matrix3 = new int[height][width];
for (int col = 0; col < width; col++) {
for (int row = 0; row < height; row++){
Color color = picture.getColor(col, row);
matrix1[row][col] = color.getRed();
matrix2[row][col] = color.getGreen();
matrix3[row][col] = color.getBlue();
int a = row-1;
int b = col-1;
int c = row+1;
int d = col+1;
if (a < 0) {
a = height-1;
}
if (b < 0) {
b = width-1;
}
if (c > height-1) {
c = 0;
}
if ( d > width-1 ) {
d = 0;
}
int GR = -2 * matrix1[a][b] - matrix1[row][b] - matrix1[a][col] + matrix1[row][col] + matrix1[c][col] + matrix1[row][d] + 2*matrix1[c][d];
int GG = -2 * matrix2[a][b] - matrix2[row][b] - matrix2[a][col] + matrix2[row][col] + matrix2[c][col] + matrix2[row][d] + 2*matrix2[c][d];
int GB = -2 * matrix3[a][b] - matrix3[row][b] - matrix3[a][col] + matrix3[row][col] + matrix3[c][col] + matrix3[row][d] + 2*matrix3[c][d];
if (GR < 0) {
GR=0;
}
if( GR>255 ) {
GR=255;
}
if ( GG<0 ) {
GG=0;
}
if( GG>255 ) {
GG=255;
}
if ( GB<0 ) {
GB=0;
}
if ( GB>255 ) {
GB=255;
}
Color newColor= new Color(GR,GG,GB);
picture.setColor(col,row,newColor);
}
}
return picture;
}

When you create a matrix like this
int[][] matrix1 = new int[height][width];
It is by default filled with 0s.
Look at when you actually give the matrix a value. in the first iteration of the for loops, everything is black. You start by setting the current pixel:
matrix1[row][col] = color.getRed();
But all the neighbours are still black. When you move in the iterations, all pixels that have not been computed yet are black and you include them in the computation when you use the neighbours.
You should start by an iteration just to fill these three matrices, followed by another iteration for the computation:
for (int col = 0; col < width; col++) {
for (int row = 0; row < height; row++){
Color color = picture.getColor(col, row);
matrix1[row][col] = color.getRed();
matrix2[row][col] = color.getGreen();
matrix3[row][col] = color.getBlue();
}
}
for (int col = 0; col < width; col++) {
for (int row = 0; row < height; row++){
int a = row-1;
int b = col-1;
[...] // The rest of the code goes here
}
}

Related

Storing all diagonals from top right to bottom left in array

I am trying to store all of the values in the matrix from the top right to the bottom left and store them in an array.
int matrixSample [][] = {
{6,4,1,4},
{7,5,4,4},
{4,4,8,3},
{4,4,8,3}
};
The output should be
[4,1,4,4,4,3,6,5,8,3,7,4,8,4,4,4]
I can get the bottom right diagonal
static int[] getAllDiagonalsInMatrix(int matrix[][]){
// Sum of arithmetic progression
int diagonal[] = new int[matrix.length * (matrix.length + 1)*2];
int index = 0;
for(int row = 0; row < matrix.length; row++) {
for(int col = 0; col < matrix[row].length - row; col++) {
diagonal[index++] = matrix[row + col][col];
}
}
return diagonal;
}
Is this even possible to do using the same two loops by adjustments made in the loops above?
Okay, here is my thought process on your problem. However, I'm going to print values instead of collecting them to make it a little easier on me and keep the solution easy to read.
First, how do you get a diagonal? We need to do this frequently so lets start by making a function for that. Maybe we could pass in the top left corner of the diagonal and go from there.
public void getDiagonal(int[][] array, int row, int col) {
// While row and col are within the bounds of the array
while (row < array.length && col < array[row].length) {
// Print element in diagonal
System.out.println(array[row][col]);
// Diagonal moves from top-left to bottom-right
row++;
col++;
}
}
Now that we have a function to get a diagonal, we just need a way to call it. Essentially, we just need to follow an L shape going from the top-right to the top-left to the bottom-left.
// Get diagonals starting in the first row with a column > 0
for (int col = array.length - 1; col > 0; col--) {
getDiagonal(array, 0, col);
}
// Get all diagonals starting from the left most column
for (int row = 0; row < array.length; row++) {
getDiagonal(array, row, 0);
}
Now that we have a working way to iterate through the values, we can rewrite it to save the values into an array instead. You could also choose to remove the function entirely now that you have a process.
Edit: I almost forgot, but the mathematical solution you were looking for is as follows.
for (int row = 0; row < array.length; row++) {
for (int col = 0; col < array.length; col++) {
// Index along diagonal
int diagonal = Math.min(row, col);
// Which part of L contains value
if (col >= row) {
int start = array.length - 1 - (col - row);
int passed = start * (start + 1) / 2;
solution[passed + diagonal] = array[row][col];
} else {
int start = array.length - 1 - (row - col);
int passed = array.length * array.length - 1 - start * (start + 1) / 2; solution[passed - array.length + 1 + row] = array[row][col];
}
}
}
One solution is to iterate through a matrix where you consider positions outside of the matrix, but exclude every index out of bounds.
static int[] getDiagonals(int[][] mat) {
int diagonal[] = new int[mat.length * (mat[0].length)];
int index = 0;
int yStart = -mat[0].length;
for (int y = yStart; y < mat.length; y++) {
for (int x = 0; x < mat[0].length; x++) {
if (y + x >= 0 && y + x < mat.length) {
diagonal[index++] = mat[y+x][x];
}
}
}
return diagonal;
}
Might not be optimal as you are effectively traversing a matrix nearly twice the size, but it is pretty intuitive.

Java - Loop to average rgb values should be breaking things....but isn't

So I've got a school project and we have to work with a couple classes our prof gave us and make our own to make an image organizer.
The first part consists of making a set of static methods to edit the images themselves as 2D arrays of Color arrays(ColorImage type).
The first first problem is making a tool to downscale an image by a factor of f(f sided square of pixels in the original becomes 1 pixel in the output), and mine works, but I think it shouldn't and I can't figure why it works, so any help is appreciated. Specifically I'm taking about the loop that averages the colours of each position in the buffer array(avgArr[][]) (line 16). I'm thinking: the value of reds blues and greens would just be overwritten for each iteration and avgColor would just get the vlaue of the last pixel it got the rgb values off of avgArr.
static ColorImage downscaleImg(ColorImage img, int f) {
ColorImage dsi = new ColorImage(img.getWidth()/f, img.getHeight()/f);
Color[][] avgArr = new Color[f][f];
int reds = 0;
int greens = 0;
int blues = 0;
for(int i = 0; i < dsi.getWidth(); i++) {
for(int j = 0; j < dsi.getHeight(); j++) {
for(int x = i*f, xc = 0; x < i*f + (f-1); x++, xc++){
for(int y = j*f, yc = 0; y < j*f + (f-1); y++, yc++) {
avgArr[xc][yc] = img.getColor(x, y);
}
}
for(int k = 0; k < f - 1; k++){
for(int w = 0; w < f - 1; w++) {
reds += avgArr[k][w].getR();
greens += avgArr[k][w].getG();
blues += avgArr[k][w].getB();
}
}
int count = f*f;
Color avgColor = new Color(reds/count, greens/count, blues/count);
dsi.setColor(i, j, avgColor);
reds = 0;
greens = 0;
blues = 0;
}
}
return dsi;
}
Thanks,
EDIT: Turns out, it was in fact just taking the colour of, the last position of avgArr that it looked at. Any suggestions to correct are welcome.
I think you can solve your problem by summing the reds/greens/blues and then dividing them by the total pixels at the end to find the average:
int reds = 0;
int greens = 0;
int blues = 0;
...
for(int k = 0; k < f - 1; k++){
for(int w = 0; w < f - 1; w++) {
reds += avgArr[k][w].getR(); // <-- note the +=
greens += avgArr[k][w].getG();
blues += avgArr[k][w].getB();
}
}
int count = (f-1)*(f-1);
Color avgColor = new Color(reds/count, greens/count, blues/count);

How to reduce the error of the noise image using genetic algorithm?

The question says, given a noise image (lena_noise) and original image (lena_original), the programmer is asked to design and implement a program that minimize the noise by given mathematical formula using Genetic algorithm.
my problem is that my program works bad, really really bad. it means that when I start with lena_noise, then it should after a while the program give me the original image, but unfortunately it gives an image worse than lena_noise. so I thought that my noise program have a problem. So, I hope find a keypoint to find how to reduce the noise using Genetic algorithm?
private int[][] Performing_Noise_into_grayscale_image(Storing_Images SI)
{
this.Generate_New_Random_for_3_parameters();
int [][] nose = new int[SI.heigth][SI.width];
for (int row = 0; row < SI.heigth; row++)
{
for (int col = 0; col < SI.width; col++)
{
double no = this.NoiseAmp*sin((2*Math.PI*this.NoiseFreqCol*row) + (2*Math.PI*this.NoiseFreqCol*col));
int value = SI.Array[row][col];
int alph = (value >> 24) & 0xff;
int red = (value >> 16) & 0xff;
int green = (value >> 8) & 0xff;
int blue = value & 0xff;
int avg = (red+green+blue)/3;
alph = ((int)no) | (alph << 24);
red = ((int) no) | (avg << 16);
green = ((int) no) | (avg << 8);
blue = ((int) no) | avg;
int value2 = 0;
value2 = (alph<<24) | (red<<16) | (green<<8) | blue;
nose[row][col] = value2;
}
}
return nose;
}
the function Generate_New_Random_for_3_parameters() it is just a function that gives a random double number between 0-30 for 3 variables. These 3 variables are (NoiseAmp, NoiseFreqCol, NoiseFreqCol) used in the mathematical formula.
Storing_Images have three attributes, these are (int [][] Array, int height, int width)
Notice that the image is grayscale image, this is why we take the average value.
Brief about the program
the program have four parameters, these are as following: Crossover_probability = 0.3, mutation_probability = 0.05, number_of_population = 4, number_of_generations = 10. if you are not familiar with these parameters, then take a look at Introduction to Genetic Algorithm. So, the program begins with receiving the lena_noise and apply on it the mathematical formula for all population (each one of the population have its own random double number of mathematical formula), then we select the best one, that is the one that have less error comparing with the lena_original. then the best one is the one that would survive for next generation. On the next generation, we apply a the mathematical formula for all population, and then we select the best one that have a few error as possible comparing to the lena_original image. etc.
the Fitness function is as follows,
public Storing_Images[] Fitness()
{
Storing_Images errorSSI [] = new Storing_Images[4];
for (int i = 0; i < (this.Childs.length) ; i++)
{
//choose the best one among 4
//the best one is the one that have the minimum error from the orginal image.
int [][] error = IP.Compare_OriginalImage_with_given_Image(Childs[i].Array);
errorSSI[i] = new Storing_Images(error,512,512);
}
int value=0;
int Sum [] = new int[4];
for (int i = 0; i < (this.Childs.length) ; i++)
{
for (int row = 0; row < IP.width; row++)
{
for (int col = 0; col < IP.height; col++)
{
int val = errorSSI[i].Array[row][col];
if ( val < 0 )
val = val * -1;
value = value + val;
}
}
double x = (value/(IP.width * IP.height));
Sum[i] = (int) x;
value =0;
}
int Mini=Sum[0];
int posi_of_mini= 0;
// int pos2=0;
for (int k = 0; k < Sum.length; k++)
{
if ( Sum[k] < Mini )
{
// pos2 = Mini;
Mini = Sum[k];
posi_of_mini = k;
}
}
this.Childs[0] = Childs[posi_of_mini];
this.Childs[1] = Childs[posi_of_mini];
this.Childs[2] = Childs[posi_of_mini];
this.Childs[3] = Childs[posi_of_mini];
return Childs;
}
about the function that do comparing between lena_original and the one of the population.
public int [][] Compare_OriginalImage_with_given_Image(int [][] current)
{
int [][] error = new int [this.height][this.width];
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
int value1 = this.Orginal[row][col];
int value2 = current[row][col];
//I need to put absolute value for either value 1 and value2
if (value1 < 0)
value1 = value1 *-1;
if(value2 < 0)
value2 = value2 * -1;
//int min = Math.min(value1, value2);
int er = value2 - value1;
error[row][col] = er;
}
}
return error;
}
Reference.
*similar question to my question but no details about the answer is from this page Image processing using genetic algorithm
*How to convert a color image into grayscale image in Java this pages tells us about how to deal with grayscale image and playing with it.
feel free to ask a questions about the problem. Also, any comments, hints, etc are welcome. Thank you
Try this to create a grey image:
public static void makeGray(BufferedImage img)
{
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
int rgb = img.getRGB(x, y);
int r = (rgb >> 16) & 0xFF;
int g = (rgb >> 8) & 0xFF;
int b = (rgb & 0xFF);
int grayLevel = (r + g + b) / 3;
int gray = (grayLevel << 16) + (grayLevel << 8) + grayLevel;
img.setRGB(x, y, gray);
}
}
}
Now, you need a way to combine 2 elements from your population.
it doesn't matter how, so for the sake of the example, I split the image evenly:
for (int x = 0; x < img1.getWidth() / 2; x++)
for (int y = 0; y < img1.getHeight(); y++)
// build 1st half of the result image
for (int x = img2.getWidth() / 2; x < img2.getWidth(); x++)
for (int y = 0; y < img2.getHeight(); y++)
// build 2nd half of the result image
You also need to take into account the mutation rate which can change random elements on the result image. (do that later)
GA is a global optimization algorithm. It is not very convenient to be used for image noise removal. Even if you find proper formula it will be only for this pair of images.

BufferedImage to 2D Array: Finding pixelated edges

I'm trying to calculate the edges of a black object within a .png file. And by that I mean find the column and row values that makeup a box that encapsulates an object. I attached a link to the photo I created which draws the box according to the values I find. As you can see the top, bottom, and right lines seem to line up correctly, but if you zoom in to the left line, part of the image is outside of the box. Why is that? I have an algorithm which I'll post below that searches every pixel in the array and finds the last occurrence of pixel values != 0 for the top, bottom, left and right sides. For some reason that extra image on the left side is registering pixels that are == 0... Are the values being rounded down to zero? If somebody could explain what is happening that would be great.
Here is a link to the image: http://i.imgur.com/UG8Cghe.png. You really have to zoom into the left side to see what I am talking about. Downloading the image and viewing is probably a necessity. It is a VERY small detail.
Here is the method that converts the BufferedImage(.png) to a 2D Array:
private static int[][] loadImageTo2D(String file_path)
{
img = null;
try { img = ImageIO.read(new File(file_path)); }
catch (IOException e) { System.out.println(e); }
int width = img.getWidth();
int height = img.getHeight();
int[][] pix = new int[height][width];
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
pix[row][col] = img.getRGB(col, row);
}//for
}//for
return pix;
}//loadImageTo2D
Here is how I am searching for the sides:
private static int[] getPerim(int[][] pix)
{
//Array holds object boundary edges.
int[] lines = new int[4];
lines[BOTTOM] = 0;
lines[TOP] = pix.length;
lines[LEFT] = pix[0].length;
lines[RIGHT] = 0;
//Top down iteration, find the first and last row and column of the
//actual graphic.
for (int row = 0; row < pix.length; row++)
{
for(int col = 0; col < pix[0].length; col++)
{
if (pix[row][col] != 0)
{
if (row < lines[TOP]) { lines[TOP] = row; }
else if (row > lines[BOTTOM]) { lines[BOTTOM] = row; }
else if (col < lines[LEFT]) { lines[LEFT] = col; }
else if (col > lines[RIGHT]) { lines[RIGHT] = col; }
}//if
}//for
}//for
return lines;
}//getPerim
I'm then using lines[] to draw the blue box you see in image. Help!
Drop the else part of if else and make all of them ifs . Only one of those if elses can be executed. What happens if pixel is the most down and most left pixel? It will be only used as the most bottom one, as the if-else statement won't get to the col part. I suggest you change it to
if (row < lines[TOP]) { lines[TOP] = row; }
if (row > lines[BOTTOM]) { lines[BOTTOM] = row; }
if (col < lines[LEFT]) { lines[LEFT] = col; }
if (col > lines[RIGHT]) { lines[RIGHT] = col; }
And no, you can't group left border with right border, as they can be on the same pixel.

How to draw a set of horizontal lines?

I am new to OpenGL as learning exercise I decided to draw a set of horizontal lines from a grid of m x n matrix containing the vertices locations
This is what I have
and If I use LINE_STRIP
A code snippet using vertex arrays and indices will be great, I cant seem to be able to get the concept just from a text book I need to see and play with a code example
Any help will be much appreciated!
#Thomas
Got it working with the following code
totalPoints = GRID_ROWS * 2 * (GRID_COLUMNS - 1);
indices = new int[totalPoints];
points = new GLModel(this, totalPoints, LINES, GLModel.DYNAMIC);
int n = 0;
points.beginUpdateVertices();
for ( int row = 0; row < GRID_ROWS; row++ ) {
for ( int col = 0; col < GRID_COLUMNS - 1; col++ ) {
int rowoffset = row * GRID_COLUMNS;
int n0 = rowoffset + col;
int n1 = rowoffset + col + 1;
points.updateVertex( n, pointsPos[n0].x, pointsPos[n0].y, pointsPos[n0].z );
indices[n] = n0;
n++;
points.updateVertex( n, pointsPos[n1].x, pointsPos[n1].y, pointsPos[n1].z );
indices[n] = n1;
n++;
}
}
points.endUpdateVertices();
Then I update and draw by doing
points.beginUpdateVertices();
for ( int n = 0; n < totalPoints; n++ ) {
points.updateVertex( n, pointsPos[indices[n]].x, pointsPos[indices[n]].y, pointsPos[indices[n]].z );
}
points.endUpdateVertices();
This is the result
Fix it by changing the nested for loop
for ( int col = 0; col < GRID_COLUMNS; col++ ) {
for ( int row = 0; row < GRID_ROWS - 1; row++ ) {
int offset = col * GRID_ROWS;
int n0 = offset + row;
int n1 = offset + row + 1;
indices[n++] = n0;
indices[n++] = n1;
}
}
Now I can have any number of rows and columns
Thanks agin!
You need to draw a line for each segment and resuse an index, i.e. for the first part you'd draw a line for (0,1), (1,2), (2,3) and so on.
Edit:
Suppose you have a 4x5 array (4 lines, 5 vertices per line). You could then calculate the indices like this (pseudo code):
Vertex[] v = new Vertex[20]; // 20 vertices in the grid
for(int row = 0; row < numrows; row++) // numrows = 4
{
int rowoffset = row * numcols ; //0, 4, 8, 12
for(int col = 0; col < (numcols - 1); col++) //numcols = 5
{
addLineIndices(rowoffset + col, rowoffset + col +1); //adds (0,1), (1,2), (2,3) and (3, 4) for the first row
}
}
Then issue the draw call for numrows * (numcols - 1) linesegments (GL_LINES), i.e. 16 in the example. Note that addLineIndices would be a function that adds the index pair for one line segment to an index array which is then supplied to the draw call.

Categories