Skip to main content

用10種程式語言做影像二值化(Image binarization)

用10種程式語言做影像二值化(Image binarization)

用10種程式語言做影像二值化(Image binarization)

簡介

有些時候,我們需要將彩色影像轉換為黑白影像,這很簡單,利用門檻值的方法就可以做到。

作法

Visual C++ 2010

image.png


// 影像的高度
for ( int iY = 0; iY < imageA->DibInfo->bmiHeader.biHeight; iY++ )
{
    // 影像的寬度
    for ( int iX = 0; iX < imageA->DibInfo->bmiHeader.biWidth; iX++ )
    {
        // 影像的索引值,因為這張影像的24 bit ,所以要乘以3
        lIDXA = ( iX * 3 ) + ( iY * imageA->DibInfo->bmiHeader.biWidth * 3 );
        // 取得藍色像素值
        byteRGB_BA = imageA->DibArry[lIDXA+0];
        // 取得綠色像素值
        byteRGB_GA = imageA->DibArry[lIDXA+1];
        // 取得紅色像素值
        byteRGB_RA = imageA->DibArry[lIDXA+2];
        // 將RGB利用YUV公式轉換Y(灰階)
        dobYUV_YA =  (0.299 * byteRGB_RA + 0.587 * byteRGB_GA + 0.114 * byteRGB_BA);
        // 利用雙門檻值,灰階轉換黑白
        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;
        }
        // 門檻值之外的填為黑色
        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;
        }
    } // 影像的寬度
} // 影像的高度

C++ Builder XE5

image.png

image.png


//---------------------------------------------------------------------------

