Java 如何使用boofcv提取象形图?

Java 如何使用boofcv提取象形图?,java,image,boofcv,Java,Image,Boofcv,我在将象形图提取为其他可处理格式时遇到问题,因为现在我得到了如下结果: 当前解决方案的一部分来自BoofCV ImageTresholding示例。此解决方案的我的代码如下所示: import georegression.metric.UtilAngle; import java.awt.Color; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.Buf

我在将象形图提取为其他可处理格式时遇到问题,因为现在我得到了如下结果:

当前解决方案的一部分来自BoofCV ImageTresholding示例。此解决方案的我的代码如下所示:

import georegression.metric.UtilAngle;

import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.IOException;

import boofcv.alg.color.ColorHsv;
import boofcv.alg.filter.binary.BinaryImageOps;
import boofcv.alg.filter.binary.GThresholdImageOps;
import boofcv.alg.filter.binary.ThresholdImageOps;
import boofcv.gui.ListDisplayPanel;
import boofcv.gui.binary.VisualizeBinaryData;
import boofcv.gui.image.ImagePanel;
import boofcv.gui.image.ShowImages;
import boofcv.io.image.ConvertBufferedImage;
import boofcv.io.image.UtilImageIO;
import boofcv.struct.image.ImageFloat32;
import boofcv.struct.image.ImageUInt8;
import boofcv.struct.image.MultiSpectral;

public class Binaryzation {
    static double splitFraction = 0.05;
    static double minimumSideFraction = 0.1;

    static ListDisplayPanel gui = new ListDisplayPanel();

    public static void printClickedColor(final BufferedImage image) {
        ImagePanel gui = new ImagePanel(image);
        gui.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                float[] color = new float[3];
                int rgb = image.getRGB(e.getX(), e.getY());
                ColorHsv.rgbToHsv((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF,
                        rgb & 0xFF, color);
                System.out.println("H = " + color[0] + " S = " + color[1]
                        + " V = " + color[2]);
                try {
                    showSelectedColor("Selected", image, color[0], color[1]);
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        });

        ShowImages.showWindow(gui, "Color Selector");
    }

    public static void showSelectedColor(String name, BufferedImage image,
            float hue, float saturation) throws IOException {

        ImageUInt8 binary = binaryTreshold(name, image, hue, saturation);
        // MAGIC HAPPENDS -removing small objects
        ImageUInt8 filtered = BinaryImageOps.erode4(binary, 1, null);
        filtered = BinaryImageOps.dilate8(filtered, 1, null);
        filtered = BinaryImageOps.removePointNoise(filtered, filtered);
        ShowImages.showWindow(filtered, "Binary " + name);
        BufferedImage visualFiltered1 = VisualizeBinaryData.renderBinary(
                filtered, true, null);
        ShowImages.showWindow(visualFiltered1, "Mask");
        BufferedImage visualFiltered12 = Fill.fill(visualFiltered1);
        ShowImages.showWindow(visualFiltered12, "Filled Mask");

    ImageUInt8 mask = ConvertBufferedImage.convertFromSingle(
            visualFiltered12, null, ImageUInt8.class);

    ImageUInt8 wynik = new ImageUInt8(mask.width, mask.height);

    //subtraction of images: wynik=mask-filtered;
    int min = 0;
    int max = 1;
    for (int i = 0; i < mask.height; i++) {
        // System.out.println("i=" + i);
        for (int j = 0; j < mask.width; j++) {
            // System.out.println("j=" + j);
            if (filtered.get(j, i) < min)
                min = filtered.get(j, i);
            if (filtered.get(j, i) > max)
                max = filtered.get(j, i);

            int filtInt = filtered.get(j, i);
            if (filtInt >= 1)
                filtInt = 1;
            else if (filtInt < 1)
                filtInt = 0;

            int maskInt = mask.get(j, i);
            if (maskInt >= 1)
                maskInt = 0;
            else if (maskInt < 1)
                maskInt = 1;

            int diff = maskInt - filtInt;
            if (diff == 1) {
                diff = 255;
                wynik.set(j, i, diff);
            } else if (diff == 0) {
                diff = 0;
                wynik.set(j, i, diff);
            } else {
                diff = 255;
                wynik.set(j, i, diff);

            }

        }
    }
    ShowImages.showWindow(wynik, "Wynik=Mask-Filtered");
    wynik = BinaryImageOps.erode4(wynik, 1, null);
    wynik = BinaryImageOps.dilate8(wynik, 1, null);
    wynik = BinaryImageOps.removePointNoise(wynik, wynik);
     UtilImageIO.saveImage(wynik, "C:/dev/zdjeciaTestowe/wynik.jpg");
    ShowImages.showWindow(wynik, "Wynik=Mask-Filtered After noise remove");

}

