Perceptron doesn't find the right line even with a bias (Processing) - java

My perceptron doesn't find the right y-intercept even though I added a bias. The slope is correct. This is my second try coding a perceptron from scratch and I got the same error twice.
The perceptron evaluates if a point on a canvas is higher or lower than the interception line. The inputs are the x-coordinate, y-coordinate and 1 for the bias.
Perceptron class:
class Perceptron
{
float[] weights;
Perceptron(int layerSize)
{
weights = new float[layerSize];
for (int i = 0; i < layerSize; i++)
{
weights[i] = random(-1.0,1.0);
}
}
float Evaluate(float[] input)
{
float sum = 0;
for (int i = 0; i < weights.length; i++)
{
sum += weights[i] * input[i];
}
return sum;
}
float Learn(float[] input, int expected)
{
float guess = Evaluate(input);
float error = expected - guess;
for (int i = 0; i < weights.length; i++)
{
weights[i] += error * input[i] * 0.01;
}
return guess;
}
}
This is the testing code:
PVector[] points;
float m = 1; // y = mx+q (in canvas space)
float q = 0; //
Perceptron brain;
void setup()
{
size(600,600);
points = new PVector[100];
for (int i = 0; i < points.length; i++)
{
points[i] = new PVector(random(0,width),random(0,height));
}
brain = new Perceptron(3);
}
void draw()
{
background(255);
DrawGraph();
DrawPoints();
//noLoop();
}
void DrawPoints()
{
for (int i = 0; i < points.length; i++)
{
float[] input = new float[] {points[i].x / width, points[i].y / height, 1};
int expected = ((m * points[i].x + q) < points[i].y) ? 1 : 0; // is point above line
float output = brain.Learn(input, expected);
fill(sign(output) * 255);
stroke(expected*255,100,100);
strokeWeight(3);
ellipse(points[i].x, points[i].y, 20, 20);
}
}
int sign(float x)
{
return x >= 0 ? 1 : 0;
}
void DrawGraph()
{
float y1 = 0 * m + q;
float y2 = width * m + q;
stroke(255,100,100);
strokeWeight(3);
line(0,y1,width,y2);
}

I found the problem
float guess = Evaluate(input);
float error = expected - guess;
should be
float guess = sign(Evaluate(input));
float error = expected - guess;
The output was never exactly one ore zero even if the answer would be correct. Because of this even the correct points gave a small error that stopped the perceptron from finding the right answer. By calculating the sign of the answer first the error is 0 if the answer is correct.

Related

Turtle Java squares Pyramid