#include < vcl.h >
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
// 建立三個 TBitmap object 的指標
Graphics::TBitmap *TheBitmap, *TempBitmap, *OriginBitmap;
// 宣告一個門檻值變數
int Threshold;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Exit1Click(TObject *Sender)
{
    // 離開程式
    Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OpenFile1Click(TObject *Sender)
{
    // 利用圖檔開啟對話框,開啟圖檔
    if ( OpenPictureDialog1->Execute() )
    {
        // 關閉自動調整大小
        Image1->AutoSize=false;
        // 啟用伸展調整
        Image1->Stretch=true;
        // 載入開啟的圖檔
        Image1->Picture->LoadFromFile(OpenPictureDialog1->FileName);
        // 設定影像指標,指向開啟的圖檔
        TheBitmap=Image1->Picture->Bitmap;
        // 建立一個 TBitmap object 保留原始影像
        OriginBitmap = new Graphics::TBitmap();
        // 保留原始影像
        OriginBitmap->Assign(TheBitmap);
        // 設定 TImage object 保留原始影像
        Image1->Picture->Bitmap->Assign(TheBitmap);
        // 如果檔案開啟成功,就設定一個旗標值
        // 代表成功地開啟了一個檔案
        OpenFile = 1;
        // 設定門檻值
        Threshold = 100;
        // 設定水平滑動軸的位置為門檻值
        ScrollBar1->Position = Threshold;
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ScrollBar1Change(TObject *Sender)
{
    // 如果開啟檔案旗標為零,則退出副程式
    if (OpenFile == 0) {
        return;
    }
    Byte *ptr, *tptr;
    // 由水平滑動軸獲得門檻值
    Threshold = (int) ScrollBar1->Position;
    // 設定 TImage 回復為原始影像
    Image1->Picture->Bitmap->Assign(OriginBitmap);
    // 建立暫存影像
    TempBitmap = new Graphics::TBitmap();
    // 暫存影像轉存至當下的影像
    TempBitmap->Assign(TheBitmap);
    // 影像的高度
    for (int y=0; y < TheBitmap->Height; y++) {
        // 設定水平掃描線的指標,指向 TheBitmap
        ptr = (Byte*) TheBitmap->ScanLine[y];
        // 設定水平掃描線的指標,指向暫存 TempBitmap
        tptr = (Byte*) TempBitmap->ScanLine[y];
        // 影像的寬度
        for (int x=0; x < TheBitmap->Width; x++) {
        // 假如暫存影像像素大於門檻值,就分類為白色
        if (tptr[x] > Threshold) {
            ptr[x] = (Byte) 255;
        }
        // 若暫存影像像素小於門檻值,就分類為黑色
        else
        {
            ptr[x] = (Byte) 0;
        }
    } // 影像的寬度
} // 影像的高度
// 釋放暫存影像指標
delete TempBitmap;
// 重繪視窗
Repaint();
// 設定二值化後的影像結果給 Image1
Image1->Picture->Bitmap->Assign(TheBitmap);
}
//---------------------------------------------------------------------------

Visual C# 2012

image.png


namespace Binarization_for_C_Sharp
{
    public partial class Form1 : Form
    {
        // 宣告檔名字串
        private string curFileName;
        // 宣告 bitmap object.
        private System.Drawing.Bitmap curBitmap;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // 建立一個檔案開啟對話框
            OpenFileDialog openDlg = new OpenFileDialog();
            // 設應檔案開啟對話框過濾副檔名的條件
            openDlg.Filter = "All format | *.bmp; *.pcx; *.png; *.jpg; *.gif;" +
                "*.tif; *.ico; *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf";
            // 設定檔案開啟對話框的標題
            openDlg.Title = "Open a picture file.";
            // 如果檔案對話框開啟圖檔成功
            if (openDlg.ShowDialog() == DialogResult.OK)
            {
                // 將檔名設定給檔名字串
                curFileName = openDlg.FileName;
                try
                {
                    // 經由檔名建立BMP影像物件
                    curBitmap = (Bitmap)Image.FromFile(curFileName);
                }
                // 如果獲得例外
                catch (Exception exp)
                {
                    // 跳出並顯示錯誤訊息
                    MessageBox.Show(exp.Message);
                }
            }
            // 重繪視窗
            Invalidate();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            // 從外部物件建立一個 graphics object
            Graphics g = e.Graphics;
            // 如果圖檔開啟成功
            if (curBitmap != null)
            {
                // 將開啟的圖檔繪製到 Graphics 的物件中
                g.DrawImage(curBitmap, 140, 10, curBitmap.Width, curBitmap.Height);
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            // 如果圖檔開啟成功
            if (curBitmap != null)
            {
                // 建立一個 color object.
                Color curColor;
                int ret;
                // 影像的寬度
                for (int iX = 0; iX < curBitmap.Width; iX++)
                {
                    // 影像的高度
                    for ( int iY = 0; iY < curBitmap.Height; iY++ )
                    {
                        // 獲得RGB像素值
                        curColor = curBitmap.GetPixel(iX, iY);
                        // 轉換RGB到YUV的Y(灰階)
                        ret = (int) (curColor.R * 0.299 + curColor.G * 0.578 + curColor.B * 0.114);
                        // 設定一個單門檻值,大於則為白色,小於則黑色
                        if (ret > 120)
                        {
                            ret = 255;
                        }
                        else
                        {
                            ret = 0;
                        }
                        // 寫入新的像素值
                        curBitmap.SetPixel( iX, iY, Color.FromArgb ( ret, ret ,ret ) );
                    } // 影像的寬度
                } // 影像的高度
                // 重繪視窗
                Invalidate();
            }
        }
    }
}

Visual Basic .NET 2012

image.png


Public Class Form1
    ' 建立一個檔名字串
    Private curFileName As String
    ' 建立一個 bitmap object
    Private curBitmap As Bitmap

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ' 建立一個開啟檔案對話框
        Dim openFileDialog1 As New OpenFileDialog()
        ' 設定對話框初始目錄
        openFileDialog1.InitialDirectory = ".\"
        ' 設定對話框過濾副檔名
        openFileDialog1.Filter = "All format | *.bmp; *.pcx; *.png; *.jpg; *.gif;" +
            "*.tif; *.ico; *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf"
        ' 設定對話框過濾副檔名的索引值,預設是1
        openFileDialog1.FilterIndex = 1
        ' 設定對話框每次開啟的時候,都回到最後開啟檔案的目錄
        ' 預設值是否(false)
        openFileDialog1.RestoreDirectory = True
        ' 如果檔案成功的開啟
        If openFileDialog1.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
            Try
                ' 設定對話框開啟的檔名給檔名字串
                curFileName = openFileDialog1.FileName
                ' 確認檔名不是空白
                If (curFileName IsNot Nothing) Then
                    ' 經由檔名建立一個BMP物件,名為b
                    Dim b As Bitmap = New Bitmap(curFileName)
                    ' 經由b建立一個大小及色彩空間相同的BMP物件
                    curBitmap = New Bitmap(b.Width, b.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb)
                    ' 將b複製到BMP物件
                    curBitmap = b.Clone()
                End If
            ' 如果出現例外,就顯示錯誤訊息
            Catch Ex As Exception
                MessageBox.Show("Cannot read file from disk. Original error: " & Ex.Message)
            Finally
            End Try
            ' 重繪視窗
            Invalidate()
        End If
    End Sub

    Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
        ' 如果圖檔成功開啟
        If (curBitmap IsNot Nothing) Then
            ' 將BMP繪製在Graphics物件中
            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
        ' 影像的高度
        For y As Integer = 0 To curBitmap.Height - 1
            ' 影像的寬度
            For x = 0 To curBitmap.Width - 1
                ' 獲得RGB像素值
                Dim curPixColor As Color = curBitmap.GetPixel(x, y)
                ' 宣告灰階像素值變數
                Dim ret As Integer
                ' 轉換RGB到YUV的Y(灰階)
                ret = (curPixColor.R * 0.299 + curPixColor.G * 0.578 + curPixColor.B * 0.114)
                ' 像素值若大於門檻值,則為白色,反之,黑色
                If ret > 120 Then
                    curBitmap.SetPixel(x, y, Color.White)
                Else
                    curBitmap.SetPixel(x, y, Color.Black)
                End If
            ' 影像的寬度
            Next
        ' 影像的高度
        Next
        ' 重繪視窗
        Invalidate()
    End Sub
End Class

Visual Basic 6.0

image.png


' 當表單載入時的副程式
Private Sub Form_Load()
    ' 經由檔名載入影像
    Picture1.Picture = LoadPicture(App.Path & "\B_01.bmp")
    ' 宣告X軸變數
    Dim lngX As Long
    ' 宣告Y軸變數
    Dim lngY As Long
    ' 宣告灰階變數
    Dim intS
    ' 分別宣告RGB變數
    Dim intR, intG, intB
    ' Set up the scale mode is pixel.
    Picture1.ScaleMode = 3
    ' 設定圖形框自動重繪
    Picture1.AutoRedraw = True
    ' 設定圖形框的單位為像素
    Picture2.ScaleMode = 3
    ' 設定圖形框自動重繪
    Picture2.AutoRedraw = True
    ' 影像的高度
    For lngY = 0 To Picture1.ScaleHeight
        ' 影像的寬度
        For lngX = 0 To Picture1.ScaleWidth
            ' 取得紅色像素值
            intR = (Picture1.Point(lngX, lngY) And &HFF)
            ' 取得綠色像素值
            intG = (Picture1.Point(lngX, lngY) And &HFF00&) \ 256
            ' 取得藍色像素值
            intB = (Picture1.Point(lngX, lngY) And &HFF0000) \ 65536
            ' RGB轉換為灰階值
            intS = (intR + intG + intB) / 3
            ' 灰階值大於門檻值,則為白色
            If intS > 120 Then
                intS = 255
            ' 反之,則為黑色
            Else
                intS = 0
            End If
            ' 將黑白像素值寫入圖形框
            Picture2.PSet (lngX, lngY), RGB(intS, intS, intS)
        ' 影像的寬度
        Next lngX
    ' 影像的高度
    Next lngY
End Sub

JAVA with NetBeans v8.1

image.png


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);
    // 設定檔案開啟對話框的初始目錄
    f.setDirectory(".");      
    // 顯示檔案對話框,並等待使用者操作
    f.show();
    // 紀錄檔案目錄字串
    String directory = f.getDirectory();
    // 建立檔案路徑及名稱的字串
    String filepath = directory+f.getFile();
    // 宣告 BufferedImage 物件
    BufferedImage img = null;
    try {
        // 經由檔案路徑及名稱讀取圖檔
        img = ImageIO.read(new File(filepath));
        // 準備二值化
        int[][] result = convertToBinarization(img);
        // 顯示二值化影像
        jLabel1.setIcon(new javax.swing.ImageIcon(img));
    }
    // 如果出現例外,則顯示錯誤訊息
    catch (IOException e) {
        System.err.println("I could not load the file \'"+directory+"'.  Sorry.");
    }
}

// RGB影像二值化的函式
private static int[][] convertToBinarization(BufferedImage image) {
    // 獲得影像的寬度
    int width = image.getWidth();
    // 獲得影像的高度
    int height = image.getHeight();
    // 建立二維陣列紀錄影像像素資料
    int[][] result = new int[height][width];
    // 影像的高度
    for (int row = 0; row < height; row++) {
        // 影像的寬度
        for (int col = 0; col < width; col++) {
            // 獲得RGB值
            result[row][col] = image.getRGB(row, col);
            // 獲得整數的RGB值
            int iRet = result[row][col];
            // 宣告透明度(alpha)變數
            int iA = 0;
            // 宣告紅色變數
            int iR = 0;
            // 宣告綠色變數
            int iG = 0;
            // 宣告藍色變數
            int iB = 0;
            int iGray = 0;
            // 獲得透明度值
            iA = (((int) iRet & 0xff) << 24);
            // 獲得藍色值
            iB = ((int) iRet & 0xff);
            // 獲得綠色值
            iG = (((int) iRet & 0x00ff00) >> 8);
            // 獲得紅色值
            iR = (((int) iRet & 0xff0000) >> 16);
            // RGB轉換為灰階
            iG = ( iR + iG + iB ) / 3;
            // 灰階值大於門檻值
            if ( iG > 120 )
            {
                // 設定為白色
                iRet = 0xffffff;
                // 寫入白色值到影像中
                image.setRGB(row, col, iRet);
            }
            else
            {
                // 寫入黑色值到影像中
                image.setRGB(row, col, 0);
            }
        }
    }
    // 回傳處理結果值
    return result;
}

DELPHI XE5

image.png


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;
  // 宣告檔名字串
  Str : String;
implementation

{$R *.dfm}



procedure TForm1.Button2Click(Sender: TObject);
var
  PByte :PByteArray;
  Gray,x,y :Integer;
  ImageBmp :TBitmap;
begin
  // 如果檔名字串為空白,則顯示錯誤訊息
  if Str = '' then
  showmessage('Can not open this file, because it is an empty.')
  // 反之,有檔名則繼續處理
  else
  begin
  // 建立一個TBitmap object.
  ImageBmp :=TBitmap.Create;
  // 儲存開啟的圖檔資料
  ImageBmp.Assign(Image1.Picture.Bitmap);
  // 設定影像格式為 24 bits
  ImageBmp.PixelFormat :=pf24Bit;
  // 影像的高度
  for y:=0 to ImageBmp.Height-1 do
  begin
    // 設定Y軸掃描線
    PByte := ImageBmp.scanline[y];
    // 影像的寬度
    for x:=0 to ImageBmp.Width-1 do
    begin
      // 四捨五入轉換RGB為YUV的Y(灰階)
      Gray:=Round(PByte[x*3+2]*0.3+PByte[x*3+1]*0.59+PByte[x*3]*0.11);
      // 當灰階值大於門檻值
      if Gray > 120 then
      // 設定為白色
      begin
        PByte[x*3]:=255;
        PByte[x*3+1]:=255;
        PByte[x*3+2]:=255;
      end
      // 反之,則為黑色
      else
      begin
        PByte[x*3]:=0;
        PByte[x*3+1]:=0;
        PByte[x*3+2]:=0;
      end
    end;
  end;
  // 影像框儲存處理後的影像
  Image1.Picture.Bitmap.Assign(ImageBmp);
  // 釋放 TBitmap object 的記憶體
  ImageBmp.Free;
end;
end;



procedure TForm1.Button1Click(Sender: TObject);
var
  // 宣告完整路徑的字串
  Path:string;
begin
  // 記錄路徑為應用程式的路徑
  path:=ExtractFilePath(application.ExeName);
  // 設定圖形開啟對話框的初始路徑
  OpenPictureDialog1.InitialDir := Path;
  // 顯示圖形開啟對話框
  if OpenPictureDialog1.Execute then
  begin
    // 記錄圖形開啟對話框的檔案名稱
    Str := OpenPictureDialog1.FileName;
    // 藉由檔案名稱載入圖檔
    Image1.Picture.LoadFromFile(Str);
  end;
end;

end.

Android v4.1.2 with Eclipse

image.png


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);
        // 設定視窗的像素格式為允許透明值(alpha)
        // 設定這個數值會覆寫掉原來系統預設值
        getWindow().setFormat(PixelFormat.TRANSLUCENT);
        // 設定視窗特徵為沒有標題
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        // 設定視窗版型為全螢幕
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
        WindowManager.LayoutParams.FLAG_FULLSCREEN);             
        // 藉由資源類別(R)設定視窗的版型
        setContentView(R.layout.activity_main);
        // 設定視窗的方向          
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        // 設定元件
        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);
        // 宣告並獲得 SurfaceHolder,這允許控制或改變像素
        SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.addCallback(this);
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        // 建立拍照的回呼函式
        mPictureCB = new PictureCallback(){
        // 開始二值化
        // 覆寫 onPictureTaken 函式.
            @Override
            public void onPictureTaken(byte[] data, Camera camera){
                // BitmapFactory 可以解碼RAW資料為BMP格式
                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;
                // 灰階影像處理轉黑白影像
                // 影像的高度
                for ( iY = 0; iY < bitmapClone.getHeight(); iY++ )
                {
                    // 影像的寬度
                    for ( iX = 0; iX < bitmapClone.getWidth(); iX++ )
                    {
                        // 獲得像素值
                        iPixel = mBitmap.getPixel(iX, iY);
                        // 獲得紅色像素
                        iRed = Color.red(iPixel);
                        // 獲得綠色像素
                        iGreen = Color.green(iPixel);
                        // 獲得藍色像素
                        iBlue = Color.blue(iPixel);
                        // 計算灰階值
                        iRGBAvg = ( iRed + iGreen + iBlue ) / 3;
                        // 當灰階值大於門檻值
                        if ( iRGBAvg > 120 )
                        {
                            // 設定像素為白色
                            bitmapClone.setPixel(iX, iY, Color.rgb(255, 255, 255));
                        }
                        else
                        {
                            // 設定像素為黑色
                            bitmapClone.setPixel(iX, iY, Color.rgb(0, 0, 0));
                        }
                    }
                }

                // 設定顯示處理過的影像
                ImgView.setImageBitmap(bitmapClone);
                // 攝影機啟動預覽
                camera.startPreview();
                // 關閉自動對焦回呼函式
                camera.autoFocus(null);
            }
};