    private static ImageUInt8 binaryTreshold(String name, BufferedImage image,
            float hue, float saturation) throws IOException {
        MultiSpectral<ImageFloat32> input = ConvertBufferedImage
                .convertFromMulti(image, null, true, ImageFloat32.class);
        MultiSpectral<ImageFloat32> hsv = input.createSameShape();

        // Convert into HSV
        ColorHsv.rgbToHsv_F32(input, hsv);

        // Euclidean distance squared threshold for deciding which pixels are
        // members of the selected set
        float maxDist2 = 0.4f * 0.4f;

        // Extract hue and saturation bands which are independent of intensity
        ImageFloat32 H = hsv.getBand(0);
        ImageFloat32 S = hsv.getBand(1);

        // Adjust the relative importance of Hue and Saturation.
        // Hue has a range of 0 to 2*PI and Saturation from 0 to 1.
        float adjustUnits = (float) (Math.PI / 2.0);

        // step through each pixel and mark how close it is to the selected
        // color
        BufferedImage output = new BufferedImage(input.width, input.height,
                BufferedImage.TYPE_INT_RGB);
        for (int y = 0; y < hsv.height; y++) {
            for (int x = 0; x < hsv.width; x++) {
                // Hue is an angle in radians, so simple subtraction doesn't
                // work
                float dh = UtilAngle.dist(H.unsafe_get(x, y), hue);
                float ds = (S.unsafe_get(x, y) - saturation) * adjustUnits;

                // this distance measure is a bit naive, but good enough for to
                // demonstrate the concept
                float dist2 = dh * dh + ds * ds;
                if (dist2 <= maxDist2) {
                    System.out.println(image.getRGB(x, y));
                    output.setRGB(x, y, image.getRGB(x, y));
                }
            }
        }
        ImageFloat32 output1 = ConvertBufferedImage.convertFromSingle(output,
                null, ImageFloat32.class);
        ImageUInt8 binary = new ImageUInt8(input.width, input.height);

        double threshold = GThresholdImageOps.computeOtsu(output1, 0, 255);
        // Apply the threshold to create a binary image
        ThresholdImageOps.threshold(output1, binary, (float) threshold, true);

        return binary;
    }

