Wie dieses Muster am einfachsten erkennen?

123neu

Bekanntes Mitglied
Hallo, wie (also mit welchem Algorithmus) kann ich die Position dieses charakteristischen Musters auf dem Bildschirm:

1618407277878.png

am einfachsten erkennen, unabhängig der Größe, Position, Farbe der Kästchen, Ränder und Figurenstellung?

Danke 😊
 

123neu

Bekanntes Mitglied
@mihe7 kannst du mir sagen, was hier falsch ist?

bsp_2.jpg

Es berechnet "irgendwas"...

Ist meine drawLine()-Methode falsch?
Warum wird (im Orginalcode) getHighestValue() und getHoughArrayImage() nicht aufgerufen?

Hier ist der Spaß:

Java:
import java.awt.AWTException;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;

import java.util.ArrayList;

import javax.swing.JFrame;

public class FindTemplate {
    public static class HoughLine {
        private double theta;
        private int r;

        public HoughLine(double theta, int r) {
            this.theta = theta;
            this.r = r;
        }

        public double getTheta() {
            return theta;
        }

        public void setTheta(double theta) {
            this.theta = theta;
        }

        public int getR() {
            return r;
        }

        public void setR(int r) {
            this.r = r;
        }

        public void drawLine(Graphics2D g2d, Color col, int w) {
            double startX = 0;
            double startY = r;
            double endX = startX + w * Math.sin(theta);
            double endY = startY + w * Math.cos(theta);
            g2d.setColor(col);
            g2d.drawLine((int) startX, (int) startY, (int) endX, (int) endY);
        }
    }

    public static void main(String[] args) throws AWTException, InterruptedException {
        Robot robot = new Robot();
        Rectangle rect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());

        Thread.sleep(10_000);

        BufferedImage img = robot.createScreenCapture(rect);
        ArrayList<FindTemplate.HoughLine> lines = getLines(img, 30);

        JFrame f = new JFrame();
        Canvas c = new Canvas() {
            private static final long serialVersionUID = 1L;

            @Override
            public void paint(Graphics g) {
                Graphics2D g2d = (Graphics2D) g;
                for (HoughLine houghLine : lines) {
                    houghLine.drawLine(g2d, Color.red, this.getWidth());
                }
            }
        };
        f.add(c);
        f.setSize(rect.getSize());
        f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        f.setVisible(true);
    }

    public static ArrayList<HoughLine> getLines(BufferedImage img, int threshold) {
        // The size of the neighbourhood in which to search for other local maxima
        final int neighbourhoodSize = 4;

        // Calculate the maximum height the hough array needs to have
        final int houghHeight = (int) (Math.sqrt(2) * Math.max(img.getHeight(), img.getWidth())) / 2;

        // Double the height of the hough array to cope with negative r values
        final int doubleHeight = 2 * houghHeight;

        // How many discrete values of theta shall we check?
        final int maxTheta = 180;

        // Using maxTheta, work out the step
        final double thetaStep = Math.PI / maxTheta;

        // Create the hough array
        final int[][] houghArray = new int[maxTheta][doubleHeight];

        // Find edge points and vote in array
        final int centerX = img.getWidth() / 2;
        final int centerY = img.getHeight() / 2;

        // cache the values of sin and cos for faster processing
        final double[] sinCache = new double[maxTheta];
        final double[] cosCache = sinCache.clone();
        for (int t = 0; t < maxTheta; t++) {
            double realTheta = t * thetaStep;
            sinCache[t] = Math.sin(realTheta);
            cosCache[t] = Math.cos(realTheta);
        }
        // Now find edge points and update the hough array
        for (int x = 0; x < img.getWidth(); x++) {
            for (int y = 0; y < img.getHeight(); y++) {
                // Go through each value of theta
                for (int t = 0; t < maxTheta; t++) {
                    // Work out the r values for each theta step
                    int r = (int) (((x - centerX) * cosCache[t]) + ((y - centerY) * sinCache[t]));

                    // this copes with negative values of r
                    r += houghHeight;

                    if (r < 0 || r >= doubleHeight)
                        continue;

                    // Increment the hough array
                    houghArray[t][r]++;
                }
            }
        }

        // Initialise the vector of lines that we'll return
        ArrayList<HoughLine> lines = new ArrayList<HoughLine>(20);

        // Only proceed if the hough array is not empty
        // if (numPoints == 0) return lines;

        // Search for local peaks above threshold to draw
        for (int t = 0; t < maxTheta; t++) {
            loop: for (int r = neighbourhoodSize; r < doubleHeight - neighbourhoodSize; r++) {

                // Only consider points above threshold
                if (houghArray[t][r] > threshold) {

                    int peak = houghArray[t][r];

                    // Check that this peak is indeed the local maxima
                    for (int dx = -neighbourhoodSize; dx <= neighbourhoodSize; dx++) {
                        for (int dy = -neighbourhoodSize; dy <= neighbourhoodSize; dy++) {
                            int dt = t + dx;
                            int dr = r + dy;
                            if (dt < 0)
                                dt = dt + maxTheta;
                            else if (dt >= maxTheta)
                                dt = dt - maxTheta;
                            if (houghArray[dt][dr] > peak) {
                                // found a bigger point nearby, skip
                                continue loop;
                            }
                        }
                    }

                    // calculate the true value of theta
                    double theta = t * thetaStep;

                    // add the line to the vector
                    lines.add(new HoughLine(theta, r));

                }
            }
        }

        return lines;
    }
}
 

