使用 10 种编程语言进行图像二值化
一个简单的图像二值化
引言
有时,我们需要将彩色图像转换为黑白图像。 例如,黑白传真机和复印机都需要将彩色图像转换为黑白图像。 为此,有几种方法,例如二值化和抖动,每种方法都包含几种变体。 前者包括日本发明的用于自动阈值的Otsu方法和最简单的固定阈值方法。
在本文中,我们首先要学习如何处理图像,因此使用了固定阈值方法。 最重要的是学习如何将图像文件读入并处理其中的像素数据。 我们尝试提供尽可能多的编程语言,以便不同的设计人员可以了解如何处理像素数据。 本文提供的编程语言包括 Visual C++ 2010、C++ Builder XE5、Visual C# 2012、Visual Basic .NET 2012、Visual Basic 6.0、JAVA with NetBeans v8.1、DELPHI XE5、Android v4.1.2 with Eclipse、HTML5 + JavaScript 和 Matlab 2011。 作者认为,学习数字图像处理与编程语言无关。 最重要的是学习数字图像处理的知识,因为编程语言只是一种帮助您实现此目标的工具,而不是关键。 因此,作者通过以十种不同的方式演示相同的算法来树立榜样。 目的是证明数字图像处理与编程语言关系不大。
为了使读者能够理解,本文中的所有程序示例都附有英文注释,以便读者不仅可以理解,还可以轻松阅读代码。 如果您有这些开发工具,则可以打开附带的源代码。 无论您选择编译还是解释它们,您都可以运行单步调试来逐步检查算法的计算过程。 或者,您可以在重要的部分或您不理解的部分设置断点,以便程序将停止并等待,直到您检查了所有变量的已保存值。 最重要的是熟悉这种二值化算法,因为它是数字图像处理技术中一种更简单的算法,并且不包含任何晦涩的数学公式。 它只需要设置阈值,然后比较大小以确定黑色或白色。 关键在于如何处理像素和计算像素的索引。
Using the Code
Visual C++ 2010
// The height of the image.
for ( int iY = 0; iY < imageA->DibInfo->bmiHeader.biHeight; iY++ )
{
// The width of the image.
for ( int iX = 0; iX < imageA->DibInfo->bmiHeader.biWidth; iX++ )
{
// The index of pixel, because we use the three depth bit to present one pixel of color.
// Therefore, we have to multiple three.
lIDXA = ( iX * 3 ) + ( iY * imageA->DibInfo->bmiHeader.biWidth * 3 );
// To get the pixel depth of the blue channel.
byteRGB_BA = imageA->DibArry[lIDXA+0];
// To get the pixel depth of the green channel.
byteRGB_GA = imageA->DibArry[lIDXA+1];
// To get the pixel depth of the red channel.
byteRGB_RA = imageA->DibArry[lIDXA+2];
// To transform RGB to Y (gray scale).
dobYUV_YA = (0.299 * byteRGB_RA + 0.587 * byteRGB_GA + 0.114 * byteRGB_BA);
// Set our thresholds, To decide which pixel become to white.
if ( dobYUV_YA > 60 && dobYUV_YA < 160 )
{
lIDXB = ( iX * 3 ) + ( iY * imageB->DibInfo->bmiHeader.biWidth * 3 );
imageB->DibArry[lIDXB+0] = 255;
imageB->DibArry[lIDXB+1] = 255;
imageB->DibArry[lIDXB+2] = 255;
}
// Otherwise, those pixels will be black.
else
{
lIDXB = ( iX * 3 ) + ( iY * imageB->DibInfo->bmiHeader.biWidth * 3 );
imageB->DibArry[lIDXB+0] = 0;
imageB->DibArry[lIDXB+1] = 0;
imageB->DibArry[lIDXB+2] = 0;
}
} // for ( int iX = 0; iX < imageA->DibInfo->bmiHeader.biWidth; iX++ )
} // for ( int iY = 0; iY < imageA->DibInfo->bmiHeader.biHeight; iY++ )
C++ Builder XE5
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
// Create three points of TBitmap object
Graphics::TBitmap *TheBitmap, *TempBitmap, *OriginBitmap;
// Create a threshold.
int Threshold;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Exit1Click(TObject *Sender)
{
// Exit the program
Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OpenFile1Click(TObject *Sender)
{
// If you got a file of the picture, you are able to load it.
if ( OpenPictureDialog1->Execute() )
{
// Disable automatic resize.
Image1->AutoSize=false;
// Enable an automatic stretch.
Image1->Stretch=true;
// Loads a picture file.
Image1->Picture->LoadFromFile(OpenPictureDialog1->FileName);
// Set a point to the picture of loading.
TheBitmap=Image1->Picture->Bitmap;
// Create a new TBitmap object to keep original picture.
OriginBitmap = new Graphics::TBitmap();
// To keep original picture.
OriginBitmap->Assign(TheBitmap);
// Set up TImage object to keep original picture.
Image1->Picture->Bitmap->Assign(TheBitmap);
// If you open picture file successful and then set a flag.
// The means that you have been opened a file.
OpenFile = 1;
// Set the threshold is 100.
Threshold = 100;
// Set the position of the scroll bar is 100.
ScrollBar1->Position = Threshold;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ScrollBar1Change(TObject *Sender)
{
// If you have not opened a file, the flag will be zero, and then returns.
if (OpenFile == 0) {
return;
}
Byte *ptr, *tptr;
// To get a counter of binarization from the scroll bar.
Threshold = (int) ScrollBar1->Position;
// Set up the TImage restore to the original picture.
Image1->Picture->Bitmap->Assign(OriginBitmap);
// To do the times of binarization
TempBitmap = new Graphics::TBitmap();
// To get a current bitmap.
TempBitmap->Assign(TheBitmap);
// To do scan line of the whole picture.
for (int y=0; y < TheBitmap->Height; y++) {
// Set Y position of the image point.
ptr = (Byte*) TheBitmap->ScanLine[y];
// Set Y position of the image point.
tptr = (Byte*) TempBitmap->ScanLine[y];
// To do scan X-axis of the line.
for (int x=0; x < TheBitmap->Width; x++) {
// if the pixel more than the threshold, it should be white.
if (tptr[x] > Threshold) {
ptr[x] = (Byte) 255;
}
// Otherwise, it should be black.
else
{
ptr[x] = (Byte) 0;
}
} // End x
} // End y
// Release the temporal bitmap.
delete TempBitmap;
// Refresh and draw the TImage object
Repaint();
// Set result of binarization of the picture.
Image1->Picture->Bitmap->Assign(TheBitmap);
}
//---------------------------------------------------------------------------
Visual C Sharp 2012
正常
namespace Binarization_for_C_Sharp
{
public partial class Form1 : Form
{
// This is a file name string.
private string curFileName;
// This is a bitmap object.
private System.Drawing.Bitmap curBitmap;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Establish a open file dialog.
OpenFileDialog openDlg = new OpenFileDialog();
// Set a filter to arrange picture format.
openDlg.Filter = "All format | *.bmp; *.pcx; *.png; *.jpg; *.gif;" +
"*.tif; *.ico; *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf";
// Set the title of the open file dialog.
openDlg.Title = "Open a picture file.";
// if open file is successful.
if (openDlg.ShowDialog() == DialogResult.OK)
{
// Get the open file name to current file name variable.
curFileName = openDlg.FileName;
try
{
// Establish a bitmap from file through by Image object.
curBitmap = (Bitmap)Image.FromFile(curFileName);
}
// If we get a exception.
catch (Exception exp)
{
// Pop to a message.
MessageBox.Show(exp.Message);
}
}
// Force to redraw.
Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
// Establish a graphics object from external object
Graphics g = e.Graphics;
// if it is to open file successful.
if (curBitmap != null)
{
// Draw the picture in the position that we set up.
g.DrawImage(curBitmap, 140, 10, curBitmap.Width, curBitmap.Height);
}
}
private void button2_Click(object sender, EventArgs e)
{
// if it is to open file successful.
if (curBitmap != null)
{
// Establish a color object.
Color curColor;
int ret;
// The width of the image.
for (int iX = 0; iX < curBitmap.Width; iX++)
{
// The height of the image.
for ( int iY = 0; iY < curBitmap.Height; iY++ )
{
// Get the pixel from bitmap object.
curColor = curBitmap.GetPixel(iX, iY);
// Transform RGB to Y (gray scale)
ret = (int) (curColor.R * 0.299 + curColor.G * 0.578 + curColor.B * 0.114);
// This is our threshold, you can change it and to try what are different.
if (ret > 120)
{
ret = 255;
}
else
{
ret = 0;
}
// Set the pixel into the bitmap object.
curBitmap.SetPixel( iX, iY, Color.FromArgb ( ret, ret ,ret ) );
} // The closing 'The height of the image'.
} // The closing 'The width of the image'.
// Force to redraw.
Invalidate();
}
}
}
}
快速
private void Form1_Paint(object sender, PaintEventArgs e)
{
// Establish a graphics object from external object
Graphics g = e.Graphics;
// if it is to open file successful.
if (curBitmap != null)
{
// Red
int iR = 0;
// Green
int iG = 0;
// Blue
int iB = 0;
// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);
System.Drawing.Imaging.BitmapData bmpData =
curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
curBitmap.PixelFormat);
// Get the address of the first line.
IntPtr ptr = bmpData.Scan0;
// Declare an array to hold the bytes of the bitmap.
int bytes = Math.Abs(bmpData.Stride) * curBitmap.Height;
byte[] rgbValues = new byte[bytes];
// Copy the RGB values into the array.
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
// Set every third value to 255. A 24bpp bitmap will binarization.
for (int counter = 0; counter < rgbValues.Length; counter += 3)
{
// Get the red channel
iR = rgbValues[counter + 2];
// Get the green channel
iG = rgbValues[counter + 1];
// Get the blue channel
iB = rgbValues[counter + 0];
// If the gray value more than threshold and then set a white pixel.
if ((iR + iG + iB) / 3 > 100)
{
// White pixel
rgbValues[counter + 2] = 255;
rgbValues[counter + 1] = 255;
rgbValues[counter + 0] = 255;
}
else
{
// Black pixel
rgbValues[counter + 2] = 0;
rgbValues[counter + 1] = 0;
rgbValues[counter + 0] = 0;
}
}
// Copy the RGB values back to the bitmap
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
// Unlock the bits.
curBitmap.UnlockBits(bmpData);
// Draw the modified image.
g.DrawImage(curBitmap, 140, 10, curBitmap.Width, curBitmap.Height);
}
}
Visual Basic .NET 2012
Public Class Form1
' Establish a string of the current file name
Private curFileName As String
' Establish a bitmap object of current bitmap object
Private curBitmap As Bitmap
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' Establish a open file dialog.
Dim openFileDialog1 As New OpenFileDialog()
' The initial directory displayed by the file dialog box. The default is an empty string ("").
openFileDialog1.InitialDirectory = ".\"
' The file filtering options available in the dialog box.
openFileDialog1.Filter = "All format | *.bmp; *.pcx; *.png; *.jpg; *.gif;" +
"*.tif; *.ico; *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf"
' A value containing the index of the filter currently selected in the file dialog box.
' The default value is 1.
openFileDialog1.FilterIndex = 1
' true if the dialog box restores the current directory to its original value
' if the user changed
' the directory while searching for files; otherwise, false. The default value is false.
openFileDialog1.RestoreDirectory = True
' If the open file is successful.
If openFileDialog1.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
Try
' Set the file name into current file name.
curFileName = openFileDialog1.FileName
' Make sure the file is not empty.
If (curFileName IsNot Nothing) Then
' Establish a bitmap from file through by Image object.
Dim b As Bitmap = New Bitmap(curFileName)
' Establish a bitmap object from the loaded image of bitmap object.
curBitmap = New Bitmap(b.Width, b.Height, _
System.Drawing.Imaging.PixelFormat.Format32bppPArgb)
' Clone the bitmap object
curBitmap = b.Clone()
End If
' If we have a problem, throw a exception and pop up a message.
Catch Ex As Exception
MessageBox.Show("Cannot read file from disk. Original error: " & Ex.Message)
Finally
' Check this again, since we need to make sure we didn't throw an exception on open.
End Try
' Force to redraw.
Invalidate()
End If
End Sub
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
' if it is to open file successful.
If (curBitmap IsNot Nothing) Then
' Draw the picture in the position that we set up.
e.Graphics.DrawImage(curBitmap, 140, 10, curBitmap.Width, curBitmap.Height)
End If
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
' The height of the image.
For y As Integer = 0 To curBitmap.Height - 1
' The width of the image.
For x = 0 To curBitmap.Width - 1
' Get the pixel from current bitmap object.
Dim curPixColor As Color = curBitmap.GetPixel(x, y)
' This is a gray variable.
Dim ret As Integer
' Transform RGB color space to Y (gray scale)
ret = (curPixColor.R * 0.299 + curPixColor.G * 0.578 + curPixColor.B * 0.114)
' This is our threshold, you can change it.
If ret > 120 Then
curBitmap.SetPixel(x, y, Color.White)
Else
curBitmap.SetPixel(x, y, Color.Black)
End If
' The closing 'The width of the image'.
Next
' The closing 'The height of the image'.
Next
' Force to redraw.
Invalidate()
End Sub
End Class
Visual Basic 6.0
' The Form loading
Private Sub Form_Load()
' Loading a bitmap
Picture1.Picture = LoadPicture(App.Path & "\B_01.bmp")
' The variable is X-axis
Dim lngX As Long
' The variable is Y-axis
Dim lngY As Long
' The variable is gray
Dim intS
' The variable is RGB, respectively.
Dim intR, intG, intB
' Set up the scale mode is pixel.
Picture1.ScaleMode = 3
' Enable the picture box autometic redraw.
Picture1.AutoRedraw = True
' Set up the scale mode is pixel.
Picture2.ScaleMode = 3
' Enable the picture box autometic redraw.
Picture2.AutoRedraw = True
' The height of the image
For lngY = 0 To Picture1.ScaleHeight
' The width of the image
For lngX = 0 To Picture1.ScaleWidth
' Get the pixel of the red channel
intR = (Picture1.Point(lngX, lngY) And &HFF)
' Get the pixel of the green channel
intG = (Picture1.Point(lngX, lngY) And &HFF00&) \ 256
' Get the pixel of the blue channel
intB = (Picture1.Point(lngX, lngY) And &HFF0000) \ 65536
' Make a gray scale pixel
intS = (intR + intG + intB) / 3
' This is our threshold, if it over 120, it should be white.
If intS > 120 Then
intS = 255
' Otherwise, it should be black.
Else
intS = 0
End If
' Set the monochromatic pixel.
Picture2.PSet (lngX, lngY), RGB(intS, intS, intS)
' The closing 'The width of the image'.
Next lngX
' The closing 'The height of the image'.
Next lngY
End Sub
JAVA for NetBeans v8.0.2
import java.awt.FileDialog;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.awt.image.DataBufferByte;
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
FileDialog f = new FileDialog(this, "Open File", FileDialog.LOAD);
// Set the default directory
f.setDirectory(".");
// Display the dialog and wait for the user's response
f.show();
// Remember new default directory.
String directory = f.getDirectory();
// Establish a full path.
String filepath = directory+f.getFile();
// Establish an image object from BufferedImage.
BufferedImage img = null;
try {
// Read an image from the file.
img = ImageIO.read(new File(filepath));
// To do binarization.
int[][] result = convertToBinarization(img);
// Show a processed image.
jLabel1.setIcon(new javax.swing.ImageIcon(img));
}
// We have a problem and then throw an exception.
catch (IOException e) {
System.err.println("I could not load the file \'"+directory+"'. Sorry.");
}
}
// This function is to convert RGB image binarization.
private static int[][] convertToBinarization(BufferedImage image) {
// Get the width of the image.
int width = image.getWidth();
// Get the height of the image.
int height = image.getHeight();
// Establish a 2D array to keep image data.
int[][] result = new int[height][width];
// The height of the image.
for (int row = 0; row < height; row++) {
// The width of the image.
for (int col = 0; col < width; col++) {
// Acquire RGB value.
result[row][col] = image.getRGB(row, col);
// Acqurie integer type of RGB value.
int iRet = result[row][col];
// The alpha variable.
int iA = 0;
// The red variable.
int iR = 0;
// The green variable.
int iG = 0;
// The bule variable.
int iB = 0;
int iGray = 0;
// Get the alpha of the alpha channel.
iA = (((int) iRet & 0xff) << 24);
// Get blue pixel of the blue channel.
iB = ((int) iRet & 0xff);
// Get green pixel of the green channel.
iG = (((int) iRet & 0x00ff00) >> 8);
// Get red pixel of the red channel.
iR = (((int) iRet & 0xff0000) >> 16);
// Transform RGB color space to gray scale.
iG = ( iR + iG + iB ) / 3;
// This is our threshold, you can change it.
if ( iG > 120 )
{
// This is white pixel.
iRet = 0xffffff;
// Set the white pixel into the image.
image.setRGB(row, col, iRet);
}
else
{
// Set the black pixel into the image.
image.setRGB(row, col, 0);
}
}
}
// return result value.
return result;
}
DELPHI XE5
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtDlgs, Vcl.ExtCtrls;
type
TForm1 = class(TForm)
Image1: TImage;
OpenPictureDialog1: TOpenPictureDialog;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
// The string variable is a file name.
Str : String;
implementation
{$R *.dfm}
procedure TForm1.Button2Click(Sender: TObject);
var
PByte :PByteArray;
Gray,x,y :Integer;
ImageBmp :TBitmap;
begin
// if it is no file name and pop up a message.
if Str = '' then
showmessage('Can not open this file, because it is an empty.')
// Otherwise, There is a file name.
else
begin
// Establish a TBitmap object.
ImageBmp :=TBitmap.Create;
// Assign the Image object.
ImageBmp.Assign(Image1.Picture.Bitmap);
// Set pixel format is 24 bits.
ImageBmp.PixelFormat :=pf24Bit;
// The height of the image.
for y:=0 to ImageBmp.Height-1 do
begin
// Set the point up to Y-axis.
PByte := ImageBmp.scanline[y];
// The width of the image.
for x:=0 to ImageBmp.Width-1 do
begin
// Transform RGB color space to gray scale.
Gray:=Round(PByte[x*3+2]*0.3+PByte[x*3+1]*0.59+PByte[x*3]*0.11);
// This is our threshold, you can change it. What is a different?
if Gray > 120 then
// Set the pixel is white.
begin
PByte[x*3]:=255;
PByte[x*3+1]:=255;
PByte[x*3+2]:=255;
end
// Otherwise, set the pixel is black.
else
begin
PByte[x*3]:=0;
PByte[x*3+1]:=0;
PByte[x*3+2]:=0;
end
end;
end;
// Assign a processed image.
Image1.Picture.Bitmap.Assign(ImageBmp);
// Release the TBitmap object.
ImageBmp.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
// The string is full path.
Path:string;
begin
// Set the path is in the path of the execute file.
path:=ExtractFilePath(application.ExeName);
// Set up initial directory.
OpenPictureDialog1.InitialDir := Path;
// Execute the OpenPictureDialog object.
if OpenPictureDialog1.Execute then
begin
// Set a file name into str variable.
Str := OpenPictureDialog1.FileName;
// Loading a picture from the file.
Image1.Picture.LoadFromFile(Str);
end;
end;
end.
Android v4.1.2 with Eclipse
package com.example.binarization.camera;
import com.example.binarization.camera.R;
import android.os.Bundle;
import android.app.Activity;
import android.view.*;
import android.widget.*;
import android.annotation.SuppressLint;
import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PictureCallback;
@SuppressLint("NewApi")
public class MainActivity extends Activity implements SurfaceHolder.Callback {
SurfaceView mSurfaceView ;
Button btn_Capture;
Camera mCamera;
PictureCallback mPictureCB;
AutoFocusCallback mAutoFocusCB;
ImageView ImgView;
TextView txtView;
Bitmap bitmapClone;
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the format of window, as per the PixelFormat types.
// This overrides the default format that is selected by
// the Window based on its window decorations.
// System chooses a format that supports translucency (many alpha bits).
getWindow().setFormat(PixelFormat.TRANSLUCENT);
// Enable extended window features.
// Flag for the "no title" feature, turning off the title at the top of the screen.
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Set the flags of the window, as per the WindowManager.LayoutParams flags.
// Window flag: Hide all screen decorations (e.g. status bar).
// while this window is displayed. This allows the window to use
// the entire display space for itself -- the status bar will be
// hidden when an app window with this flag set is on the top layer.
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// Set the activity content from a layout resource.
// The resource will be inflated, adding all top-level views to the activity.
setContentView(R.layout.activity_main);
// Change the desired orientation of this activity.
// If the activity is currently in the foreground or
// otherwise impacting the screen orientation,
// the screen will immediately be changed
// (possibly causing the activity to be restarted).
// Otherwise, this will be used the next time the activity is visible.
// Constant corresponding to portrait in the android.R.attr.screenOrientation attribute.
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
// -- (Start)
ImgView = (ImageView)this.findViewById(R.id.ImgView);
txtView = (TextView)this.findViewById(R.id.txtView);
btn_Capture = (Button)this.findViewById(R.id.btn_Capture);
mSurfaceView = (SurfaceView)this.findViewById(R.id.surView_Camera);
// -- (End)
// Set and get SurfaceHolder
// Abstract interface to someone holding a display surface.
// Allows you to control the surface size and format,
// edit the pixels in the surface, and monitor changes to the surface.
// This interface is typically available through the SurfaceView class.
// When using this interface from a thread other than the one running
// its SurfaceView, you will want to carefully read the methods
// lockCanvas and Callback.surfaceCreated().
SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// To establish Camera.takePicture callback function.
mPictureCB = new PictureCallback(){
// Image processing.
// Overwrite onPictureTake function.
@Override
public void onPictureTaken(byte[] data, Camera camera){
// We use the BitmapFactory to decode become raw data to bitmap format.
Bitmap mBitmap = BitmapFactory.decodeByteArray(data, 0 , data.length);
bitmapClone = Bitmap.createBitmap(mBitmap.getWidth(),
mBitmap.getHeight(), mBitmap.getConfig());
bitmapClone.copy(mBitmap.getConfig(), true);
int iY = 0;
int iX = 0;
int iPixel = 0;
int iRed = 0;
int iGreen = 0;
int iBlue = 0;
int iRGBAvg = 0;
// Gray of image processing.
// The height of the image
for ( iY = 0; iY < bitmapClone.getHeight(); iY++ )
{
// The width of the image
for ( iX = 0; iX < bitmapClone.getWidth(); iX++ )
{
// To get pixel.
iPixel = mBitmap.getPixel(iX, iY);
// To get value of the red channel.
iRed = Color.red(iPixel);
// To get value of the green channel.
iGreen = Color.green(iPixel);
// To get value of the blue channel.
iBlue = Color.blue(iPixel);
// Compute value of gray.
iRGBAvg = ( iRed + iGreen + iBlue ) / 3;
// This is our threshold, you can change it.
if ( iRGBAvg > 120 )
{
// Set pixel to white.
bitmapClone.setPixel(iX, iY, Color.rgb(255, 255, 255));
}
else
{
// Set pixel to black.
bitmapClone.setPixel(iX, iY, Color.rgb(0, 0, 0));
}
}
}
// Set processed image to display.
ImgView.setImageBitmap(bitmapClone);
// Show the height of the image.
//String strInfo = "";
//strInfo = String.valueOf(mBitmap.getHeight());
//txtView.setText(strInfo);
// Restart camera to preview.
camera.startPreview();
// To disable auto focus of callback function.
camera.autoFocus(null);
}
};
// To establish Camera.AutoFocusCallback
mAutoFocusCB = new AutoFocusCallback(){
@Override
public void onAutoFocus(boolean success, Camera camera){
// When auto focus is done and then we will take a picture.
if ( success == true )
{
// Into take a picture of callback function.
camera.takePicture(null, null, mPictureCB);
}
}
};
// While a user press the take a picture button, when it starts auto focus.
btn_Capture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try{
// To make sure the camera is open.
if(mCamera != null){
// Create a thread.
new Thread(new Runnable() {
public void run() {
// To execute the auto focus.
mCamera.autoFocus(mAutoFocusCB);
}
}).start();
}
}catch(Exception e) {
e.printStackTrace();
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
// Get parameters of the camera.
Camera.Parameters parameters = mCamera.getParameters();
// Set size of the picture.
parameters.setPictureSize(640, 480);
// Set size of preview.
parameters.setPreviewSize(width, height);
// Set auto focus.
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
// Set parameters of the camera.
mCamera.setParameters(parameters);
// Start preview.
mCamera.startPreview();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
// If the camera is initially successful and then to open camera.
if ( mCamera == null )
{
mCamera = Camera.open();
}
try {
// Set SurfaceHolder.
mCamera.setPreviewDisplay(holder);
}catch(Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
// Stop preview.
mCamera.stopPreview();
// Release Camera.
mCamera.release();
}
}
HTML5 + Javascript
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function imageLoaded(ev) {
element = document.getElementById("cancan");
c = element.getContext("2d");
// The image, assumed to be 512x512
im = ev.target;
// Read the width and height of the canvas
width = element.width;
height = element.height;
// Stamp the image on the left of the canvas.
c.drawImage(im, 0, 0);
// Get all canvas pixel data
imageData = c.getImageData(0, 0, width, height);
// The width index is output position.
w2 = width / 2;
// Run through the image.
// The height of the image.
for (y = 0; y < height; y++) {
// *4 for 4 ints per pixel.
// This is an input index.
inpos = y * width * 4;
// This is an output index.
outpos = inpos + w2 * 4
// The width of the image.
for (x = 0; x < w2; x++) {
// Get the pixel of the red channel.
r = imageData.data[inpos++]
// Get the pixel of the green channel.
g = imageData.data[inpos++]
// Get the pixel of the blue channel.
b = imageData.data[inpos++]
// Get the pixel of the alpha channel.
a = imageData.data[inpos++]
// Transform RGB color space to gray scale.
gray = (0.299 * r + 0.587 * g + 0.114 * b)
// This is our threshold. You can change it.
if ( gray > 120 )
{
// Set the pixel is white.
imageData.data[outpos++] = 255;
imageData.data[outpos++] = 255;
imageData.data[outpos++] = 255;
imageData.data[outpos++] = a;
}
else
{
// Set the pixel is black.
imageData.data[outpos++] = 0;
imageData.data[outpos++] = 0;
imageData.data[outpos++] = 0;
imageData.data[outpos++] = a;
}
} // The closing "The width of the image".
} // The closing "The height of the image".
// Put pixel data on canvas.
c.putImageData(imageData, 0, 0);
}
// Establish an image object.
im = new Image();
// Load the javascript function.
im.onload = imageLoaded;
// Code assumes this image is 512x512.
im.src = "B_01.jpg";
</script>
</head>
<body>
<!-- Create a canvas -->
<canvas id="cancan" width="1024", height="512">Canvas</canvas>
</body>
</html>
Matlab
% Load image
x=imread('B_01.bmp');
% Transform RGB color space to gray scale
gray=rgb2gray(x);
% Binarization
BW=im2bw(x);
% Show the image
imshow(BW);
异常
Visual C++ 2010
- 请注意,如果您的位图文件位深度不是 24 位,您应该更改您的位图文件以适应此程序,或者您可以重写此源代码以适合您的位图格式。
- 您必须安装 Microsoft SDK v7.1,因为我包含了
windowscodes.lib
。#pragma comment(lib, "windowscodecs.lib")
C++ Builder XE5
- 您还应该取消选中“构建时使用运行时包”,在:项目 -> 选项 -> 包 -> 运行时包 -> 链接到运行时包 确保取消选中您正在使用的构建配置('release' / 'debug')下的三个项目(“链接到运行时包”、“链接到动态 RTL”和“链接到 Delphi 运行时库”)。
JAVA for NetBeans v8.0.2
- 这是另一种快速获取 RGB 值的方法。 它适用于大型图像。
private static int[][] convertTo2DWithoutUsingGetRGB(BufferedImage image) {
final byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
final int width = image.getWidth();
final int height = image.getHeight();
final boolean hasAlphaChannel = image.getAlphaRaster() != null;
int[][] result = new int[height][width];
if (hasAlphaChannel) {
final int pixelLength = 4;
for (int pixel = 0, row = 0, col = 0; pixel < pixels.length; pixel += pixelLength) {
int argb = 0;
argb += (((int) pixels[pixel] & 0xff) << 24); // alpha
argb += ((int) pixels[pixel + 1] & 0xff); // blue
argb += (((int) pixels[pixel + 2] & 0xff) << 8); // green
argb += (((int) pixels[pixel + 3] & 0xff) << 16); // red
result[row][col] = argb;
col++;
if (col == width) {
col = 0;
row++;
}
}
} else {
final int pixelLength = 3;
for (int pixel = 0, row = 0, col = 0; pixel < pixels.length; pixel += pixelLength) {
int argb = 0;
argb += -16777216; // 255 alpha
argb += ((int) pixels[pixel] & 0xff); // blue
argb += (((int) pixels[pixel + 1] & 0xff) << 8); // green
argb += (((int) pixels[pixel + 2] & 0xff) << 16); // red
result[row][col] = argb;
col++;
if (col == width) {
col = 0;
row++;
}
}
}
return result;
}