// 建立自動對焦回呼函式
mAutoFocusCB = new AutoFocusCallback(){
    @Override
    public void onAutoFocus(boolean success, Camera camera){
        // 當對焦成功時,才執行拍照功能
        if ( success == true )
        {
            // 進入拍照回呼函式
            camera.takePicture(null, null, mPictureCB);                                    
        }
    }
};

// 當使用者按下拍照鈕,開啟自動對焦回呼函式
btn_Capture.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        try{
        // 確認攝影機有開啟
            if(mCamera != null){
                // 建立一個執行緒
                new Thread(new Runnable() {
                    public void run() {
                        // 執行自動對焦
                        mCamera.autoFocus(mAutoFocusCB);
                    }
                }).start();
            }
        }catch(Exception e) {
            e.printStackTrace();
        }
    }
});             

}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    // 獲得相機參數
    Camera.Parameters parameters = mCamera.getParameters();
    // 設定影像大小
    parameters.setPictureSize(640, 480);
    // 設定預覽大小
    parameters.setPreviewSize(width, height);
    // 設定自動對焦
    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
    // 將參數寫入相機
    mCamera.setParameters(parameters);
    // 開始預覽
    mCamera.startPreview();
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    // 如果相機初始化成功就開啟相機
    if ( mCamera == null )
    {
        mCamera = Camera.open();
    }
    try {
        // 設定 SurfaceHolder.
        mCamera.setPreviewDisplay(holder);
    }catch(Exception e) {
        e.printStackTrace();
    }    
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    // 停止預覽
    mCamera.stopPreview();      
    // 釋放相機
    mCamera.release();
    }
}