123neu

Bekanntes Mitglied
Ja du hast recht, es fehlte nämlich noch:

Java:
// Find non-black pixels
if ((image.getRGB(x, y) & 0x000000ff) != 0) {

also

[CODE lang="java" highlight="112-113, 128"]import java.awt.AWTException;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;

import java.util.ArrayList;

import javax.swing.JFrame;

public class FindTemplate {
public static class HoughLine {
private double theta;
private int r;

public HoughLine(double theta, int r) {
this.theta = theta;
this.r = r;
}

public double getTheta() {
return theta;
}

public void setTheta(double theta) {
this.theta = theta;
}

public int getR() {
return r;
}

public void setR(int r) {
this.r = r;
}

public void drawLine(Graphics2D g2d, Color col, int w) {
double startX = 0;
double startY = r;
double endX = startX + w * Math.sin(theta);
double endY = startY + w * Math.cos(theta);
g2d.setColor(col);
g2d.drawLine((int) startX, (int) startY, (int) endX, (int) endY);
}
}

public static void main(String[] args) throws AWTException, InterruptedException {
Robot robot = new Robot();
Rectangle rect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());

Thread.sleep(10_000);

BufferedImage img = robot.createScreenCapture(rect);
ArrayList<FindTemplate.HoughLine> lines = getLines(img, 30);

JFrame f = new JFrame();
Canvas c = new Canvas() {
private static final long serialVersionUID = 1L;

@Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
for (HoughLine houghLine : lines) {
houghLine.drawLine(g2d, Color.red, this.getWidth());
}
}
};
f.add(c);
f.setSize(rect.getSize());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setVisible(true);
}

public static ArrayList<HoughLine> getLines(BufferedImage img, int threshold) {
// The size of the neighbourhood in which to search for other local maxima
final int neighbourhoodSize = 4;

// Calculate the maximum height the hough array needs to have
final int houghHeight = (int) (Math.sqrt(2) * Math.max(img.getHeight(), img.getWidth())) / 2;

// Double the height of the hough array to cope with negative r values
final int doubleHeight = 2 * houghHeight;

// How many discrete values of theta shall we check?
final int maxTheta = 180;

// Using maxTheta, work out the step
final double thetaStep = Math.PI / maxTheta;

// Create the hough array
final int[][] houghArray = new int[maxTheta][doubleHeight];

// Find edge points and vote in array
final int centerX = img.getWidth() / 2;
final int centerY = img.getHeight() / 2;

// cache the values of sin and cos for faster processing
final double[] sinCache = new double[maxTheta];
final double[] cosCache = sinCache.clone();
for (int t = 0; t < maxTheta; t++) {
double realTheta = t * thetaStep;
sinCache[t] = Math.sin(realTheta);
cosCache[t] = Math.cos(realTheta);
}
// Now find edge points and update the hough array
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
// Find non-black pixels
if ((img.getRGB(x, y) & 0x000000ff) != 0) {
// Go through each value of theta
for (int t = 0; t < maxTheta; t++) {
// Work out the r values for each theta step
int r = (int) (((x - centerX) * cosCache[t]) + ((y - centerY) * sinCache[t]));

// this copes with negative values of r
r += houghHeight;

if (r < 0 || r >= doubleHeight)
continue;

// Increment the hough array
houghArray[t][r]++;
}
}
}
}

// Initialise the vector of lines that we'll return
ArrayList<HoughLine> lines = new ArrayList<HoughLine>(20);

// Only proceed if the hough array is not empty
// if (numPoints == 0) return lines;

// Search for local peaks above threshold to draw
for (int t = 0; t < maxTheta; t++) {
loop: for (int r = neighbourhoodSize; r < doubleHeight - neighbourhoodSize; r++) {

// Only consider points above threshold
if (houghArray[t][r] > threshold) {

int peak = houghArray[t][r];

// Check that this peak is indeed the local maxima
for (int dx = -neighbourhoodSize; dx <= neighbourhoodSize; dx++) {
for (int dy = -neighbourhoodSize; dy <= neighbourhoodSize; dy++) {
int dt = t + dx;
int dr = r + dy;
if (dt < 0)
dt = dt + maxTheta;
else if (dt >= maxTheta)
dt = dt - maxTheta;
if (houghArray[dt][dr] > peak) {
// found a bigger point nearby, skip
continue loop;
}
}
}

// calculate the true value of theta
double theta = t * thetaStep;

// add the line to the vector
lines.add(new HoughLine(theta, r));

}
}
}

return lines;
}
}[/CODE]

