Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

May seem strange at first, but can you make mathematica change the value of 0 to 10 and 11 to 1 for all occurrences. Let me explain:

I'm looping through a matrix and for each element, I want something to happen depending on the values in each element above, below, to the left and to the right. When you're at the first element however there is nothing to the left, or above, so instead I would like to use the values on either side of the matrix as if you'd curled the matrix back round onto itself, as shown below.

X denotes what element you're looking at and then T,B,L & R, correspond to the cells at the Top, bottom, to the left & right respectively. Here's the code I wrote without thinking too much and it throws up an error because it asks for elements that do no exist. (e.g. "i-1" when i=1)

Do[
  Do[
{n, m} = RandomChoice[{image[[i + 1, j]], image[[i, j + 1]], 
image[[i - 1, j]], image[[i,j - 1]]} -> {{i + 1, j}, {i, j + 1}, {i - 1, j}, {i,j - 1}}];
newimage[[n, m]] = image[[i, j]];
, {j, columns}];
  , {i, rows}];

So, without whacking loads of If statements in there, is there an elegant way to accomplish this?

Hope I explained this half decently.

share|improve this question
    
Mod seems like a quick fix, but would be neat with some Periodic attribute to a SparseArray –  ssch Mar 31 '13 at 0:33
    
@ssch oh yeah Mod would be a quick and easy way around. thanks :) –  TomJS Mar 31 '13 at 1:12
    
@ssch hmm although not sure that helps me when i=1 as then i-1=0 and Mod doesn't help there –  TomJS Mar 31 '13 at 1:15
2  
Check out the offset argument: Mod[0,10,1]==10 –  ssch Mar 31 '13 at 1:18
    
@ssch perfect!! –  TomJS Mar 31 '13 at 1:23

3 Answers 3

up vote 2 down vote accepted

ImageFilter is also a good solution here, and you can create any filtering action you want. In outline, this would look something like:

myFun[x_] := Module[{},(* Your code here*)];
ImageFilter[myFun, img, n]

where myFun takes as input a (2n+1) by (2n+1) array of pixel/matrix values and calculates a single output. The ImageFilter command applies myFun to every (2n+1) by (2n+1) block in the image, and handles the edge conditions easily using the Padding option.

share|improve this answer
    
thanks, i'll try this out –  TomJS Mar 31 '13 at 13:05
    
Here's a Wolfram demo that uses this technique: demonstrations.wolfram.com/AdaptiveThresholdingOfImages The thing I remember when writing this demo is that it is very important to make sure that your function takes the proper inputs and gives back the proper outputs. Otherwise, all is lost... –  bill s Mar 31 '13 at 13:10

As a direct answer you could use replacement, e.g.:

{-1, 0, 1, 10, 11, 12} /. {0 -> 10, 11 -> 1}
{-1, 10, 1, 10, 1, 12}

But more significantly this problem can likely be handled better by built-in functions that already make allowance for wrapping around, or by padding the array to start with. I am looking at this now.

share|improve this answer
    
I did think about padding, but then thought it could be fun (see the comment on other answer about turning an image into a many body gravitational problem) to wrap the matrix around on itself so there are no boundaries. –  TomJS Mar 31 '13 at 0:55
    
@Thomas I believe there is another question specifically about wrapping indicies and I believe that the answer there was to use Mod as ssch recommended in a comment. Is your code example actually representative of what you want to do? I'd be happy to explore other ways to approach this. –  Mr.Wizard Mar 31 '13 at 4:49
    
Yes, that is mu code so far, apart from a bit at the top to load an image and turn it into image data and a part at the bottom to display the new image. I'm happy with the Mod trick, seems to get the job done :) –  TomJS Mar 31 '13 at 13:03

Going by your choice of example (which is incomplete) and the variables used, I'm guessing you want to perform some operations on an image in which the output for each pixel depends on its immediate neighbours one city block apart.

For this, you can use a CrossMatrix as a convolution kernel and ImageConvolve will handle the edges for you.

CrossMatrix[1]
(* {{0, 1, 0}, {1, 1, 1}, {0, 1, 0}} *)

For example, here is what you get if you convolve Lena with a cross matrix:

With[{lena = ExampleData[{"TestImage", "Lena"}]}, 
    ImageConvolve[lena, CrossMatrix[1]]]

This might be all that you need to proceed, but unless you provide more information, it's hard to say what exactly it is that you need.

share|improve this answer
    
What if the data isn't an image? –  Mr.Wizard Mar 31 '13 at 0:39
    
Apologies for the limited information, always a fine balance between under and over explaining. I've started toying with the idea of reading in black and white images into an array and then letting those images evolve under some kind of many-body problem, where the grayscale values of each pixel interact with each other and producing a video from it. For example pretend the grayscale value corresponds to mass and see how all the pixels of the original image form clusters etc. I dunno, experimenting with abstract mathematica art. But this looping problem is something that cropped up –  TomJS Mar 31 '13 at 0:52
    
@Mr.Wizard See the answer they chose to accept... –  rm -rf Mar 31 '13 at 13:55

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.