Solved

Copying values from a 2D Array to a 1D Array

Posted on 2002-07-24
16
232 Views
Last Modified: 2012-06-21
Hi,

I'm trying to copy values from a 2D template to a 1D array. I want to put these values in a 1D Array so that I can sort them and then get the median value. Below is the program I'm trying to do it in. Would anyone know how to do this?

import iptoolkit.*;
import uuPack.*;

class Methods2 {
     
public IntImage imageOut = new IntImage(256,256);
     
final int ImageSize = 256;
final int MaxGreyLevel = 255;
final int MinGreyLevel = 0;
     
//constructor method
public Methods2 () {
     
MainWindow mw = new MainWindow();
         
}//Methods2
     
     
//display image on screen
public void display (IntImage imageIn, IntImage imageOut) {
       
imageOut.setScaling(false);
imageIn.displayImage();
imageOut.displayImage();
       
}//display


  public void filter(IntImage imageIn, int[][] template, IntImage imageOut) {
       
       
  IntImage src = new IntImage(ImageSize, ImageSize);
  src = imageIn;
       
  int nMaskRows = template.length;
  int nMaskCols = template[0].length;
       
  int rBorder = nMaskRows / 2;  // integer division
  int cBorder = nMaskCols / 2;
  int sum;
  int[] copy = new int[];

       
  for (int r = 0; r < (ImageSize - nMaskRows + 1); r++) {
   for (int c = 0; c < (ImageSize - nMaskCols + 1); c++) {
     sum = 0;
       for (int mr = 0; mr < nMaskRows; mr++) {
        for (int mc = 0; mc < nMaskCols; mc++) {

THE NEXT TWO LINES ARE WHAT I WAS THINKING OF PUTTING IN HERE BUT ITS NOT WORKING
        for (int i = 0; i < (nMaskRows*nMaskCols); i++) {
                 copy[i] = imageIn.pixels[r+mr][c+mc];
                     
        }//for i
                   
        }//for mc
        }//for mr
             
             
 }//forc
}//forr
         
display(imageIn, imageOut);
         
}//filter
 
}//Methods2

Regards,
Guster


0
Comment
Question by:Guster
  • 11
  • 5
16 Comments
 
LVL 16

Expert Comment

by:imladris
ID: 7175746
HMMmm. It would probably be helpful if you described the problem in a bit more detail. Is it a compile error? Or a runtime error? If so, what is the stack trace?

At present I am concerned about this line:

int [] copy=new int[];

That doesn't seem like legal code.
I'm also wonder why, given an image with pixels in a 2D structure, there are 4 nested for loops for getting it out. Shouldn't 2 nested for loops be sufficient?

0
 

Author Comment

by:Guster
ID: 7175860
Hi,

What I'm trying to do is perform edge preserving smoothing using a median filter. The first set of for loops is for going over every pixel of the image with a template (say 3x3). The second set of for loops is for going through each pixel in the template itself. For each iteration of the template I want to read the values of each pixel in the template into a 1D Array so that I can sort the values and then get the median value.
When I try to compile the above program I get an error message pointing to that line 'int[] copy = new int[]' and it says that a '}' is expected?? Is this not a legal way to declare aa array??

Below is the main class where I would call the filter method:

import iptoolkit.*;

public class Test1 {
     
public static void main (String args[]) {
         
  Methods1 method = new Methods1();
         
  String imageDir = "C:/Java_Programs/image_prac/";
  IntImage image = new IntImage(imageDir + "Morse8.raw", 256, 256);
  IntImage image1 = new IntImage(256, 256);
  int[][] temp = { {1, 1, 1},
                {1, 1, 1},
                {1, 1, 1} };
         
         
  //method.convolve(image, temp, image1);
  //image.displayImage();
  method.filter(image, temp, image1);
         
     }

     
} // Test1

Regards,
Guster
0
 

Author Comment

by:Guster
ID: 7175894
Hi again,

I changed the line to:
  int[] copy = new int[nMaskRows*nMaskCols];