Das löst natürlich noch nicht das Problem mit dem "canny edge detection algorithm"... Wie es mit OpenCV geht, wird hier beschrieben: https://www.tutorialspoint.com/opencv-hough-line-transform-implementation-using-java

Falls das alles funktioniert ... müsste ich ja auch noch wissen, welche Linien zum Schachfeld gehören und wo das anfängt ...

😑
 

mihe7

Top Contributor
Im Hough-Raum hast Du ja den Winkel der Senkrechten auf die Linie und den Abstand zum Urprung gegeben (s. https://homepages.inf.ed.ac.uk/rbf/HIPR2/hough.htm, Abb. 2). Im Array interessieren Dich also nur die 0-Grad und die 90-Grad Einträge mit den höchsten Werten. Das sind dann die vertikalen und horizontalen Linien.

Evtl. reicht hier schon eine einfache Kantenerkennung, schließlich ist es ja ein Screenshot und damit ohne großartiges Rauschen:
Java:
import java.awt.*;
import java.awt.color.*;
import java.awt.image.*;
import java.io.File;
import javax.imageio.*;

public class Test {

    private BufferedImage laplace(BufferedImage source) {
        ConvolveOp op = new ConvolveOp(new Kernel(3, 3, new float[] {
             0f,  -1f,  0f,
            -1f,   4f,  -1f,
             0f,  -1f,  0f
        }));

        return op.filter(source, null);
    }

    private BufferedImage grayscale(BufferedImage source) {
        ColorConvertOp op = new ColorConvertOp(
                ColorSpace.getInstance(ColorSpace.CS_GRAY), null);

        return op.filter(source, null);
    }

    public static void main(String[] args) throws Exception {
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice screen = ge.getDefaultScreenDevice();
        GraphicsConfiguration config = screen.getDefaultConfiguration();
        Rectangle bounds = config.getBounds();

        Robot r = new Robot(screen);
        BufferedImage img = r.createScreenCapture(bounds);
        Test t = new Test();
        
        ImageIO.write(t.laplace(t.grayscale(img)), "jpg", new File("test.jpg"));
    }
}
 

Barista

Top Contributor
// Find non-black pixels if ((image.getRGB(x, y) & 0x000000ff) != 0)
Also ich habe letztens viel an einem OCR-Programm gearbeitet.

Schwarze Pixel habe ich folgendermassen erkannt:

[CODE lang="java" title="Detect black pixel"]public static boolean rgbToBlackBin(
final int rgb )
{
final int red = ( rgb >> 16 ) & 0xFF;

if ( red > 40 )
{
return false;
}

final int green = ( rgb >> 8 ) & 0xFF;

if ( green > 40 )
{
return false;
}

final int blue = rgb & 0xFF;

if ( blue > 40 )
{
return false;
}

return true;
}
[/CODE]
 

123neu

Bekanntes Mitglied
x*cos(t) + y*sin(t) = r
<=> x = (r-y*sin(t)) / cos(t)

für y = 0 ist dann x = r/cos(t) und für y = height gilt x = (r-height*sin(t)) / cos(t)
Wärst du so freundlich, und würdest das bitte erläutern?

Das hab ich bis jetzt...
Java:
        public void drawLine(Graphics2D g2d, Color col, int h) {
            double x1 = r * Math.sin(theta);
            double y1 = r * Math.cos(theta);
            double x2 = x1 + h * Math.sin(-theta);
            double y2 = y1 + h * Math.cos(-theta);
            // (x1,y1), (x2,y2) sind zwei Punkte auf der Geraden

//            double endX = startX + w * Math.sin(theta);
//            double endY = startY + w * Math.cos(theta);

            g2d.setColor(col);
            g2d.drawLine((int) ?, (int) 0, (int) ?, (int) h);
        }

theta ist der Alphawinkel, r ist die Länge, h steht für height.
 

mihe7

Top Contributor
So, also hat schon gestimmt - Winkel und Abstand sind ja konstant.

Es ist cos²(t) + sin²(t) = 1. Die Punkte (x,y) auf dem Rand eines Kreises mit Radius r sind durch x = r*cos(t) und y = r*sin(t) bestimmt, mit cos(t) = x/r und sin(t) = y/r folgt x/r*cos(t) + y/r*sin(t) = 1, multipliziert mit r gibt das x*cos(t)+y*sin(t) = r.

Löst man das nach y auf, erhält man y = (r-x*cos(t))/sin(t) = r/sin(t) - x*cos(t)/sin(t). Da r und t konstant sind, ist das die Gleichung einer Geraden, die durch den Punkt P=(r*cos(t), r*sin(t)) mit einer Steigung von -cos(t)/sin(t) verläuft und damit Senkrecht auf der durch OP gegebenen Strecke (mit Länge r) steht, deren Steigung r*sin(t)/r*cos(t) = sin(t)/cos(t) beträgt.
 

123neu

Bekanntes Mitglied
Ehrlich gesagt, hilft mir das überhaupt nicht weiter...

Kannst du diese Methode nicht einfach vervollständigen?
Java:
        public void drawLine(Graphics2D g2d, Color col, int w, int h) {
            double x1 = r * Math.sin(theta) - w / 2;
            double y1 = r * Math.cos(theta) - h / 2;
            double a = -x1 / Math.sin(-theta);
            double b = -y1 / Math.cos(-theta);
            double x2 = x1 + a * Math.sin(-theta);
            double y2 = y1 + b * Math.cos(-theta);

            g2d.setColor(col);
            g2d.drawLine((int) x2, (int) y2, (int) w, (int) h);
        }

Die Herleitung ist ja schön und gut, aber die hilft mir 0️⃣0️⃣0️⃣0️⃣
 
Zuletzt bearbeitet:

123neu

Bekanntes Mitglied
Dein Filter scheint aber zu funktionieren:
Java:
    BufferedImage img2 = new ConvolveOp(new Kernel(3, 3, new float[] { 0f, -1f, 0f, -1f, 4f, -1f, 0f, -1f, 0f })).filter(new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null).filter(img, null), null);
    try {
        ImageIO.write(img2, "png", new File("testimg1.png"));
    } catch (IOException e) {
        e.printStackTrace();
    }