HTML5 + Javascript

image.png


<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function imageLoaded(ev) {
    element = document.getElementById("cancan");
    c = element.getContext("2d");
    // 這張影像解析度為 512x512
    im = ev.target;
    // 讀取影像元素的寬與高
    width = element.width;
    height = element.height;
    // 設定左邊 canvas 的位置
    c.drawImage(im, 0, 0);
    // 獲得左邊 canvas 的像素資料
    imageData = c.getImageData(0, 0, width, height);
    // 右邊 canvas 的X軸起始位置
    w2 = width / 2;
    // 開始二值化
    // 影像的高度
    for (y = 0; y < height; y++) {
        // 每一個像素值為 32 bits
        // 設定Y軸索引值
        inpos = y * width * 4;
        // 設定輸出索引值
        outpos = inpos + w2 * 4
        // 影像的寬度
        for (x = 0; x < w2; x++) {
            // 取得紅色像素
            r = imageData.data[inpos++]
            // 取得綠色像素
            g = imageData.data[inpos++]
            // 取得藍色像素
            b = imageData.data[inpos++]
            // 取得透明值
            a = imageData.data[inpos++]
            // RGB轉換YUV的Y(灰階)
            gray = (0.299 * r + 0.587 * g + 0.114 * b)
            // 若灰階值大於門檻值
            if ( gray > 120 )
            {
                // 設定輸出像素為白色
                imageData.data[outpos++] = 255;
                imageData.data[outpos++] = 255;
                imageData.data[outpos++] = 255;
                imageData.data[outpos++] = a;
            }
            else
            {
                // 設定輸出像素為黑色
                imageData.data[outpos++] = 0;
                imageData.data[outpos++] = 0;
                imageData.data[outpos++] = 0;
                imageData.data[outpos++] = a;
            }
        } // 影像的寬度
    } // 影像的高度

    // 將影像資料繪製在 canvas.
    c.putImageData(imageData, 0, 0);
}

