Image rotation algorithm for a square pixel grid - algorithm

I'm currently working on my own little online pixel editor.
Now I'm trying to add a rotation function.
But I can't quite figure out how to realize it.
Here is the basic query for my pixel grid:
for (var y = 0;y < pixelAmount;y++) {
for (var x = 0;x < pixelAmount;x++) {
var name = y + "x" + x;
newY = ?? ;
newX = ?? ;
if ($(newY + "x" + newX).style.backgroundColor != "rgb(255, 255, 255)")
{ $(name).style.backgroundColor = $(newY + "x" + newX).style.backgroundColor; }
}
}
How do I calculate newY and newX?

How do you rotate a two dimensional array?
from this^ post I got this method (in c#):
int a[4][4];
int n=4;
int tmp;
for (int i=0; i<n/2; i++){
for (int j=i; j<n-i-1; j++){
tmp=a[i][j];
a[i][j]=a[j][n-i-1];
a[j][n-i-1]=a[n-i-1][n-j-1];
a[n-i-1][n-j-1]=a[n-j-1][i];
a[n-j-1][i]=tmp;
}
}
or this one:
int[,] array = new int[4,4] {
{ 1,2,3,4 },
{ 5,6,7,8 },
{ 9,0,1,2 },
{ 3,4,5,6 }
};
int[,] rotated = RotateMatrix(array, 4);
static int[,] RotateMatrix(int[,] matrix, int n) {
int[,] ret = new int[n, n];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
ret[i, j] = matrix[n - j - 1, i];
}
}
return ret;
}
the first method doesn't use a second array (/matrix) to save memory..

Take a look at this doc (Section 3: Rotating a bitmap with an angle of any value). It walks you through how to do the math and gives you some sample code (C++, but it should be good enough for what you need).

If very quick performance is not of huge importance (which is the case by default), you can consider rotating the picture clockwise by flipping it against the main diagonal and then horizontally. To rotate counterclockwise, flip horizontally, then against the main diagonal. The code is much simpler.
For diagonal flip you exchange the values of image[x,y] with image[y,x] in a loop like this
for( var x = 0; x < pixelAmount; ++x )
for( var y = x + 1; y < pixelAmount; ++y )
swap(image[x,y],image[y,x]);
For horizontal flip you do something like
for( var y = 0; y < pixelAmount; ++y )
{
i = 0; j = pixelAmount - 1;
while( i < j ) {
swap( image[i,y], image[j,y] );
++i; --j;
}
}

Related

p5.js image histogram equalization

It's easy to blend() two images using p5.js, which is great, but I would like to be able to equalize the histogram of the resulting blended image. Something like -equalize in ImageMagick. Does anyone know how to do this in p5.js?
You can do this, sure. Algo: For each channel calculate cumulative normalized histograms multiplied by maximum value in that channel - this will be your new pixel values in channel given old value.
I've read algo description in GeeksforGeeks portal and ported it to p5.js, code:
let img
let mod
// helpers
function getMappings() {
hists = [[], [], []];
newlevels = [[], [], []];
maxval = [-1, -1, -1];
// RGB histograms & maximum pixel values
for (let i = 0; i < img.width; i++) {
for (let j = 0; j < img.height; j++) {
let c = img.get(i, j);
hists[0][c[0]] = (hists[0][c[0]] || 0) + 1;
hists[1][c[1]] = (hists[1][c[1]] || 0) + 1;
hists[2][c[2]] = (hists[2][c[2]] || 0) + 1;
for (let ch=0; ch < 3; ch++) {
if (c[ch] > maxval[ch]) {
maxval[ch] = c[ch];
}
}
}
}
// New intensity levels based on cumulative, normalized histograms
for (let hi = 0; hi < 3; hi++) {
let acc = 0;
for (let lev=0; lev < 256; lev++) {
acc += hists[hi][lev];
newlevels[hi][lev] = Math.round(maxval[hi]*acc/(img.width*img.height));
}
}
return newlevels;
}
function equalizeHistograms() {
let map = getMappings();
for (let i = 0; i < mod.width; i++) {
for (let j = 0; j < mod.height; j++) {
let c = img.get(i, j);
let newcol = color(map[0][c[0]], map[1][c[1]], map[2][c[2]]);
mod.set(i, j, newcol);
}
}
mod.updatePixels();
}
// system functions
function preload() {
img = loadImage('https://i.imgur.com/00HxCYr.jpg');
mod = createImage(200, 140);
}
function setup() {
img.loadPixels();
mod.loadPixels();
createCanvas(250, 400);
equalizeHistograms();
}
function draw() {
image(img,0,0);
image(mod,0,140);
}
DEMO

