3

奇妙なピクセルが混在しているように見える火星1のグレースケール画像があります。

異常な画像ピクセルをハイライトするための Swing コンポーネントはありますか? そうでない場合、そのようなコンポーネントをどのように作成しますか?


  1. Sirenum Fossae Trough - 火星の MGS MOC リリース番号 MOC2-248の元の (768x1536 ピクセル) 画像については、Mars Global Surveyor - Mars Orbiter Cameraページを参照してください。

気になった火口の北縁に斑点が見えます。3 つの暗いスポットを強調するために、画像をズームおよびトリミングしたものを次に示します。ほとんどのズームは画像を遠くから (小さく) 表示していますが、最後はセクションを 2 倍のサイズ (2 倍ズーム) で表示しています。

1/4ズーム 1/2ズーム 2×ズーム

すべてのスポットはクレーターと渓谷の境界にあります。1 つは最後の画像の右側近くにあり、残りの 2 つは左側にあります。

4

2 に答える 2

3

別のビューについては、ImageJコマンドを使用して元の画像Analyze > Histogramを調べました。異常を囲む 80 x 32 ピクセルの領域に注目しました。結果を以下に示します。ここに示すをレンダリングするために使用する は、便利な追加機能になる可能性がありますJFreeChartChartFactory.createHistogram()HistogramDataset

またZoom、ARGB 値を調べることもありました。左端のペアは不透明な黒で0xFF000000、右端のピクセルは0xFF070707です。同様のツールチップ アプローチは、ピクセル値を表示するのに役立つ場合があります。

ヒストグラム

リスト

于 2013-10-12T23:09:03.500 に答える
3

ピクセルの表示と並べ替えにaJTableを使用し、選択したピクセルを表示するために小さな半透明の十字線が付いた画像を使用します。で画像を表示するJLabelと、必要に応じてカスタマイズできる基本的な実行可能なコンポーネントがあります。

結果

すべての画像は、ブラウザー ベースの 8 倍のズーム スケールで表示されます (FF では滑らかにディザ処理が行われるため、線の鮮明度は低下しますが、ほぼ同じように鮮明になります)。

そのピクセルと周囲のピクセルの間のピクセル x/y、RGB & 'グレー スケール差' の情報が計算され、並べ替え可能なテーブル (3200 行) に表示されます。

タイトルの付いた各セクションには、イメージとテーブルの最初の 6 行が表示され、使用された並べ替えキーと選択された行の両方が示されます。

関心のある画像 - 何も選択されていません。

3 つの最も暗いピクセルは、それ以上のプロンプトがなくても明らかです..

X   Y   RGB     Diff.   Select
0   0   192     20.75   -
1   0   186     21.625  -
2   0   174     25.625  -
3   0   177     23.375  -
4   0   175     24.375  -
5   0   181     24.25   -
6   0   189     19.75   -

最も暗いピクセル

しかし、ロジックを確認するために、緑色の十字線でハイライトされた最も暗いピクセルを次に示します。

X   Y   RGB ▲   Diff.   Select
16  25  0       240.625 TRUE
6   30  0       240.125 TRUE
74  7   6       230.875 TRUE
78  31  112     37.875  -
79  34  112     22.75   -
75  37  115     31.375  -

次に暗いピクセル

「次に暗い」ピクセルとそのすぐ隣のピクセルとの間のグレースケールの違いは、それほど明白ではありません。最も暗い 3 ピクセルほど明白ではありません。

X   Y   RGB ▲   Diff.   Select
16  25  0       240.625 -
6   30  0       240.125 -
74  7   6       230.875 -
78  31  112     37.875  TRUE
79  34  112     22.75   TRUE
75  37  115     31.375  TRUE

次に大きな違い

グレースケールによるピクセルの次に大きな違いは、同様に目立たないものです。差は 200 ピクセル以上から 50 ピクセル未満に減少します。

X   Y   RGB     Diff. ▼ Select
16  25  0       240.625 -
6   30  0       240.125 -
74  7   6       230.875 -
37  18  205     47.875  TRUE
31  20  209     45.375  TRUE
59  13  196     44.875  TRUE

結論

データに基づくと、これらの 3 つの最も暗いピクセルは外れ値であり異常であるように思われるため、「画像の不具合」と言えます。

コード

これは、明るさと色の違いを表示/ソートし、画像を生成するために使用される Java コードです。最初のトリミングされた画像にホットリンクします。

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.event.*;
import javax.swing.table.*;

import java.io.*;
import java.net.URL;

class ImageBrightnessFilter {

    BufferedImage bi;
    JPanel gui = null;
    ArrayList<Point> points;
    JLabel l;

    ImageBrightnessFilter(BufferedImage bi) {
        this.bi = bi;
    }

    public static double getNeighborDifference(BufferedImage bi, int x, int y) {
        Color c = new Color(bi.getRGB(x, y));
        int r = c.getRed();

        int tot = 0;
        for (int xx = x - 1; xx < x + 2; xx++) {
            for (int yy = y - 1; yy < y + 2; yy++) {
                try {
                    tot += new Color(bi.getRGB(xx, yy)).getRed();
                } catch (ArrayIndexOutOfBoundsException aioobe) {
                    tot += r;
                }
            }
        }

        return (tot / 8d) - r;
    }