    public static void main(String args[]) throws IOException {
        BufferedImage image = UtilImageIO
                .loadImage("C:/dev/zdjeciaTestowe/images.jpg");

        // Let the user select a color
        printClickedColor(image);
        // Display pre-selected colors
        showSelectedColor("Yellow", image, 1f, 1f);

    }
}
导入georegression.metric.UtilAngle;
导入java.awt.Color;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.awt.image.buffereImage;
导入java.awt.image.WritableRaster;
导入java.io.IOException;
导入boofcv.alg.color.ColorHsv;
导入boofcv.alg.filter.binary.BinaryImageOps;
导入boofcv.alg.filter.binary.GThresholdImageOps;
导入boofcv.alg.filter.binary.ThresholdImageOps;
导入boofcv.gui.ListDisplayPanel;
导入boofcv.gui.binary.VisualizationBinaryData;
导入boofcv.gui.image.ImagePanel;
导入boofcv.gui.image.ShowImages;
导入boofcv.io.image.convertBuffereImage;
导入boofcv.io.image.UtilImageIO;
导入boofcv.struct.image.ImageFloat32;
导入boofcv.struct.image.ImageUInt8;
导入boofcv.struct.image.MultiSpectral;
公共类二进制化{
静态双分裂分数=0.05;
静态双最小侧分数=0.1;
静态ListDisplayPanel gui=新建ListDisplayPanel();
公共静态无效打印ClickedColor(最终缓冲区图像){
ImagePanel gui=新的ImagePanel(图像);
gui.addMouseListener(新的MouseAdapter(){
@凌驾
公共无效mouseClicked(MouseEvent e){
浮动[]颜色=新浮动[3];
intrgb=image.getRGB(e.getX(),e.getY());
颜色HSV.rgbToHsv((rgb>>16)和0xFF,(rgb>>8)和0xFF,
rgb&0xFF,颜色);
System.out.println(“H=“+color[0]+”S=“+color[1]
+“V=“+颜色[2]);
试一试{
showSelectedColor(“选定”,图像,颜色[0],颜色[1]);
}捕获(IOE1异常){
//TODO自动生成的捕捉块
e1.printStackTrace();
}
}
});
ShowImages.showWindow(gui,“颜色选择器”);
}
public static void showSelectedColor(字符串名称、缓冲区图像、,
浮动色调、浮动饱和度)引发异常{
ImageUInt8 binary=binaryTreshold(名称、图像、色调、饱和度);
//魔术-移除小对象
ImageUInt8 filtered=BinaryImageOps.4(二进制,1,null);
filtered=BinaryImageOps.8(filtered,1,null);
filtered=BinaryImageOps.removePointNoise(已过滤,已过滤);
ShowImages.showWindow(已过滤,“二进制”+名称);
BuffereImage visualFiltered1=VisualizeBinaryData.renderBinary(
过滤,真,空);
ShowImages.showWindow(visualFiltered1,“掩码”);
BuffereImage visualFiltered12=Fill.Fill(visualFiltered1);
ShowImages.showWindow(visualFiltered12,“填充遮罩”);
ImageUInt8掩码=ConvertBuffereImage.convertFromSingle(
visualFiltered12,null,ImageUInt8.class);
ImageUInt8 wynik=新的ImageUInt8(掩码宽度、掩码高度);
//图像减法:wynik=掩模过滤;
int min=0;
int max=1;
对于(int i=0;i最大值)
max=filtered.get(j,i);
int filtInt=filtered.get(j,i);
如果(filtInt>=1)
filtInt=1;
else if(filtInt<1)
filtInt=0;
int maskInt=mask.get(j,i);
如果(maskInt>=1)
maskInt=0;
else if(maskInt<1)
maskInt=1;
int diff=maskInt-filtInt;
如果(差异==1){
差异=255;
wynik.set(j,i,diff);
}否则如果(差异==0){
差异=0;
wynik.set(j,i,diff);
}否则{
差异=255;
wynik.set(j,i,diff);
}
}
}
ShowImages.showWindow(wynik,“wynik=Mask-Filtered”);
wynik=BinaryImageOps.4(wynik,1,null);
wynik=BinaryImageOps.8(wynik,1,null);
wynik=BinaryImageOps.removePointNoise(wynik,wynik);
saveImage(wynik,“C:/dev/zdjeciaTestowe/wynik.jpg”);
ShowImages.showWindow(wynik,“wynik=去除噪声后过滤的遮罩”);
}
私有静态映像UINT8二进制树名(字符串名称、缓冲区映像、,
浮动色调、浮动饱和度)引发异常{
多光谱输入=ConvertBuffereImage
.convertFromMulti(image,null,true,ImageFloat32.class);
多光谱hsv=input.createSameShape();
//转换成高速列车
彩色hsv.rgbToHsv_F32(输入,hsv);
//欧几里德距离平方阈值,用于确定哪些像素是
//所选集合的成员
float maxDist2=0.4f*0.4f;
//提取与强度无关的色调和饱和度带
ImageFloat32 H=hsv.getBand(0);
ImageFloat32 S=hsv.getBand(1);
//调整色调和饱和度的相对重要性。
//色调的范围为0到2*PI,饱和度为0到1。
浮动调整单位=(浮动)(数学PI/2.0);
//单步扫描每个像素,并标记其与选定像素的距离
//颜色
BuffereImage输出=新的BuffereImage(input.width、input.height、,
BuffereImage.TYPE_INT_RGB);
对于(int y=0;yimport java.awt.image.BufferedImage;
import boofcv.struct.image.ImageUInt8;

public class Fill {
    private static final int BLACK = -16777216;
    private static final int WHITE = -1;

    /**
     * @param input Buffered image
     * @return image with filled holes
     */
    public static BufferedImage fill(BufferedImage input) {
        int width = input.getWidth();
        int height = input.getHeight();
        BufferedImage output=new BufferedImage(width, height, input.getType());
        for (int i = 0; i < height; i++) {
            // System.out.println("i=" + i);
            for (int j = 0; j < width; j++) {
                // System.out.println("j=" + j);
                if (input.getRGB(j, i) == WHITE) {
                    output.setRGB(j, i, WHITE);
                } else if (isPreviusWhite(j, i, input)
                        && isAnotherWhiteInLine(j, i, input)) {
                    output.setRGB(j, i, WHITE);
                }
            }
        }
        return output;
    }

    private static boolean isPreviusWhite(int i, int i2, BufferedImage input) {
        boolean condition = false;
        while (1 < i2) {
            if (input.getRGB(i, i2) == WHITE)
                return true;
            i2--;
        }
        return condition;
    }

    private static boolean isAnotherWhiteInLine(int j, int i,
            BufferedImage input) {
        boolean condition = false;
        while (j < input.getWidth()) {
            if (input.getRGB(j, i) == WHITE)
                return true;
            j++;
        }
        return condition;
    }
}