Processing For loop sequence

I am attempting to draw several ellipses in sequence along the y and x axis of the canvas. The dots are drawn at randomised y positions.
I previously had the ellipses drawing at random heights sequentially along the x-axis. However, all ellipses along the y-axis were drawn at once.
for (int x = 0; x < xStep; x++) {
int mh = int(map(noise(offset+(x*0.05)), 0, 1, 0, h));
for (int y = mh; y > mh - 3; y--) {
ellipse(x*diam, y*diam, diam, diam);
}
}
xStep++;
if (xStep > w) {
xStep = 0;
offset = random(1000);
}
I then moved on to add another for loop to try sequence the ellipses along the y-axis as well as the x-axis. So visually each ellipse is drawn one after the other on the y-axis before the next column (x-axis) is drawn. However, using the code below what I get instead is the y and x-axis 'drawing' in sequence but at the same time so visually it does not look like one row completes before the next column is drawn.
//count rows and frames
if (counter > 7) {
counter = 0;
rowCounter++;
}
for (int j=0; j<7; j++) { //set values to match counter
if (j == counter){
for (int x = 0; x < xStep; x++) {
int mh = int(map(noise(offset+(x*0.05)), 0, 1, 0, h));
for (int y = mh; y > mh - 3; y--) {
y=y-j;
ellipse(x*diam, y*diam, diam, diam);
}
}
}
}
xStep++;
counter++;
if (rowCounter > 7) {
rowCounter = 0;
}
if (xStep > w) {
xStep = 0;
offset = random(1000);
}
Or if I try using a conditional for the xStep I only get one row of ellipses drawn.
//count rows and frames
if (counter > 7) {
counter = 0;
rowCounter++;
}
for (int j=0; j<7; j++) { //set values to match counter
if ((j == counter) && (xStep != lastXstep)) {
for (int x = 0; x < xStep; x++) {
int mh = int(map(noise(offset+(x*0.05)), 0, 1, 0, h));
for (int y = mh; y > mh - 3; y--) {
y=y-j;
ellipse(x*diam, y*diam, diam, diam);
xStep=lastXstep;
}
}
}
}
xStep++;
counter++;
if (rowCounter > 7) {
rowCounter = 0;
}
if (xStep > w) {
xStep = 0;
offset = random(1000);
}
Can anyone help point me in the direction of where I am going wrong with the for loop construction?
Thanks.
Keep in mind that every call to the draw() function draws a single frame. Processing is double-buffered, so the screen is not updated until the very end of the draw() function. That's why you're only seeing the end result instead of the in-between steps.
If you want to render the in-between steps, you're going to have to split it up into multiple frames. You'd do that by keeping track of the state of your program in a set of variables, changing those variables over time, and using those variables to draw each frame.
Shameless self-promotion: here is a tutorial on animation in Processing that describes the above approach in greater detail.

Polynomial multiplication in M2(R)?