    public JPanel getGui() {
        if (gui == null) {
            gui = new JPanel(new BorderLayout(2, 2));

            ImageTableModel itm = new ImageTableModel(bi);
            final JTable table = new JTable(itm);
            table.setAutoCreateRowSorter(true);
            JScrollPane tableScroll = new JScrollPane(table);
            Dimension d = tableScroll.getPreferredSize();
            Dimension shortTable = new Dimension(
                    (int) d.getWidth(),
                    table.getRowHeight() * 8
                    + table.getTableHeader().getPreferredSize().height);
            tableScroll.setPreferredSize(shortTable);
            gui.add(tableScroll, BorderLayout.CENTER);

            l = new JLabel(
                    new ImageIcon(
                    (bi.getSubimage(0, 0, 80, 40)).getScaledInstance(640, 320, 0)));
            l.setBorder(new LineBorder(Color.BLACK));
            gui.add(l, BorderLayout.PAGE_START);

            ListSelectionListener lsl = new ListSelectionListener() {

                @Override
                public void valueChanged(ListSelectionEvent e) {
                    points = new ArrayList<Point>();
                    if (!e.getValueIsAdjusting()) {
                        int[] rows = table.getSelectedRows();
                        for (int row : rows) {
                            int index = row;
                            int x = (Integer) table.getValueAt(index, 0);
                            int y = (Integer) table.getValueAt(index, 1);
                            Point p = new Point(x, y);
                            points.add(p);
                        }
                    }
                    l.setIcon(new ImageIcon(getHighlightImage().getScaledInstance(640, 320, 0)));
                    l.repaint();
                }
            };
            table.getSelectionModel().addListSelectionListener(lsl);

            JToolBar tb = new JToolBar();
            gui.add(tb, BorderLayout.PAGE_END);
            JButton saveImage = new JButton("Save");
            tb.add(saveImage);
            ActionListener saveListener = new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    String s = JOptionPane.showInputDialog(gui, "name");
                    File home = new File(System.getProperty("user.home"));
                    File f = new File(home,s + ".png");
                    try {
                        ImageIO.write(getHighlightImage(), "png", f);
                    } catch (IOException ex) {
                        Logger.getLogger(
                                ImageBrightnessFilter.class.getName()).log(
                                Level.SEVERE, null, ex);
                    }
                }
            };
            saveImage.addActionListener(saveListener);
        }

        return gui;

    }

    public BufferedImage getHighlightImage() {
        BufferedImage b = new BufferedImage(
                bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_INT_ARGB);

        Graphics2D g = b.createGraphics();
        g.drawImage(bi, 0, 0, null);

        g.setColor(new Color(0, 255, 0, 95));
        if (points!=null) {
            for (Point point : points) {
                g.drawLine(point.x - 4, point.y, point.x - 2, point.y);
                g.drawLine(point.x + 4, point.y, point.x + 2, point.y);
                g.drawLine(point.x, point.y - 4, point.x, point.y - 2);
                g.drawLine(point.x, point.y + 4, point.x, point.y + 2);
            }
        }

        g.dispose();

        return b;
    }

    public static void main(String[] args) throws Exception {
        String s = "I:\\pics\\Space\\Stellar\\2\\MarsSthHemisphereInSpring.gif";
        File f = new File(s);
        URL url = new URL("http://i.stack.imgur.com/z8U5w.png");
        BufferedImage bi0 =
            //ImageIO.read(f);
            ImageIO.read(url);
        final BufferedImage bi =
            //bi0.getSubimage(160, 799, 80, 40);
            bi0;
        Runnable r = new Runnable() {

            @Override
            public void run() {
                ImageBrightnessFilter ibf = new ImageBrightnessFilter(bi);
                JOptionPane.showMessageDialog(null, ibf.getGui());
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

class ImageTableModel extends DefaultTableModel {

    BufferedImage bi;
    final static String[] columnName = {
        "X",
        "Y",
        "RGB",
        "Diff"
    };

    public ImageTableModel(BufferedImage bi) {
        super();
        this.bi = bi;
    }

    @Override
    public Object getValueAt(final int rowIndex, final int columnIndex) {
        Object o = null;
        int x = rowIndex % bi.getWidth();
        int y = rowIndex / bi.getWidth();
        int rgb = bi.getRGB(x, y);
        Color c = new Color(rgb);
        int r = c.getRed();
        switch (columnIndex) {
            case 0:
                o = new Integer(x);
                break;
            case 1:
                o = new Integer(y);
                break;
            case 2:
                o = new Integer(r);
                break;
            case 3:
                o = new Double(ImageBrightnessFilter.getNeighborDifference(
                        bi, x, y));
                break;
            default:
                return null;
        }
        return o;
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
            case 0:
            case 1:
            case 2:
                return Integer.class;
            case 3:
                return Double.class;
            default:
                return null;
        }
    }

    @Override
    public int getColumnCount() {
        return columnName.length;
    }

    @Override
    public String getColumnName(int columnIndex) {
        return columnName[columnIndex];
    }

    @Override
    public int getRowCount() {
        if (bi == null) {
            return 80 * 40;
        }
        return bi.getHeight() * bi.getWidth();
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }
}
于 2013-10-12T18:34:45.220 に答える