Java和Python中相同程序的巨大性能差异

时间:2016-12-26 20:32:24

标签: java python performance

今天我尝试在Python中编写一个我用Java编写的程序,用于将背景与文本图像隔离开来。 而且我无法弄清楚为什么我的Python程序执行速度比我的Java程序慢得多(在Java中花费不到一秒钟,在Python中花费不到5分钟),尽管它们几乎完全相同。

我想提一下我对Python很陌生,所以如果我犯了一个明显的错误,我很抱歉。

这是Python代码:

import random
import math
from PIL import Image
from pythonds.basic.stack import Stack

def isolatebackground(image, max_distance):
    newimage = image.copy()
    (width, height) = image.size

    w = random.randrange(width);
    h = random.randrange(height);

    # Preparing unvisited pixels
    unvisitedpixels = []

    for x in range(width):
        for y in range(height):
            unvisitedpixels.append((x,y))

    # Background pixels
    background = []

    stack = Stack()
    stack.push((x,y))
    (width, height) = image.size
    pixels = image.load()
    unvisitedpixels.remove((x,y))

    possibleneighbors = [i for i in range(8)]
    translations = [(-1, -1), (0, -1), (1, -1), (1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0)]

    # Region growing algorithm
    while not stack.isEmpty():
        (currentred, currentgreen, currentblue, currentalpha) = pixels[x, y]
        foundneighbor = False
        unvisitedneighbors = possibleneighbors.copy()

        while len(unvisitedneighbors) > 0:
            n = random.choice(unvisitedneighbors)
            unvisitedneighbors.remove(n)
            (i, j) = translations[n]
            newX = x + i
            newY = y + j
            if newX >= 0 and newX < width and newY >= 0 and newY < height:
                if (newX, newY) in unvisitedpixels:
                    unvisitedpixels.remove((newX, newY))
                    (newred, newgreen, newblue, newalpha) = pixels[newX, newY]

                    distance = math.sqrt((newred - currentred) ** 2 + (newgreen - currentgreen) ** 2 + (newblue - currentblue) ** 2)

                    if distance <= max_distance:
                        foundneighbor = True
                        background.append((newX, newY))

                        stack.push((newX, newY))
                        (x, y) = (newX, newY)

        if not foundneighbor:
            (x,y) = stack.pop()

    for p in background:
        newimage.putpixel(p, (255, 0, 0))

    return newimage


if __name__ == '__main__':
    image = Image.open("TestImage3.png")
    newimage = isolatebackground(image, 5)
    newimage.show()

Java代码:

Main.java:

import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import java.io.IOException;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;
import java.util.TreeMap;
import javax.imageio.ImageIO;

public class Main
{
    public static void main(String[] args) throws IOException
    {
        BufferedImage im = readImage("TestImage3.png");

        BufferedImage split_im = removeBackground(im, 5);

        File f1 = new File("test.png");

        ImageIO.write(split_im, "png", f1);
    }

    public static BufferedImage readImage(String path) throws IOException
    {
        File image_file = new File(path);

        BufferedImage image = ImageIO.read(image_file);

        return image;
    }

    public static BufferedImage removeBackground (BufferedImage image, double threshold)
    {
        BufferedImage split_im = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics g = split_im.getGraphics();
        g.drawImage(image, 0, 0, null);
        g.dispose();

        int x = (int)(image.getWidth() * Math.random());
        int y = (int)(image.getHeight() * Math.random());

        split_im.setRGB(x, y, Color.RED.getRGB());

        int[][] translations = {{-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}};
        List<Integer> possibleNeighbors = new ArrayList<>();

        for (int i = 0; i < 8; i++)
        {
            possibleNeighbors.add(i);
        }

        Map<Coordinates, Integer> unvisitedPixels = new HashMap<>();

        for (int h = 0; h < image.getHeight(); h++)
        {
            for (int w = 0; w < image.getWidth(); w++)
            {
                unvisitedPixels.put(new Coordinates(w, h), image.getRGB(w, h));
            }
        }

        Coordinates initialCoord = new Coordinates(x, y);

        unvisitedPixels.remove(initialCoord);

        Stack visitedPixels = new Stack();
        visitedPixels.push(initialCoord);

        while (!visitedPixels.empty())
        {
            Color c1 = new Color(image.getRGB(x, y));
            int r1 = c1.getRed();
            int g1 = c1.getGreen();
            int b1 = c1.getBlue();
            boolean foundNeighbor = false;

            List<Integer> unvisitedNeighbors = new ArrayList<>(possibleNeighbors);

            while (!unvisitedNeighbors.isEmpty())
            {
                int n = (int)(8 * Math.random());

                if (unvisitedNeighbors.contains(n))
                {
                    unvisitedNeighbors.remove(unvisitedNeighbors.indexOf(n));
                    int[] translation = translations[n];
                    int newX = x + translation[0];
                    int newY = y + translation[1];

                    if (newX >= 0 && newX < image.getWidth() && newY >= 0 && newY < image.getHeight())
                    {
                        Coordinates coord = new Coordinates(newX, newY);
                        Integer value = unvisitedPixels.get(coord);

                        if (value != null)
                        {
                            Color c2 = new Color(value);
                            int r2 = c2.getRed();
                            int g2 = c2.getGreen();
                            int b2 = c2.getBlue();

                            double distance = Math.sqrt(Math.pow(r1 - r2, 2) + Math.pow(g1 - g2, 2) + Math.pow(b1 - b2, 2));

                            if (distance <= threshold)
                            {
                                foundNeighbor = true;
                                split_im.setRGB(x, y, Color.RED.getRGB());
                                unvisitedPixels.remove(coord);

                                x = newX;
                                y = newY;
                                visitedPixels.push(coord);
                            }
                        }
                    }
                }
            }

            if (!foundNeighbor)
            {
                Coordinates newCoord = (Coordinates)visitedPixels.pop();
                x = newCoord.getX();
                y = newCoord.getY();
            }
        }

        return split_im;
    }
}

Coordinates.java:

public class Coordinates
{
    private int x;
    private int y;

    public Coordinates(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    @Override
    public String toString() {
        return "Coordinates{" + "x=" + x + ", y=" + y + '}';
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 73 * hash + this.x;
        hash = 73 * hash + this.y;
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null)
        {
            return false;
        }
        else if (!(obj instanceof Coordinates))
        {
            return false;
        }
        else
        {
            Coordinates other = (Coordinates)obj;

            return this.x == other.getX() && this.y == other.getY();
        }
    }

}

我使用此图像作为测试:Test image(分辨率较低,否则Python程序需要很长时间才能对其进行分析)。

你知道什么可能导致Python中这么糟糕的表现吗?

谢谢!

0 个答案:

没有答案