jfeaturelib, java for glcm - java

I am doing my program using jfeaturelib for searching glcm features. I am using this haralick.java and already run my program perfectly using this demo HaralickDemo.java. All I want to know is how to use horizontal neigbhor 0 degree only or 90 degree only. This is the code:
private void calculate() {
calculateGreyValues();
final int imageWidth = image.getWidth();
final int imageHeight = image.getHeight();
final int d = HARALICK_DIST;
int i, j, pos;
// image is not empty per default
for (int y = 0; y < imageHeight; y++) {
for (int x = 0; x < imageWidth; x++) {
pos = imageWidth * y + x;
// horizontal neighbor: 0 degrees
i = x - d;
// j = y;
if (!(i < 0)) {
increment(grayValue[pos], grayValue[pos - d]);
}
// vertical neighbor: 90 degree
// i = x;
j = y - d;
if (!(j < 0)) {
increment(grayValue[pos], grayValue[pos - d * imageWidth]);
}
// 45 degree diagonal neigbor
i = x + d;
j = y - d;
if (i < imageWidth && !(j < 0)) {
increment(grayValue[pos], grayValue[pos + d - d * imageWidth]);
}
// 135 vertical neighbor
i = x - d;
j = y - d;
if (!(i < 0) && !(j < 0)) {
increment(grayValue[pos], grayValue[pos - d - d * imageWidth]);
}
}
}
And can you explain me detail of this haralick.java program?

Related

Rotate 2D array by alpha degrees

I wrote a function which takes two parameters:
JPG image as 3D array
rotation degrees given by alpha
My approach was:
public static int[][] rotate(int[][] img, double alpha) {
double rad = Math.toRadians(alpha);
double sin = Math.sin(rad);
double cos = Math.cos(rad);
int height = img.length;
int width = img[0].length;
int[][] rotate = new int[height][width];
for(int i = 0; i < height; i++) {
for(int j = height - i - 1; j < width; j++) {
if(j < height && i < width) {
double i_new = Math.floor(cos * (img[i].length - i) - sin * (img[j].length - j)) + i;
double j_new = Math.floor(sin * (img[i].length - i) + cos * (img[j].length - j)) + j;
rotate[i][j] = img[(int)j_new][(int)i_new];
}
}
}
return rotate;
}
While fixing the index range, the output is a black image. What am I missing?
After a while I got to a solution.
Caution: Its not using any special pre-defined libraries.
The global function which run`s over the matrice:
public static int[][] rotate(int[][] img, double alpha) {
double rad = Math.toRadians(alpha); //construct of the relevant angles
double sin = Math.sin(rad);
double cos = Math.cos(rad);
int height = img.length;
int width = img[0].length;
int[][] rotate = new int[height][width];
int a = height / 2; //we will use the area of a and b to compare coordinates by the formula given
int b = width / 2;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
double i_new = Math.floor(cos * (i - a) - sin * (j - b)) + a; // following the conversion function
double j_new = Math.floor(sin * (i - a) + cos * (j - b)) + b;
if (i_new >= rotate.length || i_new < 0 || j_new >= rotate[0].length || j_new < rotate[0][0]) { // if out of scope of the conversion --> print none
System.out.print(""); //mainly cause 'continue' statements are not necessary in java and JS
} else {
rotate[(int) i_new][(int) j_new] = img[i][j]; //convert
}
}
}
return rotate;
}
The global function which rotates each 2D matrice:
public static int[][][] rotate_alpha(int[][][] img, double alpha) {
int height = img[0].length;
int width = img[0][0].length;
int[][][] rotated = new int[3][height][width];
for (int k = 0; k < 3; k++) {
rotated[k] = rotate(img[k], alpha);
}
return rotated;
}
Hope this topic is solved by now, and stands by all the standards of the clean code.

Rendering section of a BufferedImage within a Rectangle

I am currently trying to draw just a section of a BufferedImage that is within the bounds of a Rectangle on the fly. The image gets moved, and thus the size of the image in the rectangle changes.
Visual depiction:
Currently, this is what I have and it works great with a low res image. But if I scale the minimap up, this becomes very inefficient and causes lag
private BufferedImage extractPixels() {
int[] imagePixels = new int[scaledImage.getWidth() * scaledImage.getHeight()];
scaledImage.getRGB(0, 0, scaledImage.getWidth(), scaledImage.getHeight(), imagePixels,
0, scaledImage.getWidth());
int maxX = 0, maxY = 0;
boolean first = false;
for (int y = 0; y < scaledImage.getHeight(); y++) {
for (int x = 0; x < scaledImage.getWidth(); x++) {
int px = (int)(this.x + x);
int py = (int)(this.y + y);
if (viewingArea.contains(px, py)) {
if (x > maxX) maxX = x;
if (y > maxY) maxY = y;
if (!first) {
imageX = x;
imageY = y;
first = true;
}
}
}
}
int xCount = maxX - imageX;
int yCount = maxY - imageY;
if (imageX < 0 || imageX > scaledImage.getWidth() || imageX + xCount > scaledImage.getWidth()) return null;
if (imageY < 0 || imageY > scaledImage.getHeight() || imageY + yCount > scaledImage.getHeight()) return null;
return scaledImage.getSubimage(imageX, imageY, xCount, yCount);
}
In Render loop:
public void Render(PixelRenderer renderer) {
BufferedImage image = extractPixels();
if (image != null) renderer.renderImage(image, x + imageX, y + imageY);
}
Is there a way to do this more efficiently, so that re-scaling has less of an effect on performance?
Fixed by calculating where the image should subimage from, and the size of the subimage dependent on the position of the main image.
private BufferedImage extractPixels() {
double xp = viewingArea.x - this.x;
double yp = viewingArea.y - this.y;
double iw = viewingArea.width;
double ih = viewingArea.height;
int rightBound = scaledImage.getWidth() - viewingArea.width;
int bottomBound = scaledImage.getHeight() - viewingArea.height;
if (xp < 0) {
xp = 0;
iw = viewingArea.width - (this.x - viewingArea.x);
imageX = viewingArea.x + (viewingArea.width - (int)iw);
} else if (xp >= 0 && xp < rightBound) {
xp -= dx;
iw -= dx;
imageX = viewingArea.x;
}
if (xp >= rightBound) {
iw = viewingArea.width - ((int)xp - (scaledImage.getWidth() - viewingArea.width));
imageX = viewingArea.x;
}
if (yp < 0) {
yp = 0;
ih = viewingArea.height - (this.y - viewingArea.y);
imageY = viewingArea.x + (viewingArea.height - (int)ih);
} else if (yp >= 0 && yp < bottomBound) {
yp -= dy;
ih -= dy;
imageY = viewingArea.y;
}
if (yp >= bottomBound) {
ih = viewingArea.height - ((int)yp - (scaledImage.getHeight() - viewingArea.height));
imageY = viewingArea.y;
}
if (iw < 0) iw = Math.abs(iw);
if (ih < 0) ih = Math.abs(ih);
if (xp < 0) xp = Math.abs(xp);
if (yp < 0) yp = Math.abs(yp);
BufferedImage result = new BufferedImage((int)iw, (int)ih, BufferedImage.TYPE_INT_RGB);
try {
result = scaledImage.getSubimage((int)xp, (int)yp, (int)iw, (int)ih);
} catch (Exception e) {
//TODO: Log to game engine something bad has happened
e.printStackTrace();
}
return result;
}

How to rotate a 2D array of pixels about it's "center"

I've been given a 2D array of pixels and I am suppose to rotate this image based off of the pixel array about it's centermost point. I've tried to implement code which rotates the image based off of the rotation matrix, but I haven't been successful so far.
Current 2D Array Rotation Code:
int width = originalImage.length;
int height = originalImage[0].length;
final double angle = 90;
int[][] array = new int[width][height];
double c = Math.cos(Math.toRadians(angle));
double s = Math.sin(Math.toRadians(angle));
int x = width / 2;
int y = height / 2;
for (int xx = 0; xx < width; xx++) {
for (int yy = 0; yy < height; yy++) {
int xp = xx - x;
int yp = yy - y;
int xa = (int)((float)((float)xp * c - (float)yp * s));
int ya = (int)((float)((float)xp * s + (float)yp * c));
xa += x;
ya += y;
xp += x;
yp += y;
if(xa < width && ya < height) array[xa][ya] = originalImage[xp][yp];
//System.out.print("\n"+xa+" "+ya);
}
}
I've also tried this:
int[][] array = new int[originalImage.length][originalImage[0].length];
int xx = 0, yy = 0;
for (int x = originalImage.length - 1; x >= 0; x--) {
xx = 0;
for (int y = 0; y < originalImage[x].length; y++) {
//System.out.println(array[yy][xx]);
//System.out.println(originalImage[y][x]);
if (y < originalImage.length && x < originalImage[x].length) {
array[yy][xx] = originalImage[y][x];
//System.out.print(array[yy][xx]);
}
xx++;
}
yy++;
}
Are there any suggestion to how I can improve my code, or how this should be done?
since you are rotating by 90 degrees you can skip a bit
// origin to center point
int xp = xx - x;
int yp = yy - y;
// rotation and origin back to (0,0)
int x_rotated = -yp + y;
int y_rotated = xp + x;
//
array[x_rotated][y_rotated] = originalImage[xx][yy];
If you want to rotate in a different direction change
int x_rotated = yp + y;
int y_rotated = -xp + x;

Rotate Bitmap pixels

I'm trying to rotate a Bitmap where the pixels are stored in an Array int pixels[]. I got the following method:
public void rotate(double angle) {
double radians = Math.toRadians(angle);
double cos, sin;
cos = Math.cos(radians);
sin = Math.sin(radians);
int[] pixels2 = pixels;
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++) {
int centerx = this.width / 2, centery = this.height / 2;
int m = x - centerx;
int n = y - centery;
int j = (int) (m * cos + n * sin);
int k = (int) (n * cos - m * sin);
j += centerx;
k += centery;
if (!((j < 0) || (j > this.width - 1) || (k < 0) || (k > this.height - 1)))
try {
pixels2[(x * this.width + y)] = pixels[(k * this.width + j)];
} catch (Exception e) {
e.printStackTrace();
}
}
pixels = pixels2;
}
But it just gives me crazy results. Does anyone know where the error is?
The line
int[] pixels2 = pixels;
is supposed to copy the array, but you are just copying the reference to it. Use pixels.clone(). In fact, you just need a new, empty array, so new int[pixels.lenght] is enough. In the end you need System.arraycopy to copy the new content into the old array.
There are other problems in your code -- you are mixing up rows and columns. Some expressions are written as though the image is stored row by row, others as if column by column. If row-by-row (my assumption), then this doesn't make sense: x*width + y. It should read y*width + x -- you are skipping y rows down and then moving x columns to the right. All in all, I have this code that works OK:
import static java.lang.System.arraycopy;
public class Test
{
private final int width = 5, height = 5;
private int[] pixels = {0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0};
public Test rotate(double angle) {
final double radians = Math.toRadians(angle),
cos = Math.cos(radians), sin = Math.sin(radians);
final int[] pixels2 = new int[pixels.length];
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++) {
final int
centerx = this.width / 2, centery = this.height / 2,
m = x - centerx,
n = y - centery,
j = ((int) (m * cos + n * sin)) + centerx,
k = ((int) (n * cos - m * sin)) + centery;
if (j >= 0 && j < width && k >= 0 && k < this.height)
pixels2[(y * width + x)] = pixels[(k * width + j)];
}
arraycopy(pixels2, 0, pixels, 0, pixels.length);
return this;
}
public Test print() {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++)
System.out.print(pixels[width*y + x]);
System.out.println();
}
System.out.println();
return this;
}
public static void main(String[] args) {
new Test().print().rotate(-45).print();
}
}
public void render(float nx, float ny, float nz, float size, float rotate) {
int wid = (int) ((width - nz) * size);
int hgt = (int) ((height - nz) * size);
if (wid < 0 || hgt < 0) {
wid = 0;
hgt = 0;
}
for (int x = 0; x < wid; x++) {
for (int y = 0; y < hgt; y++) {
double simple = Math.PI;
int xp = (int) (nx +
Math.cos(rotate) * ((x / simple) - (wid / simple) / 2) + Math
.cos(rotate + Math.PI / 2)
* ((y / simple) - (hgt / simple) / 2));
int yp = (int) (ny + Math.sin(rotate)
* ((x / simple) - (wid / simple) / 2) + Math.sin(rotate
+ Math.PI / 2)
* ((y / simple) - (hgt / simple) / 2));
if (xp + width < 0 || yp + height < 0 || xp >= Main.width
|| yp >= Main.height) {
break;
}
if (xp < 0
|| yp < 0
|| pixels[(width / wid) * x + ((height / hgt) * y)
* width] == 0xFFFF00DC) {
continue;
}
Main.pixels[xp + yp * Main.width] = pixels[(width / wid) * x
+ ((height / hgt) * y) * width];
}
}
}
This is only a new to rotating for me, but the process of this is that of a normal rotation. It still needs much fixing -- it's inefficient and slow. But in a small program, this code works. I'm posting this so you can take it, and make it better. :)

Processing/Line Graphing - Help

I posted something similar yesterday, but got nothing. I spent a few hours today problem-solving, but didn't progress any.
I'm using Processing (the language) and trying to implement a method that draws a line between two points. (I don't want to use the library's line() method.)
My lineCreate method works great for positive slopes, but fails with negative slopes. Can you help figure out why?
Here's the lineCreate() code:
void createLine(int x0, int y0, int x1, int y1){
//...
// Handle slanted lines...
double tempDX = x1 - x0;
double tempDY = y1 - y0; // Had to create dx and dy as doubles because typecasting dy/dx to a double data type wasn't working.
double m = (-tempDY / tempDX); // m = line slope. (Note - The dy value is negative
int deltaN = (2 * -dx); // deltaX is the amount to increment d after choosing the next pixel on the line.
int deltaNE = (2 * (-dy - dx)); // ...where X is the direction moved for that next pixel.
int deltaE = (2 * -dy); // deltaX variables are used below to plot line.
int deltaSE = (2 * (dy + dx));
int deltaS = (2 * dx);
int x = x0;
int y = y0;
int d = 0; // d = Amount d-value changes from pixel to pixel. Depends on slope.
int region = 0; // region = Variable to store slope region. Different regions require different formulas.
if(m > 1){ // if-statement: Initializes d, depending on the slope of the line.
d = -dy - (2 * dx); // If slope is 1-Infiniti. -> Use NE/N initialization for d.
region = 1;
}
else if(m == 1)
region = 2;
else if(m > 0 && m < 1){
d = (2 * -dy) - dx; // If slope is 0-1 -> Use NE/E initialization for d.
region = 3;
}
else if(m < 0 && m > -1){
d = (2 * dy) + dx; // If slope is 0-(-1) -> Use E/SE initliazation for d.
region = 4;
}
else if(m == -1)
region = 5;
else if(m < -1){
d = dy + (2 * dx); // If slope is (-1)-(-Infiniti) -> Use SE/S initialization for d.
region = 6;
}
while(x < x1){ // Until points are connected...
if(region == 1){ // If in region one...
if(d <= 0){ // and d<=0...
d += deltaNE; // Add deltaNE to d, and increment x and y.
x = x + 1;
y = y - 1;
}
else{
d += deltaN; // If d > 0 -> Add deltaN, and increment y.
y = y - 1;
}
}
else if(region == 2){
x = x + 1;
y = y - 1;
}
else if(region == 3){ // If region two...
if(d <= 0){
d += deltaE;
x = x + 1;
}
else{
d += deltaNE;
x = x + 1;
y = y - 1;
}
}
else if(region == 4){ // If region three...
if(d <= 0){
d += deltaSE;
x = x + 1;
y = y + 1;
}
else{
d += deltaE;
x = x + 1;
}
}
else if(region == 5){
x = x + 1;
y = y + 1;
}
else if(region == 6){ // If region four...
if(d <= 0){
d += deltaSE;
x = x + 1;
y = y + 1;
}
else{
d += deltaS;
y = y + 1;
}
}
point(x, y); // Paints new pixel on line going towards (x1,y1).
}
return;
}
Have a look at this page. It explains the whole theory behind line drawing with code examples.
There are a number of known algorithm for line drawing. Read about them here.

Categories