The program compiles without any errors now but I'm thinking that the lines:

  for (int i = 0; i < (nMaskRows*nMaskCols); i++) {
     copy[i] = imageIn.pixels[r+mr][c+mc];

will simply add the value of the first number in the template to each cell in the array and then it will do the same for the second value of the template and so on.
How can I get the array to hold each of the successive template values together??
0
 
LVL 16

Expert Comment

by:imladris
ID: 7177576
Well, that's progress at least. So there was a compiler error and it has been resolved. Now you are looking for assurance you are getting the result you want.

However, I'm not clear on what you're after. Perhaps an example would clarify things. Suppose the beginning of the image lines are:

1, 50, 25, 30, 3, ......
2, 52, 30,  3, 25, .....
1, 53, 33, 30, 5, ......

and the template is the 3x3 ones matrix in your last example, what would you expect to find in your 1D array? Feel free to use different numbers if you think it would be helpful.
0
 

Author Comment

by:Guster
ID: 7178171
Hi,

Say I'm running the template over the nine values:

1, 50, 25
2, 52, 30
1, 53, 33

I want to have each of those values in its corresponding cell in the template so that I can calculate the median. To get this I'm going to multiply each '1' value in each cell of the template by the corresponding value in the image. I haven't done this yet in the program as I was just concentrating on getting values in the template into a 1D Array.

I've been able to put the values into a 1D Array successfully. This is shown below. I have also sorted the array values, so now I'm trying to work out how to get the median value from the sorted list(I have what I've done on this so far below as well).

int[] copy = new int[nMaskRows*nMaskCols];
int b;
int x = 0;
int median;

       
  //for (int r = 0; r < (ImageSize - nMaskRows + 1); r++) {
  //for (int c = 0; c < (ImageSize - nMaskCols + 1); c++) {
  //sum = 0;
         
for (int mr = 0; mr < nMaskRows; mr++) {
  for (int mc = 0; mc < nMaskCols; mc++) {
      b = template[mr][mc];
      copy[x] = b;
      ++x;
  }//for mc
}//for mr


for (int ib = 0; ib < x ; ib++)
    {
      System.out.println("This is pixel number " + (ib + 1)+ ", its value is " + copy[ib]);
    }

sort(copy);
for (int ic = 0; ic < copy.length; ic++)
    {
      System.out.println("The sorted pixel value is " + copy[ic]);
    }
median(copy);
       
}//filter
     
         
public static int [] sort(int [] prob){

  int temp;
  int max;
         
for( int index = 0; index < prob.length - 1; index++){
               
  max = index;
               
  for( int scan = index + 1; scan < prob.length; scan++)
    if(prob[scan] > prob[max])
     max = scan;
     temp = prob[max];
     prob[max] = prob[index];
     prob[index] = temp;
                         
  }
     
return prob;
         
}//sort


public void median(int[] values) {
         
  int number = values.length;
  int med = 0;
         
for( int i = 0; i < number; i++){
   if(values[i] == number/2)
      med = values[i] + 1;
}
System.out.println("The median of the list is : " + med);
         
}//median


My median method isn't correct as it's just returning the half the value of the length of the array as opposed to the actual value in the middle cell. Do you know how I could fix this??

Guster
 





0
 

Author Comment

by:Guster
ID: 7178176
Hi again,

When I'm doing the sorting and trying to get the median value I'm using different values in the template instead of all the 1's, say:

2, 6, 4
3, 9, 1
7, 5, 8


Guster
0
 

Author Comment

by:Guster
ID: 7178206
Hi,

Ive been trying a certain way of calculating the median value of a list. It is shown below:


public int getMax(int[] values){
    //Iterator it = values.iterator();
  int max = 0;//((Integer) it.next()).intValue();
  for (int i = 0; i < values.length; i++) {
    if(values[i]>max) {
       max=values[i];
    }    
  }
  return max;
}//getMax
     
     
public int[] removeMax(int[] values){
  int max = getMax(values);
    //Iterator it = values.iterator();
  for (int i = 0; i < values.length; i++) {
    if(values[i] == max){
       values[i].remove();
       return values;
    }
  }
    return values;//never reaches this point as values contains a max
}//removeMax
     
     
public int getMedian(int[] values){
 int median;
 if(values.length/2 == (values.length+1)/2){//if even number of elements
    for(int i=0;i<(values.length -1)/2;++i){
        removeMax(values);
    }
      median = getMax(values);//median is mean of two central values
      removeMax(values);
      median = median + getMax(values);
      median = median/2;//mean of x,y is (x+y)/2
    }else{//if odd number of elements
      for(int i=0;i<values.length/2;++i){
     removeMax(values);
      }
      median = getMax(values);//median is central value
    }
    return median;
}//getMedian


The only error that I'm getting when I compile the program is an error saying 'int[] cannot be dereferenced' because of the line 'values[i].remove();'.
How can I delete a value from the list without it saying that it can't be dereferenced??

Regards,
Guster
0
 
LVL 16

Expert Comment

by:imladris
ID: 7178396
Guster,

in order to help I need to be very clear on what you are attempting to accomplish. An example would be best. You have shown a couple more matrixes, but what I am still unclear on is what result you expect in the 1D array.

Suppose the image values are:

1, 50, 25
2, 52, 30
1, 53, 33

and the template is

2, 6, 4
3, 9, 1
7, 5, 8


what will be in the 1D array? Please provide a list of numbers.
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 

Author Comment

by:Guster
ID: 7178552
Hi,

What I want to accomplish is to move a template over every pixel in an image but the template doesn't actually have any values in it. It uses the corresponding pixel values in the image. Say for an image that has the values:

2, 6, 4
3, 9, 1
7, 5, 8

When the template moves over these I want the template to pick up these values, hence these values will go into the 2D Array. I then want to get the median of these values, so I want to put them into a 1D Array so that I can sort them and pick out the median value. Once I have the median value I want to output this in an output image. This will be performed on every pixel in the image to smooth it.

When I was using the example of the matrix above, I was just assigning these examples to the template to use for practice in sorting the array. In reality I want to pick up the values from the input image.

Guster
0
 

Author Comment

by:Guster
ID: 7178555
The result in the ID Array from the above template after sorting it would be:

1, 2, 3, 4, 5, 6, 7, 8, 9

I then want to pick the median value which is 5.
0
 
LVL 16

Expert Comment

by:imladris
ID: 7178605
OK, it appears to be a two step process then. You have an image, which is a collection of values in a 2D array. Then you use the template to alter these values in some fashion and the result is again an image which is a 2D array. Finally you transform the 2D array into a 1D array, and find the median. So I would envision something like (this does averages with the 3x3 template):


int i,j,k,l;
int ix1,ix2;

// First create a new image using the original and
   the template
for(i=0; i<rows; ++i)
{   for(j=0; j<cols; ++j)
    {   imageOut.pixels[i][j]=0; // initialize out pixel
        for(k=0; k<=trow; ++k)
        {   for(l=0; l<tcol; ++l)
            {   ix1=i+(k-1);
                ix2=j+(l-1);
                // add surrounding pixels from original
                // multiplied by template value
                if(ix1>=0 && ix2>=0 && ix1<rows && ix2<cols)
                    imageOut.pixels[i][j]+=imageIn.pixels[ix1][ix2]*template[k][l];
            }
        }
        // average resulting value
        imageOut.pixels[i][j]/=9;
    }
}

// Now convert imageOut from 2D to 1D array
int copy[]=new int[rows*cols];
for(i=0; i<rows; ++i)
{   for(j=0; j<cols; ++j)
    {   copy[i*cols+j]=imageOut.pixels[i][j];
    }
}


As you can see every row of the out image is copied into the copy array. Each row starts at i times the number of columns (e.g. row 0 would begin at 0, row 1 at index cols, row 2 at index cols*2 etc.).
Then sort the array, and pick the middle value.

Does that help?

0
 

Author Comment

by:Guster
ID: 7178687
That looks good, but how do I pick the middle value from a ID Array of values? Say the array contains 9 values how would I pick out the middle value?? And if I want to get the median for an array that has an even number of values I need to add the two middle values and divide by two, how would I do this?? This is the bit I'm stuck on at the minute

Guster
0
 

Author Comment

by:Guster
ID: 7178704
Hi,
 
I think I got it for an odd numbered array. Is it simply something like:

if(values.length == 9) {
   med = values[4];
   System.out.println("The median of the list is : " + med);
}

and so on for the odd numbered templates??
0
 

Author Comment

by:Guster
ID: 7179947
Hi,

In my program there's a possibility of the template being different sizes i.e. 5x5, 7x7, 9x9 etc. How could I calculate the median of the array without having to write 'if(values.length == 25)' and 'if(values.length == 49)' etc??

Regards,
Guster
0
 
LVL 16

Accepted Solution

by:
imladris earned 50 total points
ID: 7180326
The median value for a sorted array would be in its middle. The middle can be calculated based on its length. For an even array there isn't an exact middle. I don't think you should get the two middle and divide by 2 if you want a median. One of the key differences between a median and an average is precisely that a median *is* one of the datapoints.

Anyway, the medianindex can be computed with:

int medianindex=value.length/2;

For an odd length array, this will give you the middle. For an even length array, it will give you the value to the "right" of the middle. To get the "left" one you could subtract one, if the array is even length (value.length%2==0). Code would be something like:

int medianindex=value.length/2+(value.length%2==0?-1:0);


If you must average the two you could get them both and divide. In total it could then look something like this to get the median:

int median;
if(value.length%2==0)
{   // even length case
    int ix=value.length/2;
    median=(value[ix-1]+value[ix])/2;
}
// odd length case
else median=value[value.length/2];

0
 

Author Comment

by:Guster
ID: 7180343
Hi,

In my program there's a possibility of the template being different sizes i.e. 5x5, 7x7, 9x9 etc. How could I calculate the median of the array without having to write 'if(values.length == 25)' and 'if(values.length == 49)' etc??

Regards,
Guster
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

An old method to applying the Singleton pattern in your Java code is to check if a static instance, defined in the same class that needs to be instantiated once and only once, is null and then create a new instance; otherwise, the pre-existing insta…
Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
Video by: Michael
Viewers learn about how to reduce the potential repetitiveness of coding in main by developing methods to perform specific tasks for their program. Additionally, objects are introduced for the purpose of learning how to call methods in Java. Define …
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now