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

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

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

Python 日期與時間的處理

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

Image

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

Image

Python 日期與時間的處理

Image

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

Image

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

Image

修復損毀的 SQLite DB 資料庫

Image

解決 ValueError: If using all scalar values, you must pass an index

Image

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

Image

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

Image