I was trying to implement a FFT-based multiplication algorithm in M2(R). Basically an algorithm that gets as an input two polynoms with elements given as matrices, and builds the product polynom. However, even though the algorithm should work, as it looks exactly identical to a version I wrote earlier on regular number, it doesn't. The coefficients are always off by a little.
I have not found any articles on the roots of unity in M2(C), but I have found(on paper) that choosing eps = ((cos(2PI/n) , i sin(2PI/n)) , ( i sin(2PI/n) , cos(2PI/n))), I get a nice cycle.
Is there something wrong in my approach?
Here is the code:
struct FFT {
PolyC To, Aux[17][2], Res[17][2], AC, BC, ResC, ResD, ArgA, ArgB;
void fft(PolyC V, var depth, var n, PolyC To, MatC step) {
if(n == 1) {
To[0] = V[0];
} else {
MatC eps = matCHelper.I2;
//We "split" the poly in 2
for(var i=0; i<n; i++)
Aux[depth+1][i&1][i>>1] = V[i];
//We recursively apply FFT to the components
fft(Aux[depth+1][0], depth+1, n/2, Res[depth+1][0], step*step);
fft(Aux[depth+1][1], depth+1, n/2, Res[depth+1][1], step*step);
//We compute the result for the n roots
for(var i=0; i<n/2; i++) {
To[i] = Res[depth+1][0][i] + eps * Res[depth+1][1][i];
To[n/2+i] = Res[depth+1][0][i] - eps * Res[depth+1][1][i];
eps = eps * step;
}
}
}
void FFTMultiply(Poly Res, Poly A, Poly B, var n1, var n2) {
var M;
for(M = 1; M <= 2*n1 || M <= 2*n2; M <<= 1);
for(var i=0; i<n1; i++) ArgA[i] = A[i];
for(var i=n1; i<M; i++) ArgA[i] = matCHelper.O2;
for(var i=0; i<n2; i++) ArgB[i] = B[i];
for(var i=n2; i<M; i++) ArgB[i] = matCHelper.O2;
MatC step( Complex(cos(2*PI/M), 0) , Complex(0, sin(2*PI/M)),
Complex(0, sin(2*PI/M)) , Complex(cos(2*PI/M), 0) );
fft(ArgA, 0, M, AC, step);
fft(ArgB, 0, M, BC, step);
for(var i=0; i<M; i++) {
RezC[i] = AC[i] * BC[i];
}
step.b = -step.b;
step.c = -step.c;
fft(RezC, 0, M, RezD, step);
for(var i=0; i<M; i++) {
// Now I divided everything by M and copied every element of ResD to Res modulo some number
}
}
};
You can not expect this method to work if your coefficient matrices do not commute with your matrix step. To get it working correctly, use the diagonal matrix corresponding to multiplication with the scalar exp(i*2*PI/M).

Connected Component Labeling - Implementation