I have to make a pyramid that can have its parameters changed, but my code keeps not allowing the next row after to start at the proper point, I need help! I'm sorry if its messy, I'm very new. picture at bottom is result. I need it to be centered.
public class Pyramid2 {
public static void main(String[] args) {
Turtle t = new Turtle();
t.delay(100);
pyramid(t, 200, 5);
}
public static void square(Turtle t, double base, int levels) {
for (int i = 0; i < 4; i++) {
t.forward(base / ((levels * 2) - 1));
t.left(90);
}
}
public static void pyramid(Turtle t, double base, int levels) {
//for (int p = 1; (p-1)< levels; p++){
for (int j = 0; j < levels; j++) {
for (int i = 0; i < ((levels) * 2) - (j * 2) - 1; i++) {
square(t, base, levels);
t.forward(base / ((levels * 2) - 1));
}
t.penup();
t.left(90);
t.forward(base / ((levels * 2) - 1));
t.right(90);
t.backward(base - (base / (((levels * 2) - (j * 2)) - 1)));
t.pendown();
}
}
}
what I get
I couldn't figure out how to set up a turtle Java environment (link to a guide in the comments would be appreciated!), but the basic algorithm is pretty much language-agnostic. I'll use JavaScript with var so it should be compatible with Java 10+.
I'm not sure if your turtle has goto, but if it does, that makes rewinding to the left side of the canvas to prepare the next row easier. I'll assume you don't have this and only use forward, right, pendown and penup commands.
My approach is this:
Set size and levels constants which represent the box/grid size and number of levels, respectively. (If you want to use base, fine--compute size = base / (levels * 2 - 1) as you've already done, but save it in a variable).
Start from the top level
For each level i:
Compute the number of boxes for the level: boxes = i * 2 + 1
Compute the left x-offset to start drawing boxes from: offset = (levels - i - 1) * size
Move forward offset pixels
Draw the boxes for the level
Move to the beginning of the next line and point rightward (goto(0, turtle.y + size) would be handy here to avoid some maneuvering)
Here's the code:
var size = 20;
var levels = 5;
var t = new Turtle();
t.penup();
for (var i = 0; i < levels; i++) {
var boxes = i * 2 + 1;
var offset = (levels - i - 1) * size;
t.forward(offset);
t.pendown();
for (var j = 0; j < boxes; j++) {
for (var k = 0; k < 4; k++) {
t.forward(size);
t.right(90);
}
t.forward(size);
}
t.penup();
t.right(90);
t.forward(size);
t.right(90);
t.forward(offset + size * boxes);
t.right(180);
}
///////////////////////////////////////
// turtle library; ignore code below //
function Turtle() {
const rad = d => d * Math.PI / 180;
const canvas = document.querySelector("#turtle-pond");
canvas.width = innerWidth;
canvas.height = innerHeight;
const ctx = canvas.getContext("2d");
ctx.translate(0.5, 0.5);
let x = 0, y = 0, angle = 0;
let penDown = true;
return {
pendown() {
penDown = true;
},
penup() {
penDown = false;
},
forward(dist) {
if (penDown) {
ctx.beginPath();
ctx.moveTo(x, y);
}
x += Math.cos(rad(angle)) * dist;
y += Math.sin(rad(angle)) * dist;
if (penDown) {
ctx.lineTo(x, y);
ctx.stroke();
}
},
right(ang) {
angle += ang;
},
left(ang) {
angle -= ang;
},
};
}
<canvas id="turtle-pond"></canvas>

Get lines of Sudoku grid with open cv

I am developing an app that will solve Sudoku from camera. I am using OpenCV library. I spent some time researching and I decided to try with this project, since I am totally new in image recognition .
I have a problem with detecting grid lines. With code I have, app detects only one horizontal or one vertical line(depends on threshold, 51 and below returns one vertical and 52 and above returns one horizontal). Here is my function for finding corners, where I am detecting lines:
private List<Point> findCorners(Mat mat) {
Mat lines = new Mat();
List<double[]> horizontalLines = new ArrayList<double[]>();
List<double[]> verticalLines = new ArrayList<double[]>();
//Imgproc.GaussianBlur( mat, lines, new Size(5, 5), 2, 2 );
int threshold = 150;
int minLineSize = 0;
int lineGap = 10;
//Imgproc.Canny(mat, lines, 70, 100);
Imgproc.HoughLinesP(mat, lines, 1, Math.PI / 180, threshold);
for (int i = 0; i < lines.cols(); i++) {
double[] line = lines.get(0, i);
double x1 = line[0];
double y1 = line[1];
double x2 = line[2];
double y2 = line[3];
if (Math.abs(y2 - y1) < Math.abs(x2 - x1)) {
horizontalLines.add(line);
} else if (Math.abs(x2 - x1) < Math.abs(y2 - y1)) {
verticalLines.add(line);
}
}
String lineInfo = String.format(
"horizontal: %d, vertical: %d, total: %d",
horizontalLines.size(), verticalLines.size(), lines.cols());
Log.d(TAG_HOUGHLINES, lineInfo);
// find the lines furthest from centre which will be the bounds for the
// grid
double[] topLine = horizontalLines.get(0);
double[] bottomLine = horizontalLines.get(0);
double[] leftLine = verticalLines.get(0);
double[] rightLine = verticalLines.get(0);
double xMin = 1000;
double xMax = 0;
double yMin = 1000;
double yMax = 0;
for (int i = 0; i < horizontalLines.size(); i++) {
if (horizontalLines.get(i)[1] < yMin
|| horizontalLines.get(i)[3] < yMin) {
topLine = horizontalLines.get(i);
yMin = horizontalLines.get(i)[1];
} else if (horizontalLines.get(i)[1] > yMax
|| horizontalLines.get(i)[3] > yMax) {
bottomLine = horizontalLines.get(i);
yMax = horizontalLines.get(i)[1];
}
}
for (int i = 0; i < verticalLines.size(); i++) {
if (verticalLines.get(i)[0] < xMin
|| verticalLines.get(i)[2] < xMin) {
leftLine = verticalLines.get(i);
xMin = verticalLines.get(i)[0];
} else if (verticalLines.get(i)[0] > xMax
|| verticalLines.get(i)[2] > xMax) {
rightLine = verticalLines.get(i);
xMax = verticalLines.get(i)[0];
}
}
// obtain four corners of sudoku grid
Point topLeft = ImgManipUtil.findCorner(topLine, leftLine);
Point topRight = ImgManipUtil.findCorner(topLine, rightLine);
Point bottomLeft = ImgManipUtil.findCorner(bottomLine, leftLine);
Point bottomRight = ImgManipUtil.findCorner(bottomLine, rightLine);
List<Point> corners = new ArrayList<Point>(4);
corners.add(topLeft);
corners.add(topRight);
corners.add(bottomLeft);
corners.add(bottomRight);
return corners;
}
Here is the input image

How to Get an Objects X position in processing

I am trying to make Space Invaders in Processing. I am currently working on getting the enemy to move correctly. I have got them to be drawn in the right spot but I haven't gotten them to be moved correctly. Here is my code:
PImage mainPlayer;
PImage enemyPlayer;
float Xspeed = 60;
float Yspeed = 60;
float X;
float Y;
Enemy EnemyPlayer = new Enemy("EnemyPlayerSpaceInvaders.png", 10, 10, 6);
void setup() {
size(1400, 800);
//enemyPlayer = loadImage("EnemyPlayerSpaceInvaders.png");
mainPlayer = loadImage("MainPlayerSpaceInvaders.png");
}
void draw() {
background(0);
Enemy[] enemyPlayer = new Enemy[60];
for (int i = 0; i < 5; i += 1) {
for (int j = 0; j < 11; j += 1) {
enemyPlayer[j *i] = new Enemy("EnemyPlayerSpaceInvaders.png", 50 + j * 100, 5 + 75 * i, 6);
}
}
for (int i = 0; i < 5; i += 1) {
for (int j = 0; j < 11; j += 1) {
if(enemyPlayer[j * i].alive){
enemyPlayer[j * i].Draw();
}
enemyPlayer[j *i].moveAndDraw(6);
}
}
}
class Enemy {
boolean alive = true;
float x;
float y;
float speed;
String playerTexFile;
PImage playerTex;
Enemy(String PlayerTexFile, float X, float Y, float Speed){
x = X;
y = Y;
speed = Speed;
playerTexFile = PlayerTexFile;
}
void Draw(){
playerTex = loadImage(playerTexFile);
image(playerTex, x, y);
}
void moveAndDraw(float Speed){
playerTex = loadImage(playerTexFile);
if(alive){
x += Speed;
if (x >= 1300) {
x = 100;
y += 50;
}
}
}
}
Here is my result:
The Draw function works but what you're seeing that is messing it up is the moveAndDraw() function.
And the enemy drawings aren't moving. I have made this before with c++ SFML but in that there is a very basic getPosition function. The reason I want to get position is that right now I'm having to use inaccurate numbers as the X and Y position and for the enemy to move correctly I need to know exactly what it's position is. I have checked multiple pages on processing.org but none of them helped. I haven't found any getPosition void and all the ones I've seen other people using a void to do this I just haven't been able to get it to work. If there is some code that could get me this to work or just some function I've looked over and even a website page I could look at I'd be open to it. Please tell me anything I can do to get this working.
The issue is that you recreate the enemies in every frame at it's initial position:
void draw() {
background(0);
Enemy[] enemyPlayer = new Enemy[60];
for (int i = 0; i < 5; i += 1) {
for (int j = 0; j < 11; j += 1) {
enemyPlayer[j *i] = new Enemy("EnemyPlayerSpaceInvaders.png", 50 + j * 100, 5 + 75 * i, 6);
}
}
// [...]
}
You've to:
Create a global array of enemies Enemy[] enemyPlayer (and delete PImage enemyPlayer).
Create and initialize the enemies in setup.
Use and move the existing enemies in draw:
Further note, that your loops doesn't do what you expect it to do. Create the enemies in 2 nested loops. If i runs from o to 6 and j from 0 to 10, the the index of an enemy is i*10 + j.
The enemies can be moved in a single loop from 0 to enemyPlayer.length.
//PImage enemyPlayer; <--- DELETE
// global array of enemies
Enemy[] enemyPlayer = new Enemy[60];
// [...]
void setup() {
size(1400, 800);
mainPlayer = loadImage("MainPlayerSpaceInvaders.png");
// create enemies
for (int i = 0; i < 6; i += 1) {
for (int j = 0; j < 10; j += 1) {
enemyPlayer[i*10 + j] = new Enemy("rocket64.png", 50 + j * 100, 5 + 75 * i, 6);
}
}
}
void draw() {
background(0);
// move enemies
for(int i = 0; i < enemyPlayer.length; ++i ) {
if(enemyPlayer[i].alive){
enemyPlayer[i].Draw();
}
enemyPlayer[i].moveAndDraw(6);
}
}

Why won't it revolve?

I'm trying to make a rotating ellipse to the center, and I'm having trouble as to how it isn't moving besides being in the draw and having an offset in x and y changing. I mapped the initial x and y position of the ellipses at first and try and calculated its distance from the center I was wondering if any of you could help, it'll be much appreciated. ^^ (beginner here) [IDE processing]
I dunno what's wrong with the revolution from polar to cartesian coord.
Heart heart = new Heart();
int h = 500;
int w = 500;
void setup(){
size(500,500);
heart = new Heart();
heart.init();
//heart.display();
}
void draw(){
background(0);
heart.rotate();
}
class Heart {
float[][] pos;
float[] dist;
int hold;
float xOff;
float yOff;
Heart(){
hold = 10;
dist = new float[hold];
pos = new float[hold][hold];
}
void init(){
for(int i = 0; i < hold; i++){
for(int j = 0; j < hold; j++){
pos[i][j] = random(0,h);
}
}
}
/*void display(){
for (int k = 0; k < hold; k++){
fill(0,10,255,50);
ellipse(pos[k][0],pos[0][k],15,15);
stroke(255);
line(w/2,h/2,pos[k][0],pos[0][k]);
}
}*/
void rotate(){
float[] r = new float[hold];
int theta;
for(int k = 0; k < hold; k++){
r[k] = dist(w/2,h/2,pos[k][0],pos[0][k]);
for(theta = 0; theta <= TWO_PI; theta++){
xOff = r[k] * cos(theta);
yOff = r[k] * sin(theta);
stroke(255);
println(pos[k][0] + xOff);
ellipse(pos[k][0] + xOff,pos[0][k] + yOff,15,15);
}
}
}
}
I expect the ellipses to revolve, no error.
Use a global variable angle of type float. Increment the angle in every frame and pass it to the method Heart.rotate():
float angle = 0.0;
void draw(){
background(0);
heart.rotate(angle);
angle += 0.01;
}
The method Heart.rotate() hast to draw the the ellipse with one certain angle i every frame, rather than all the possible angles in a loop in each frame.
class Heart {
// ...
void rotate(float theta){
float[] r = new float[hold];
for(int k = 0; k < hold; k++){
r[k] = dist(w/2,h/2,pos[k][0],pos[0][k]);
xOff = r[k] * cos(theta);
yOff = r[k] * sin(theta);
stroke(255);
println(pos[k][0] + xOff);
ellipse(pos[k][0] + xOff,pos[0][k] + yOff,15,15);
}
}
}
Note, the display is updated once after global draw() has been executed. There is no update of the display in the inner loop of the method Heart.rotate().

Collision Bug in 2D Platformer Game

I am currently developing a 2D Mario-Like Platformer Game. I ran into a collision problem i've been trying to solve for a while now, but nothing seems to work :/
Basicly, i have a CenterLayer, which stores at which Position what kind of Tile is.
Then i have some Sprites and a Player, which should collide with these Tiles.
Because these Tiles can be triangular shaped (or any other kind of convex polygon), i decided to handle collision via SAT (Seperating Axis Theorem). This works great, but when it comes to collision with the floor where many tiles are adjacent to eachother and the sprite is moving left, it pickes the wrong edge and moves the Sprite to the right, but expected result would be moving it up. This causes the sprite to get stuck.
This is the code im currently using:
package level;
import java.awt.Polygon;
import tiles.Tile;
import sprites.*;
public class Collider {
/** Collide Sprite (or Player) with CenterLayer **/
public static void collide(Sprite s, CenterLayer c){
CollisionPolygon ps = s.getPolygon();
//Get blocks to collide with
int startXTile = (int) (s.getX() / CenterLayer.TILE_WIDTH) - 1;
int endXTile = (int) Math.ceil((s.getX() + s.getWidth()) / CenterLayer.TILE_WIDTH) + 1;
int startYTile = (int) (s.getY() / CenterLayer.TILE_HEIGHT) - 1;
int endYTile = (int) Math.ceil((s.getY() + s.getHeight()) / CenterLayer.TILE_HEIGHT) +1;
//limit to level boundaries
if(startXTile < 0) startXTile = 0;
if(endXTile > c.LEVEL_WIDTH) endXTile = c.LEVEL_WIDTH;
if(startYTile < 0) startYTile = 0;
if(endYTile > c.LEVEL_HEIGHT) endYTile = c.LEVEL_HEIGHT;
int sizeX = endXTile - startXTile;
int sizeY = endYTile - startYTile;
//loop through tiles and collide
for(int xc = 0; xc < sizeX; xc++)
for(int yc = 0; yc < sizeY; yc++){
int xblock = xc + startXTile;
int yblock = yc + startYTile;
Tile t = c.getTile(xblock, yblock);
if(t!=null){ //if tile == null --> tile is air
CollisionPolygon pt = t.getPolygon(xblock, yblock);
double[] projection = PolygonCollision(ps, pt);
//if collision has happened
if(projection[0] != 0 || projection[1] != 0){
//collide
s.moveBy(projection[0], projection[1]);
//update sprites polygon to new position
ps = s.getPolygon();
}
}
}
}
public static double dotProduct(double x, double y, double dx, double dy) {
return x * dx + y * dy;
}
// Calculate the projection of a polygon on an axis (ax, ay)
// and returns it as a [min, max] interval
public static double[] ProjectPolygon(double ax, double ay, Polygon p) {
double dotProduct = dotProduct(ax, ay, p.xpoints[0], p.ypoints[0]);
double min = dotProduct;
double max = dotProduct;
for (int i = 0; i < p.npoints; i++) {
dotProduct = dotProduct(p.xpoints[i], p.ypoints[i], ax, ay);
if (dotProduct < min) {
min = dotProduct;
} else if (dotProduct > max) {
max = dotProduct;
}
}
return new double[] { min, max };
}
// Calculate the distance between [minA, maxA](p1[0], p1[1]) and [minB, maxB](p2[0], p2[1])
// The distance will be negative if the intervals overlap
public static double IntervalDistance(double[] p1, double[] p2) {
if (p1[0] < p2[0]) {
return p2[0] - p1[1];
} else {
return p1[0] - p2[1];
}
}
public static double[] PolygonCollision(CollisionPolygon p1, CollisionPolygon p2){
boolean intersection = true;
int edgeCount1 = p1.npoints;
int edgeCount2 = p2.npoints;
double projectionX = 0;
double projectionY = 0;
double projectionDist = Double.POSITIVE_INFINITY;
//loop through all the edges
for(int edgeIndex = 0; edgeIndex < edgeCount1 + edgeCount2; edgeIndex++){
//find edges
double[] axis;
if(edgeIndex < edgeCount1){
axis = p1.getAxis(edgeIndex);
} else {
axis = p2.getAxis(edgeIndex - edgeCount1);
}
double axisX = axis[0];
double axisY = axis[1];
//System.out.println("edge: " +axisX + ", "+ axisY);
//find the projection of both polygons on current axis
final double[] proj1 = ProjectPolygon(axisX, axisY, p1);
final double[] proj2 = ProjectPolygon(axisX, axisY, p2);
//Check if polygons are intersecting, if not end loop
double id = IntervalDistance(proj1, proj2);
if(id > 0){
intersection = false;
break;
}
//Check if projection would be shorter than previous one
id = Math.abs(id);
if(id < projectionDist){
projectionDist = id;
projectionX = axisX;
projectionY = axisY;
//check if hit from "false" side
double d1x = p1.getCenterX();
double d1y = p1.getCenterY();
double d2x = p2.getCenterX();
double d2y = p2.getCenterY();
double midx = d1x - d2x;
double midy = d1y - d2y;
double dot = dotProduct(midx, midy, projectionX, projectionY);
if(dot < 0){
projectionX = -projectionX;
projectionY = -projectionY;
}
}
}
double[] result = new double[]{0, 0};
if(intersection){
//System.out.println("colliison: " + projectionX +"; "+ projectionY + ", " + projectionDist);
result[0] = projectionX * projectionDist;
result[1] = projectionY * projectionDist;
}
return result;
}
}
Any Ideas?
Tom
I had this bug too , it happens when there are parallel edges on a poly.The easy way to fix this is to project the difference between the polygon centers on the found axis.If the result is negative you would just multiply the axis by -1.
Vector aMidPoint = new Vector();
Vector bMidPoint = new Vector();
for ( Vector v : aVerts) {
aMidPoint = aMidPoint.add(v);
}
for ( Vector v : bVerts) {
bMidPoint = bMidPoint.add(v);
}
aMidPoint = aMidPoint.scalarDivision(aVerts.size());
bMidPoint = bMidPoint.scalarDivision(bVerts.size());
Vector ba = aMidPoint.subtract(bMidPoint);
if (ba.dotProduct(minOverlapVector) < 0) {
minOverlapVector = minOverlapVector.scalarMultiplication(-1);
}

Categories

Resources