// 建立影像物件.
im = new Image();
// 設定JavaScript的函式
im.onload = imageLoaded;
// 這張影像的解析度是 512x512.
im.src = "B_01.jpg";
</script>
</head>

<body>
<!—建立一個 canvas -->
<canvas id="cancan" width="1024", height="512">Canvas</canvas>
</body>
</html>

Matlab 2011

image.png


% 載入影像
x=imread('B_01.bmp');
% RGB轉換為灰階
gray=rgb2gray(x);
% 二值化
BW=im2bw(x);
% 顯示影像
imshow(BW);

Popular posts from this blog

Python 日期與時間的處理

數位影像處理:最佳化處理策略之快速消除扭曲演算法

寫作:波蘭文學習之旅:1-1. 波蘭文字母與發音(注音版)

Python 日期與時間的處理

Image

數位影像處理:最佳化處理策略之快速消除扭曲演算法

Image

寫作:波蘭文學習之旅:1-1. 波蘭文字母與發音(注音版)

Image

Visual Basic 6.0 (VB6) 程式語言案例學習 (10. 條碼列印程式)

Image

Visual Basic 6.0 (VB6) 程式語言案例學習 (07. 收據列印程式)

Image

Visual Basic .Net (VB.Net) 程式語言案例學習 (06. 題庫測驗系統)

Image

Visual Basic 6.0 (VB6) 程式語言案例學習 (11. 生產線拍照程式)

Image

Visual Basic 6.0 (VB6) 程式語言案例學習 (04. 人事考勤管理系統)

Image

Visual Basic .Net (VB.Net) 程式語言案例學習 (03. 場地預約系統)

Image