I have asked a similar question some days ago, but I have yet to find an efficient way of solving my problem.
I'm developing a simple console game, and I have a 2D array like this:
1,0,0,0,1
1,1,0,1,1
0,1,0,0,1
1,1,1,1,0
0,0,0,1,0
I am trying to find all the areas that consist of neighboring 1's (4-way connectivity). So, in this example the 2 areas are as following:
1
1,1
1
1,1,1,1
1
and :
1
1,1
1
The algorithm, that I've been working on, finds all the neighbors of the neighbors of a cell and works perfectly fine on this kind of matrices. However, when I use bigger arrays (like 90*90) the program is very slow and sometimes the huge arrays that are used cause stack overflows.
One guy on my other question told me about connected-component labelling as an efficient solution to my problem.
Can somebody show me any C++ code which uses this algorithm, because I'm kinda confused about how it actually works along with this disjoint-set data structure thing...
Thanks a lot for your help and time.
I'll first give you the code and then explain it a bit:
// direction vectors
const int dx[] = {+1, 0, -1, 0};
const int dy[] = {0, +1, 0, -1};
// matrix dimensions
int row_count;
int col_count;
// the input matrix
int m[MAX][MAX];
// the labels, 0 means unlabeled
int label[MAX][MAX];
void dfs(int x, int y, int current_label) {
if (x < 0 || x == row_count) return; // out of bounds
if (y < 0 || y == col_count) return; // out of bounds
if (label[x][y] || !m[x][y]) return; // already labeled or not marked with 1 in m
// mark the current cell
label[x][y] = current_label;
// recursively mark the neighbors
for (int direction = 0; direction < 4; ++direction)
dfs(x + dx[direction], y + dy[direction], current_label);
}
void find_components() {
int component = 0;
for (int i = 0; i < row_count; ++i)
for (int j = 0; j < col_count; ++j)
if (!label[i][j] && m[i][j]) dfs(i, j, ++component);
}
This is a common way of solving this problem.
The direction vectors are just a nice way to find the neighboring cells (in each of the four directions).
The dfs function performs a depth-first-search of the grid. That simply means it will visit all the cells reachable from the starting cell. Each cell will be marked with current_label
The find_components function goes through all the cells of the grid and starts a component labeling if it finds an unlabeled cell (marked with 1).
This can also be done iteratively using a stack.
If you replace the stack with a queue, you obtain the bfs or breadth-first-search.
This can be solved with union find (although DFS, as shown in the other answer, is probably a bit simpler).
The basic idea behind this data structure is to repeatedly merge elements in the same component. This is done by representing each component as a tree (with nodes keeping track of their own parent, instead of the other way around), you can check whether 2 elements are in the same component by traversing to the root node and you can merge nodes by simply making the one root the parent of the other root.
A short code sample demonstrating this:
const int w = 5, h = 5;
int input[w][h] = {{1,0,0,0,1},
{1,1,0,1,1},
{0,1,0,0,1},
{1,1,1,1,0},
{0,0,0,1,0}};
int component[w*h];
void doUnion(int a, int b)
{
// get the root component of a and b, and set the one's parent to the other
while (component[a] != a)
a = component[a];
while (component[b] != b)
b = component[b];
component[b] = a;
}
void unionCoords(int x, int y, int x2, int y2)
{
if (y2 < h && x2 < w && input[x][y] && input[x2][y2])
doUnion(x*h + y, x2*h + y2);
}
int main()
{
for (int i = 0; i < w*h; i++)
component[i] = i;
for (int x = 0; x < w; x++)
for (int y = 0; y < h; y++)
{
unionCoords(x, y, x+1, y);
unionCoords(x, y, x, y+1);
}
// print the array
for (int x = 0; x < w; x++)
{
for (int y = 0; y < h; y++)
{
if (input[x][y] == 0)
{
cout << ' ';
continue;
}
int c = x*h + y;
while (component[c] != c) c = component[c];
cout << (char)('a'+c);
}
cout << "\n";
}
}
Live demo.
The above will show each group of ones using a different letter of the alphabet.
p i
pp ii
p i
pppp
p
It should be easy to modify this to get the components separately or get a list of elements corresponding to each component. One idea is to replace cout << (char)('a'+c); above with componentMap[c].add(Point(x,y)) with componentMap being a map<int, list<Point>> - each entry in this map will then correspond to a component and give a list of points.
There are various optimisations to improve the efficiency of union find, the above is just a basic implementation.
You could also try this transitive closure approach, however the triple loop for the transitive closure slows things up when there are many separated objects in the image, suggested code changes welcome
Cheers
Dave
void CC(unsigned char* pBinImage, unsigned char* pOutImage, int width, int height, int CON8)
{
int i, j, x, y, k, maxIndX, maxIndY, sum, ct, newLabel=1, count, maxVal=0, sumVal=0, maxEQ=10000;
int *eq=NULL, list[4];
int bAdd;
memcpy(pOutImage, pBinImage, width*height*sizeof(unsigned char));
unsigned char* equivalences=(unsigned char*) calloc(sizeof(unsigned char), maxEQ*maxEQ);
// modify labels this should be done with iterators to modify elements
// current column
for(j=0; j<height; j++)
{
// current row
for(i=0; i<width; i++)
{
if(pOutImage[i+j*width]>0)
{
count=0;
// go through blocks
list[0]=0;
list[1]=0;
list[2]=0;
list[3]=0;
if(j>0)
{
if((i>0))
{
if((pOutImage[(i-1)+(j-1)*width]>0) && (CON8 > 0))
list[count++]=pOutImage[(i-1)+(j-1)*width];
}
if(pOutImage[i+(j-1)*width]>0)
{
for(x=0, bAdd=true; x<count; x++)
{
if(pOutImage[i+(j-1)*width]==list[x])
bAdd=false;
}
if(bAdd)
list[count++]=pOutImage[i+(j-1)*width];
}
if(i<width-1)
{
if((pOutImage[(i+1)+(j-1)*width]>0) && (CON8 > 0))
{
for(x=0, bAdd=true; x<count; x++)
{
if(pOutImage[(i+1)+(j-1)*width]==list[x])
bAdd=false;
}
if(bAdd)
list[count++]=pOutImage[(i+1)+(j-1)*width];
}
}
}
if(i>0)
{
if(pOutImage[(i-1)+j*width]>0)
{
for(x=0, bAdd=true; x<count; x++)
{
if(pOutImage[(i-1)+j*width]==list[x])
bAdd=false;
}
if(bAdd)
list[count++]=pOutImage[(i-1)+j*width];
}
}
// has a neighbour label
if(count==0)
pOutImage[i+j*width]=newLabel++;
else
{
pOutImage[i+j*width]=list[0];
if(count>1)
{
// store equivalences in table
for(x=0; x<count; x++)
for(y=0; y<count; y++)
equivalences[list[x]+list[y]*maxEQ]=1;
}
}
}
}
}
// floyd-Warshall algorithm - transitive closure - slow though :-(
for(i=0; i<newLabel; i++)
for(j=0; j<newLabel; j++)
{
if(equivalences[i+j*maxEQ]>0)
{
for(k=0; k<newLabel; k++)
{
equivalences[k+j*maxEQ]= equivalences[k+j*maxEQ] || equivalences[k+i*maxEQ];
}
}
}
eq=(int*) calloc(sizeof(int), newLabel);
for(i=0; i<newLabel; i++)
for(j=0; j<newLabel; j++)
{
if(equivalences[i+j*maxEQ]>0)
{
eq[i]=j;
break;
}
}
free(equivalences);
// label image with equivalents
for(i=0; i<width*height; i++)
{
if(pOutImage[i]>0&&eq[pOutImage[i]]>0)
pOutImage[i]=eq[pOutImage[i]];
}
free(eq);
}
very useful Document => https://docs.google.com/file/d/0B8gQ5d6E54ZDM204VFVxMkNtYjg/edit
java application - open source - extract objects from image - connected componen labeling => https://drive.google.com/file/d/0B8gQ5d6E54ZDTVdsWE1ic2lpaHM/edit?usp=sharing
import java.util.ArrayList;
public class cclabeling
{
int neighbourindex;ArrayList<Integer> Temp;
ArrayList<ArrayList<Integer>> cc=new ArrayList<>();
public int[][][] cclabel(boolean[] Main,int w){
/* this method return array of arrays "xycc" each array contains
the x,y coordinates of pixels of one connected component
– Main => binary array of image
– w => width of image */
long start=System.nanoTime();
int len=Main.length;int id=0;
int[] dir={-w-1,-w,-w+1,-1,+1,+w-1,+w,+w+1};
for(int i=0;i<len;i+=1){
if(Main[i]){
Temp=new ArrayList<>();
Temp.add(i);
for(int x=0;x<Temp.size();x+=1){
id=Temp.get(x);
for(int u=0;u<8;u+=1){
neighbourindex=id+dir[u];
if(Main[neighbourindex]){
Temp.add(neighbourindex);
Main[neighbourindex]=false;
}
}
Main[id]=false;
}
cc.add(Temp);
}
}
int[][][] xycc=new int[cc.size()][][];
int x;int y;
for(int i=0;i<cc.size();i+=1){
xycc[i]=new int[cc.get(i).size()][2];
for(int v=0;v<cc.get(i).size();v+=1){
y=Math.round(cc.get(i).get(v)/w);
x=cc.get(i).get(v)-y*w;
xycc[i][v][0]=x;
xycc[i][v][1]=y;
}
}
long end=System.nanoTime();
long time=end-start;
System.out.println("Connected Component Labeling Time =>"+time/1000000+" milliseconds");
System.out.println("Number Of Shapes => "+xycc.length);
return xycc;
}
}
Please find below the sample code for connected component labeling . The code is written in JAVA
package addressextraction;
public class ConnectedComponentLabelling {
int[] dx={+1, 0, -1, 0};
int[] dy={0, +1, 0, -1};
int row_count=0;
int col_count=0;
int[][] m;
int[][] label;
public ConnectedComponentLabelling(int row_count,int col_count) {
this.row_count=row_count;
this.col_count=col_count;
m=new int[row_count][col_count];
label=new int[row_count][col_count];
}
void dfs(int x, int y, int current_label) {
if (x < 0 || x == row_count) return; // out of bounds
if (y < 0 || y == col_count) return; // out of bounds
if (label[x][y]!=0 || m[x][y]!=1) return; // already labeled or not marked with 1 in m
// mark the current cell
label[x][y] = current_label;
// System.out.println("****************************");
// recursively mark the neighbors
int direction = 0;
for (direction = 0; direction < 4; ++direction)
dfs(x + dx[direction], y + dy[direction], current_label);
}
void find_components() {
int component = 0;
for (int i = 0; i < row_count; ++i)
for (int j = 0; j < col_count; ++j)
if (label[i][j]==0 && m[i][j]==1) dfs(i, j, ++component);
}
public static void main(String[] args) {
ConnectedComponentLabelling l=new ConnectedComponentLabelling(4,4);
l.m[0][0]=0;
l.m[0][1]=0;
l.m[0][2]=0;
l.m[0][3]=0;
l.m[1][0]=0;
l.m[1][1]=1;
l.m[1][2]=0;
l.m[1][3]=0;
l.m[2][0]=0;
l.m[2][1]=0;
l.m[2][2]=0;
l.m[2][3]=0;
l.m[3][0]=0;
l.m[3][1]=1;
l.m[3][2]=0;
l.m[3][3]=0;
l.find_components();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
System.out.print(l.label[i][j]);
}
System.out.println("");
}
}
}

