在Android中对图像进行二值化

我正在开发一个使用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.

*/

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:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context=".MainActivity" >

    <TextView

    android:id="@+id/textView2"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:text="@string/hello_world" />

    <TextView

    android:id="@+id/textView1"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_below="@+id/textView2"

    android:layout_centerHorizontal="true"

    android:text="Original Image" />

    <ImageView

    android:id="@+id/imageView1"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_below="@+id/textView1"

    android:layout_centerHorizontal="true"

    android:src="@drawable/ic_launcher" />

    <TextView

    android:id="@+id/TextView02"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_alignLeft="@+id/textView1"

    android:layout_below="@+id/imageView1"

    android:layout_centerHorizontal="true"

    android:layout_marginTop="28dp"

    android:text="YES/NO Image" />

    <ImageView

    android:id="@+id/ImageView01"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_below="@+id/TextView02"

    android:layout_centerHorizontal="true"

    android:src="@drawable/ic_launcher" />

以上是 在Android中对图像进行二值化 的全部内容, 来源链接: utcz.com/qa/419315.html

回到顶部