当前位置: 首页 > 面试题库 >

在Android中对图像进行二值化

公冶京
2023-03-14
问题内容

我正在开发一个使用tesseract OCR扫描图像中文本的android应用,
听说在对其执行OCR之前对图像进行二值化处理会产生更好的结果,
所以我开始寻找可以执行此操作的代码,

我发现很少,但实际上是在Java中,并且需要awt库…因此它们在android上不起作用。
所以你能帮我找到一个吗?
谢谢


问题答案:

一个简单的解决方案

在下文中,我仅根据正常的3维空间距离公式更改图像中的每个像素。我根据像素与每种颜色的距离来决定像素应为黑色还是白色。例如,(1,2,3)比(255,255,255)更接近(0,0,0),因此将其确定为黑色。我敢肯定还有更多聪明的算法。这只是一个简单的

MainActivity.java

package com.example.binarizeimage;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.widget.ImageView;

import com.example.binarizeimage.R.drawable;

/**
 * @author Sherif elKhatib - shush
 *
 */
public class MainActivity extends Activity {
    /**
     * Boolean that tells me how to treat a transparent pixel (Should it be black?)
     */
    private static final boolean TRASNPARENT_IS_BLACK = false;
    /**
     * This is a point that will break the space into Black or white
     * In real words, if the distance between WHITE and BLACK is D;
     * then we should be this percent far from WHITE to be in the black region.
     * Example: If this value is 0.5, the space is equally split.  
     */
    private static final double SPACE_BREAKING_POINT = 13.0/30.0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //this is the original image
        Bitmap theOriginalImage = BitmapFactory.decodeResource(this.getResources(), drawable.ic_launcher);
        //this is the image that is binarized
        Bitmap binarizedImage = convertToMutable(theOriginalImage);
        // I will look at each pixel and use the function shouldBeBlack to decide 
        // whether to make it black or otherwise white
        for(int i=0;i<binarizedImage.getWidth();i++) {
            for(int c=0;c<binarizedImage.getHeight();c++) {
                int pixel = binarizedImage.getPixel(i, c);
                if(shouldBeBlack(pixel))
                    binarizedImage.setPixel(i, c, Color.BLACK);
                else
                    binarizedImage.setPixel(i, c, Color.WHITE);
            }
        }