cvDilate/cvErode: How to avoid connection between separated objects?

I would like to separate objects in OpenCv like the following image it shows:
But if I am using cvDilate or cvErode the objects grow together... how to do that with OpenCv?
It looks like you will need to write your own dilate function and then add xor functionality yourself.
Per the opencv documentation, here is the rule that cvdilate uses:
dst=dilate(src,element): dst(x,y)=max((x',y') in element))src(x+x',y+y')
Here is pseudocode for a starting point (this does not include xor code):
void my_dilate(img) {
for(i = 0; i < img.height; i++) {
for(j = 0; j < img.width; j++) {
max_pixel = get_max_pixel_in_window(img, i, j);
img.pixel(i,j) = max_pixel;
}
}
}
int get_max_pixel_in_window(img, center_row, center_col) {
int window_size = 3;
int cur_max = 0;
for(i = -window_size; i <= window_size; i++) {
for(j = -window_size; j <= window_size; j++) {
int cur_col = center_col + i;
int cur_row = center_row + j;
if(out_of_bounds(img, cur_col, cur_row)) {
continue;
}
int cur_pix = img.pixel(center_row + i, center_col + j);
if(cur_pix > cur_max) {
cur_max = cur_pix;
}
}
}
return cur_max;
}
// returns true if the x, y coordinate is outside of the image
int out_of_bounds(img, x, y) {
if(x >= img.width || x < 0 || y >= img.height || y <= 0) {
return 1;
}
return 0;
}
As far as I know OpenCV does not have "dilation with XOR" (although that would be very nice to have).
To get similar results you might try eroding (as in 'd'), and using the eroded centers as seeds for a Voronoi segmentation which you could then AND with the original image.
after erosion and dilate try thresholding the image to eliminate weak elements. Only strong regions should remain and thus improve the object separation. By the way could you be a little more clear about your problem with cvDilate or cvErode.

Resources