testimg1.png
 

mihe7

Top Contributor
Ja vertikale Geraden sind speziell. Ansonsten enthält jede Gerade einen Punkt bei x=0, und (width, y(width)) bedeutet ja nicht, dass die Gerade bis "ganz nach unten" geht.

Beispiel: 45°, Abstand 10. Box-Breite 20. y(0) = 14.142135623730951, y(20) = -5.857864376269051

Nachtrag: für horizontale und vertikale Geraden kannst Du ja direkt r nehmen.
 

123neu

Bekanntes Mitglied
Java:
import java.awt.AWTException;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;

import java.io.File;
import java.io.IOException;

import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class FindTemplate {
    public static class HoughLine {
        private double theta;
        private int r;

        public HoughLine(double theta, int r) {
            this.theta = theta;
            this.r = r;
        }

        public double getTheta() {
            return theta;
        }

        public void setTheta(double theta) {
            this.theta = theta;
        }

        public int getR() {
            return r;
        }

        public void setR(int r) {
            this.r = r;
        }

        private int y(int x) {
            return (int) ((r - x * Math.cos(theta)) / Math.sin(theta));
        }

        public void drawLine(Graphics2D g2d, Color col, int w, int h) {
            double x1 = r * Math.sin(theta) - h / 2;
            double y1 = r * Math.cos(theta) - h / 2;
//            double a = -x1 / -Math.sin(t);
//            double b = -y1 / -Math.cos(t);
            double x2 = x1 + 10 * -Math.sin(theta);
            double y2 = y1 + 10 * -Math.cos(theta);

            g2d.setColor(col);
            g2d.drawLine((int) x1, (int) y1, (int) x2, (int) y2);
        }
    }

    public static void main(String[] args) throws AWTException, InterruptedException {
        Robot robot = new Robot();
        Rectangle rect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());

        Thread.sleep(10_000);

        BufferedImage img = robot.createScreenCapture(rect);
        ArrayList<FindTemplate.HoughLine> lines = getLines(img, 175);

        JFrame f = new JFrame();
        Canvas c = new Canvas() {
            private static final long serialVersionUID = 1L;

            @Override
            public void paint(Graphics g) {
                Graphics2D g2d = (Graphics2D) g;
                for (HoughLine houghLine : lines) {
                    houghLine.drawLine(g2d, Color.red, this.getHeight(), this.getHeight());
                }
            }
        };
        f.add(c);
        f.setSize(rect.getSize());
        f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        f.setVisible(true);
    }

    public static ArrayList<HoughLine> getLines(BufferedImage img, int threshold) {
        // The size of the neighbourhood in which to search for other local maxima
        final int neighbourhoodSize = 4;

        // Calculate the maximum height the hough array needs to have
        final int houghHeight = (int) (Math.sqrt(2) * Math.max(img.getHeight(), img.getWidth())) / 2;

        // Double the height of the hough array to cope with negative r values
        final int doubleHeight = 2 * houghHeight;

        // How many discrete values of theta shall we check?
        final int maxTheta = 180;

        // Using maxTheta, work out the step
        final double thetaStep = Math.PI / maxTheta;

        // Create the hough array
        final int[][] houghArray = new int[maxTheta][doubleHeight];

        // Find edge points and vote in array
        final int centerX = img.getWidth() / 2;
        final int centerY = img.getHeight() / 2;

        // cache the values of sin and cos for faster processing
        final double[] sinCache = new double[maxTheta];
        final double[] cosCache = sinCache.clone();
        for (int t = 0; t < maxTheta; t++) {
            double realTheta = t * thetaStep;
            sinCache[t] = Math.sin(realTheta);
            cosCache[t] = Math.cos(realTheta);
        }

        BufferedImage img2 = new ConvolveOp(new Kernel(3, 3, new float[] { 0f, -1f, 0f, -1f, 4f, -1f, 0f, -1f, 0f })).filter(new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null).filter(img, null), null);
        try {
            ImageIO.write(img2, "png", new File("testimg1.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Now find edge points and update the hough array
        for (int x = 0; x < img2.getWidth(); x++) {
            for (int y = 0; y < img2.getHeight(); y++) {
                // Find non-black pixels
                if ((img2.getRGB(x, y) & 0x000000ff) != 0) {
                    // Go through each value of theta
                    for (int t = 0; t < maxTheta; t++) {
                        // Work out the r values for each theta step
                        int r = (int) (((x - centerX) * cosCache[t]) + ((y - centerY) * sinCache[t]));

                        // this copes with negative values of r
                        r += houghHeight;

                        if (r < 0 || r >= doubleHeight)
                            continue;

                        // Increment the hough array
                        houghArray[t][r]++;
                    }
                }
            }
        }

        // Initialise the vector of lines that we'll return
        ArrayList<HoughLine> lines = new ArrayList<HoughLine>(20);

        // Only proceed if the hough array is not empty
        // if (numPoints == 0) return lines;

        // Search for local peaks above threshold to draw
        for (int t = 0; t < maxTheta; t++) {
            loop: for (int r = neighbourhoodSize; r < doubleHeight - neighbourhoodSize; r++) {

                // Only consider points above threshold
                if (houghArray[t][r] > threshold) {

                    int peak = houghArray[t][r];

                    // Check that this peak is indeed the local maxima
                    for (int dx = -neighbourhoodSize; dx <= neighbourhoodSize; dx++) {
                        for (int dy = -neighbourhoodSize; dy <= neighbourhoodSize; dy++) {
                            int dt = t + dx;
                            int dr = r + dy;
                            if (dt < 0)
                                dt = dt + maxTheta;
                            else if (dt >= maxTheta)
                                dt = dt - maxTheta;
                            if (houghArray[dt][dr] > peak) {
                                // found a bigger point nearby, skip
                                continue loop;
                            }
                        }
                    }

                    // calculate the true value of theta
                    double theta = t * thetaStep;

                    // add the line to the vector
                    lines.add(new HoughLine(theta, r));

                }
            }
        }

        return lines;
    }
}
 

mihe7

Top Contributor
Gepfuscht:
Java:
import java.awt.AWTException;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;

import java.io.File;
import java.io.IOException;

import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class FindTemplate {
    public static class HoughLine {
        private double theta;
        private int r;

        public HoughLine(double theta, int r) {
            this.theta = theta;
            this.r = r;
        }

        public double getTheta() {
            return theta;
        }

        public void setTheta(double theta) {
            this.theta = theta;
        }

        public int getR() {
            return r;
        }

        public void setR(int r) {
            this.r = r;
        }

        private int y(int x, int realR) {
            return (int) ((realR - x * Math.cos(theta)) / Math.sin(theta));
        }

        public void drawLine(Graphics2D g2d, Color col, int w, int h) {
            final int houghHeight = (int) (Math.sqrt(2) * Math.max(w, h)) / 2;
            int realR = r - houghHeight;
            double x1, y1, x2, y2;

            if (theta != 0.0) {
                x1 = 0;
                y1 = h/2 + y(0, realR);
                x2 = w;
                y2 = h/2 + y(w, realR);
            } else {
                System.out.println("r" +  r);                
                
                x1 = x2 = w/2 + realR;
                y1 = 0;
                y2 = h;
            }

            g2d.setColor(col);
            g2d.drawLine((int) x1, (int) y1, (int) x2, (int) y2);
        }

        public String toString() {
            return String.format("(\u03b8,r)=(%f,%d)", theta, r);
        }
        public String toString(int width, int height) {
            final int houghHeight = (int) (Math.sqrt(2) * Math.max(width, height)) / 2;
            return String.format("(\u03b8,r)=(%f,%d)", theta, r - houghHeight);
        }
    }

    public static void main(String[] args) throws Exception {
/*
        Robot robot = new Robot();
        Rectangle rect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());

        Thread.sleep(10_000);

        BufferedImage img = robot.createScreenCapture(rect);

        Rectangle rect = new Rectangle(500, 500);
        BufferedImage img = new BufferedImage(rect.width, rect.height, BufferedImage.TYPE_INT_RGB);
        Graphics g = img.createGraphics();
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, img.getWidth(), img.getHeight());
        int size = 200;
        g.setColor(Color.WHITE);
        g.fillRect((rect.width - size)/2, (rect.height - size)/2, size, size);
        g.setColor(Color.YELLOW);
        g.fillRect((rect.width - size)/2 - 59, (rect.height - size)/2 - 50, size, size);
        g.dispose();
*/
        BufferedImage img = ImageIO.read(new File("testinput.png"));
        Rectangle rect = new Rectangle(0, 0, img.getWidth(), img.getHeight());

        ArrayList<FindTemplate.HoughLine> lines = getLines(img, 30);
        BufferedImage img2 = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics g = img2.createGraphics();
        Graphics2D g2d = (Graphics2D) g;
        g.drawImage(img, 0, 0, null);
        for (HoughLine houghLine : lines) {
            houghLine.drawLine(g2d, Color.red, rect.width, rect.height);
        }
        g.dispose();

        ImageIO.write(img2, "png", new File("testoutput.png"));

        JFrame f = new JFrame();
        Canvas c = new Canvas() {
            private static final long serialVersionUID = 1L;

            @Override
            public void paint(Graphics g) {
                g.drawImage(img2, 0, 0, null);
            }
        };
        f.add(c);
        f.setSize(rect.getSize());
        f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        f.setVisible(true);
    }

    public static ArrayList<HoughLine> getLines(BufferedImage img, int thresholdPct) {
        // The size of the neighbourhood in which to search for other local maxima
        final int neighbourhoodSize = 4;

        // Calculate the maximum height the hough array needs to have
        final int houghHeight = (int) (Math.sqrt(2) * Math.max(img.getHeight(), img.getWidth())) / 2;

        // Double the height of the hough array to cope with negative r values
        final int doubleHeight = 2 * houghHeight;

        // How many discrete values of theta shall we check?
        final int maxTheta = 180;

        // Using maxTheta, work out the step
        final double thetaStep = Math.PI / maxTheta;

        // Create the hough array
        final int[][] houghArray = new int[maxTheta][doubleHeight];

        // Find edge points and vote in array
        final int centerX = img.getWidth() / 2;
        final int centerY = img.getHeight() / 2;

        // cache the values of sin and cos for faster processing
        final double[] sinCache = new double[maxTheta];
        final double[] cosCache = sinCache.clone();
        for (int t = 0; t < maxTheta; t++) {
            double realTheta = t * thetaStep;
            sinCache[t] = Math.sin(realTheta);
            cosCache[t] = Math.cos(realTheta);
        }

        BufferedImage img2 = new ConvolveOp(new Kernel(3, 3, new float[] { 0f, -1f, 0f, -1f, 4f, -1f, 0f, -1f, 0f })).filter(new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null).filter(img, null), null);
        try {
            ImageIO.write(img2, "png", new File("testimg1.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Now find edge points and update the hough array
        int maxIntensity = 0;
        for (int x = 0; x < img2.getWidth(); x++) {
            for (int y = 0; y < img2.getHeight(); y++) {
                // Find non-black pixels
                if ((img2.getRGB(x, y) & 0x000000ff) != 0) {
                    // Go through each value of theta
                    for (int t = 0; t < maxTheta; t++) {
                        // Work out the r values for each theta step
                        int r = (int) (((x - centerX) * cosCache[t]) + ((y - centerY) * sinCache[t]));

                        // this copes with negative values of r
                        r += houghHeight;

                        if (r < 0 || r >= doubleHeight)
                            continue;

                        // Increment the hough array
                        houghArray[t][r]++;
                        maxIntensity = Math.max(maxIntensity, houghArray[t][r]);
                    }
                }
            }
        }

        BufferedImage img3 = new BufferedImage(maxTheta, doubleHeight, BufferedImage.TYPE_INT_RGB);
        for (int y = 0; y < doubleHeight; y++) {
            for (int x = 0; x < maxTheta; x++) {
                int intensity = (int)(houghArray[x][y] * 255L / maxIntensity);
                int rgb = intensity << 16 | intensity << 8 | intensity;
                img3.setRGB(x, y, rgb);
            }
        }
        try {
            ImageIO.write(img3, "png", new File("testimg2.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        

        // Initialise the vector of lines that we'll return
        ArrayList<HoughLine> lines = new ArrayList<HoughLine>(20);

        // Only proceed if the hough array is not empty
        // if (numPoints == 0) return lines;
        double threshold = maxIntensity * thresholdPct / 100.0;

        // Search for local peaks above threshold to draw
        for (int t = 0; t < maxTheta; t++) {
            loop: for (int r = neighbourhoodSize; r < doubleHeight - neighbourhoodSize; r++) {

                // Only consider points above threshold
                if (houghArray[t][r] > threshold) {

                    int peak = houghArray[t][r];

                    // Check that this peak is indeed the local maxima
                    for (int dx = -neighbourhoodSize; dx <= neighbourhoodSize; dx++) {
                        for (int dy = -neighbourhoodSize; dy <= neighbourhoodSize; dy++) {
                            int dt = t + dx;
                            int dr = r + dy;
                            if (dt < 0)
                                dt = dt + maxTheta;
                            else if (dt >= maxTheta)
                                dt = dt - maxTheta;
                            if (houghArray[dt][dr] > peak) {
                                // found a bigger point nearby, skip
                                continue loop;
                            }
                        }
                    }

                    // calculate the true value of theta
                    double theta = t * thetaStep;
                    if (t < 5 || t > 88 && t < 92) {
                        lines.add(new HoughLine(theta, r));
                    }

                }
            }
        }

        return lines;
    }
}

Ergebnis

: testoutput.png

Allerdings war Dein Bild der Input, das nochmal durch den Kantendetektor ging. Evtl. sollte man doch mal Canny probieren...
 

123neu

Bekanntes Mitglied
Danke dir @mihe7 😊 Das bringt mich schon einen riesigen Schritt weiter...

Ja, ich hab mir schon fast gedacht dass die Ränder die hier eher weiß sind problematisch werden könnten... Eventuell invertieren? :)

Oder ich lass das Ding auf Grau anspringen... 🤔

Edit: Du kannst auch noch mit dem Threshold rumspielen.
 

mihe7

Top Contributor
Vor ein paar Jahren habe ich die Hough-Lines dazu verwendet, eine Grafik waagerecht auszurichten. Das hatte ich wesentlich einfacher in Erinnerung.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
Temsky34 Wie bekomme ich dieses Java-Warning wieder weg? Java Basics - Anfänger-Themen 2
berserkerdq2 Überprüfen ob eine Schreibberechtigung auf ein file exisitert bzw. ob man dieses file löschen kann, wie? Java Basics - Anfänger-Themen 9
F Kann mir jemand kurz dieses Programm erklären? Java Basics - Anfänger-Themen 22
cmn489 Werte beim Funktionsaufruf in ein Feld übertragen(falls dieses leer ist) Java Basics - Anfänger-Themen 1
T Methode schreiben, die einem Array ein Stringelement hinzufügt, wenn dieses noch nicht enthalten ist. Java Basics - Anfänger-Themen 6
Salvatore321 Wie kann ich dieses Zustandsdiagramm am besten Umsetzen? Java Basics - Anfänger-Themen 5
Sajeel Chattha Dieses Programm umschreiben Java Basics - Anfänger-Themen 5
M Wie erstelle ich dieses Parallelogramm??? Java Basics - Anfänger-Themen 6
P Wie kann ich die Zahlen dieses Arrays dividieren? Java Basics - Anfänger-Themen 2
G Weiß jemand wie man dieses Programm schreibt? Java Basics - Anfänger-Themen 84
A Kann mir jemand dieses Programm erklären? Java Basics - Anfänger-Themen 1
ChrisPL4Y Wieso funktioniert dieses Programm nicht? Java Basics - Anfänger-Themen 6
B Könnte jemand über dieses jurze Javaprogramm schauen? Irgendwas funktioniert mit der z-Varible nicht Java Basics - Anfänger-Themen 2
TechGirl JAVA GUI Oberfläche Umkreisung - wie heißt dieses Element? Java Basics - Anfänger-Themen 2
W Methoden Methode auf Array aufrufen, und dieses Array dabei ändern? Java Basics - Anfänger-Themen 10
Tacofan Was macht dieses "Stückchen Code"? Java Basics - Anfänger-Themen 3
Shams Kann man von einem Interface aus auf die dieses implementierende Klasse zugreifen? Java Basics - Anfänger-Themen 4
M Warum ist dieses Feld der Klasse Math immutable? Java Basics - Anfänger-Themen 7
R Wieso funktioniert dieses Array nicht? Java Basics - Anfänger-Themen 13
M Wie heisst dieses Sortierverfahren? Java Basics - Anfänger-Themen 6
G Wo ist die Eigenschaft dieses JFrames versteckt? Java Basics - Anfänger-Themen 5
G Wie nennt man dieses Konstrukt Java Basics - Anfänger-Themen 3
V Schon wieder ein kleines problem...dieses mal mit do-while loop Java Basics - Anfänger-Themen 9
F Was soll dieses Programm genau machen ? Java Basics - Anfänger-Themen 9
P OOP Wie schreib ich dieses Programm am besten? Java Basics - Anfänger-Themen 6
D Was genau bedeutet und bewirkt dieses @override? Java Basics - Anfänger-Themen 15
P Datentypen Warum würde dieses Beispiel nicht funktionieren? Java Basics - Anfänger-Themen 6
G Aus eigenem Panel dieses Löschen Java Basics - Anfänger-Themen 2
S für was steht dieses e ?? Java Basics - Anfänger-Themen 4
J Was bedeutet dieses a [i].length? Java Basics - Anfänger-Themen 3
D Wie bringe ich dieses Programm als .jar zum laufen ? Java Basics - Anfänger-Themen 12
R Image aus jar laden (dieses mal awt) Java Basics - Anfänger-Themen 19
W "Sprechen Sie Java?" suche dieses Buch gebraucht! Java Basics - Anfänger-Themen 11
G Dieses verdammte Regex Java Basics - Anfänger-Themen 2
H warum ist dieses Kontext static? Java Basics - Anfänger-Themen 5
G Dieses leidige ID Thema Java Basics - Anfänger-Themen 9
D Was ist denn dieses Jar ueberhaupt ? Java Basics - Anfänger-Themen 3
G Wie nennt man dieses Konstrukt: Vector<Object> Java Basics - Anfänger-Themen 2
N Ist dieses Problem mit Java zu lösen? Java Basics - Anfänger-Themen 7
C Warum funktioniert dieses Speichern in Array nicht? Java Basics - Anfänger-Themen 4
S Ist dieses Projekt realisierbar? Java Basics - Anfänger-Themen 2
D Warum läuft dieses Programm so langsam? Java Basics - Anfänger-Themen 5
B Split und dieses Zeichen "" Java Basics - Anfänger-Themen 3
G Was macht dieses Program ? Java Basics - Anfänger-Themen 13
L Dieses Problem nagt an meiner Würde - Argument * Java Basics - Anfänger-Themen 4
D Vereinfachung dieses Programms Java Basics - Anfänger-Themen 11
megachucky Suche ein paar gute Tutorials so wie dieses hier. Java Basics - Anfänger-Themen 4
M Wie auf ein Objekt zugreifen und dieses manipulieren? Java Basics - Anfänger-Themen 5
S Hilfe!!!! Wie ändere ich dieses Applet???? Java Basics - Anfänger-Themen 9
E Durch Muster in Array iterieren Java Basics - Anfänger-Themen 3
B Dekorator Muster - Irgendwas stimmt hier doch nicht? Java Basics - Anfänger-Themen 4
frager2345 Singleton-Muster Java ->Nur eine Instanz einer Klasse erzeugen können Java Basics - Anfänger-Themen 45
frager2345 Java Singleton Muster -> Methode für Konstruktor mit Parametern Java Basics - Anfänger-Themen 3
H Muster mit verschachtelten Schleifen kreieren. Java Basics - Anfänger-Themen 2
Yasemin bahar Muster erkennen Java Basics - Anfänger-Themen 13
C Erste Schritte Muster ausgeben in der Konsole - großes V Java Basics - Anfänger-Themen 5
U Muster in einem Array erkennen Java Basics - Anfänger-Themen 8
F Quadrat Mit Muster Java Basics - Anfänger-Themen 15
J Muster und Schleifen Java Basics - Anfänger-Themen 33
R 2D Arrays mit vorgegebenem Muster Java Basics - Anfänger-Themen 2
E Arrays nach best Muster füllen Java Basics - Anfänger-Themen 4
K String nach bestimmtem Muster parsen Java Basics - Anfänger-Themen 3
P Sägezahn Muster Programm Java Basics - Anfänger-Themen 2
C Array Muster erzeugen Java Basics - Anfänger-Themen 2
J Erste Schritte zweidimensionales Array Muster befüllen. Java Basics - Anfänger-Themen 4
J Strukturierung mit MVC Muster Java Basics - Anfänger-Themen 20
J Array Muster mit true und false Java Basics - Anfänger-Themen 6
C Muster programmieren Java Basics - Anfänger-Themen 4
C Muster programmieren Java Basics - Anfänger-Themen 4
E Muster auf der Konsole ausgeben lassen (Schleifen) Java Basics - Anfänger-Themen 7
arti28 Erste Schritte For-Schleifen und While-Schleifen, String als Muster ausgeben. Java Basics - Anfänger-Themen 3
L Java Muster Java Basics - Anfänger-Themen 1
Todesbote String auf Muster überprüfen Java Basics - Anfänger-Themen 19
C Array Zickzack Muster Java Basics - Anfänger-Themen 3
P RegEx Muster mehrfach treffen Java Basics - Anfänger-Themen 2
M Muster erkennen. Idee: Fassade. Java Basics - Anfänger-Themen 3
Dit_ Regex | Muster {a}{b}{c} Java Basics - Anfänger-Themen 7
pindakaas Compiler geht nicht (Dekorator Muster) Java Basics - Anfänger-Themen 18
M Datentypen Strings nach Muster auslesen und verarbeiten Java Basics - Anfänger-Themen 5
S X Zeichnen als Muster ausgeben Java Basics - Anfänger-Themen 5
R Muster ausgeben Java Basics - Anfänger-Themen 4
H Muster ausgeben Java Basics - Anfänger-Themen 25
G String auf Muster prüfen Java Basics - Anfänger-Themen 5
O useDelimiter / Muster im Parameter (Pattern) Java Basics - Anfänger-Themen 6
S OOP Warum gleiche Instanz der Klasse? (Factory-Muster) Java Basics - Anfänger-Themen 13
L Sägezahn Muster Java Basics - Anfänger-Themen 4
C Muster mit Zweidimensionalen Arrays Java Basics - Anfänger-Themen 18
0 Applet mit folgendem Muster erstellen Java Basics - Anfänger-Themen 12
P Fragen zum Observer Muster und Datenbanken Java Basics - Anfänger-Themen 2
Z Muster Java Basics - Anfänger-Themen 9
J nach Muster in String suchen Java Basics - Anfänger-Themen 4
V wie kann man am einfachsten für ein Element der JavaFX die Umrandung aktiwieren ? auch ohne css ? Java Basics - Anfänger-Themen 4
R Erste Schritte Wie am einfachsten Aufgabe wiederholen Java Basics - Anfänger-Themen 37
H Unterschied zwischen 2 Date in Sekunden am einfachsten? Java Basics - Anfänger-Themen 5
-horn- Wie am Einfachsten mit Config-Datei umgehen. Welches Format? Java Basics - Anfänger-Themen 6
H Objekte in einer Hashtable am einfachsten sortieren Java Basics - Anfänger-Themen 13

Ähnliche Java Themen

Neue Themen


Oben