        ImageView iv = (ImageView) findViewById(R.id.imageView1);
        ImageView ivb = (ImageView) findViewById(R.id.ImageView01);
        //show the original image
        iv.setImageBitmap(BitmapFactory.decodeResource(this.getResources(), drawable.ic_launcher));
        //show the binarized image
        ivb.setImageBitmap(binarizedImage);
    }
    /**
     * @param pixel the pixel that we need to decide on
     * @return boolean indicating whether this pixel should be black
     */
    private static boolean shouldBeBlack(int pixel) {
        int alpha = Color.alpha(pixel);
        int redValue = Color.red(pixel);
        int blueValue = Color.blue(pixel);
        int greenValue = Color.green(pixel);
        if(alpha == 0x00) //if this pixel is transparent let me use TRASNPARENT_IS_BLACK
            return TRASNPARENT_IS_BLACK;
        // distance from the white extreme
        double distanceFromWhite = Math.sqrt(Math.pow(0xff - redValue, 2) + Math.pow(0xff - blueValue, 2) + Math.pow(0xff - greenValue, 2));
        // distance from the black extreme //this should not be computed and might be as well a function of distanceFromWhite and the whole distance
        double distanceFromBlack = Math.sqrt(Math.pow(0x00 - redValue, 2) + Math.pow(0x00 - blueValue, 2) + Math.pow(0x00 - greenValue, 2));
        // distance between the extremes //this is a constant that should not be computed :p
        double distance = distanceFromBlack + distanceFromWhite;
        // distance between the extremes
        return ((distanceFromWhite/distance)>SPACE_BREAKING_POINT);
    }
    /**
     * @author Derzu
     * 
     * @see http://stackoverflow.com/a/9194259/833622
     * 
     * Converts a immutable bitmap to a mutable bitmap. This operation doesn't allocates
     * more memory that there is already allocated.
     * 
     * @param imgIn - Source image. It will be released, and should not be used more
     * @return a copy of imgIn, but muttable.
     */
    html" target="_blank">public static Bitmap convertToMutable(Bitmap imgIn) {
        try {
            //this is the file going to use temporally to save the bytes. 
            // This file will not be a image, it will store the raw image data.
            File file = new File(Environment.getExternalStorageDirectory() + File.separator + "temp.tmp");

            //Open an RandomAccessFile
            //Make sure you have added uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
            //into AndroidManifest.xml file
            RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");

            // get the width and height of the source bitmap.
            int width = imgIn.getWidth();
            int height = imgIn.getHeight();
            Config type = imgIn.getConfig();

            //Copy the byte to the file
            //Assume source bitmap loaded using options.inPreferredConfig = Config.ARGB_8888;
            FileChannel channel = randomAccessFile.getChannel();
            MappedByteBuffer map = channel.map(MapMode.READ_WRITE, 0, imgIn.getRowBytes()*height);
            imgIn.copyPixelsToBuffer(map);
            //recycle the source bitmap, this will be no longer used.
            imgIn.recycle();
            System.gc();// try to force the bytes from the imgIn to be released

            //Create a new bitmap to load the bitmap again. Probably the memory will be available. 
            imgIn = Bitmap.createBitmap(width, height, type);
            map.position(0);
            //load it back from temporary 
            imgIn.copyPixelsFromBuffer(map);
            //close the temporary file and channel , then delete that also
            channel.close();
            randomAccessFile.close();

            // delete the temp file
            file.delete();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return imgIn;
    }
}
  • activity_main.xml *

    xmlns:android="http://schemas.android.com



 类似资料:
  • 这是logcat 08-12 08:52:32.887:D/DalvikVM(774):GC_CONCURRENT释放71K,7%释放2765K/2964K,暂停23ms+15ms,总计94ms 08-12 08:52:33.497:D/gralloc_goldfish(774):检测到没有GPU仿真的仿真器。 08-12 08:52:40.698:D/DalvikVM(774):GC_CONCU

  • 我补充了这样的意图: 现在它在选择器中显示dropbox应用程序,但我无法从中选择图像。它只是启动dropbox应用程序,而不选择和返回到我的应用程序的可能性。

  • 本文向大家介绍在python2.7中用numpy.reshape 对图像进行切割的方法,包括了在python2.7中用numpy.reshape 对图像进行切割的方法的使用技巧和注意事项,需要的朋友参考一下 遇到这么个需求:把图片按照定义的patchsize切块,然后按照z轴顺序叠放小块,如下图(仅考虑灰度图像) 图片im,设size为(h,w),patchsize为(ph,pw),则处理后大小(

  • 目标 在本教程中,您将学习简单二值化,自适应二值化,Otsu 二值化等。 你会学到这些函数:cv2.threshold,cv2.adaptiveThreshold 等。 简单二值化 简单二值化是很直截了当的一种方法。如果像素值大于阈值,则分配一个值(可以是白色),否则分配另一个值(可以是黑色)。使用的函数是cv2.threshold。第一个参数是源图像,这应该是灰度图像。第二个参数是用于分类像素值

  • 目标 学习对图像应用不同的几何变换,如平移,旋转,仿射变换等。 你会学到这些函数:cv2.getPerspectiveTransform 变换 OpenCV 提供了两个转换函数,cv2.warpAffine 和 cv2.warpPerspective,可以进行各种变换。 cv2.warpAffine 采用 2x3 变换矩阵,而 cv2.warpPerspective 采用3x3变换矩阵作为输入。

  • 本文向大家介绍彩色图像、灰度图像、二值图像和索引图像区别?相关面试题,主要包含被问及彩色图像、灰度图像、二值图像和索引图像区别?时的应答技巧和注意事项,需要的朋友参考一下 彩色图像:RGB图像。灰度图像:0-255像素值。二值图像:0和1,用于掩膜图像。 索引图像:在灰度图像中,自定义调色板,自定义输出256种颜色值。