一個極其簡單的圖像識別小程序

前段時間寫了個簡單的圖像識別程序,主要實現了對螺絲、螺母、硬幣和小扳手的識別。現在來簡單地做一個總結。
該程序的主要思路如下:

  1. 將采集到的RGB圖像轉化為灰度圖像
  2. 應用OSTU算法對圖像進行閾值分割并二值化
  3. 使用區域生長算法將各個待檢測目標提取出來
  4. 根據目標的形狀特征對目標進行分類

接下來對各個步驟做一些分析。

圖像預處理

圖像預處理是本實驗的第一步。其目的是將目標物體的圖像從背景中分割出來,這樣我們才方便做后續的識別。
首先將RGB圖像轉換為灰度圖像,是為了去除冗余的色彩信息,同時也簡化了計算。
在灰度圖像的基礎上在進行圖像分割。我們這里采取比較簡單又較為常用的閾值分割法來進行圖像分割。這里使用的OSTU算法是一種具有一定自適應性的閾值分割法,網絡上有許多對這個算法的詳細說明,我們這里不加贅述。

區域生長

雖然通過閾值分割我們已經得到了所有目標物體的像素分布,但是僅憑這個我們無法對每個物體的特征進行分析。因為我們并不知道單獨的每個目標的像素分布。所以我們要尋找一種方法,將每個物體的像素信息分布保存起來。這種方法就是區域生長算法。區域生長的核心思想就是從種子點開始向相鄰的點逐點搜索,從而將整個連通區域提取出來。
以下是該部分的源代碼:

//返回生長區域點的個數
int CMainFrame::RegionGrow(Point init, vector<Point> &result, int **mark)
{
    stack<Point> seedStack;
    Point seed(0,0);
    int n = 0;  //區域內點的數量

    mark[init.y][init.x] = 1;
    seedStack.push(init);
    Point tmp(seed.x,seed.y);
    while (1)
    {
        seed = seedStack.top();
        seedStack.pop();
        if(seed.x < m_pBmpInfo->bmiHeader.biWidth-1)
        {
            tmp.x = seed.x + 1;
            tmp.y = seed.y;
            if(!mark[tmp.y][tmp.x] && gImageBuffer[tmp.y*m_pBmpInfo->bmiHeader.biWidth+tmp.x] == 0)
            {
                seedStack.push(tmp);
                result.push_back(tmp);
                mark[tmp.y][tmp.x] = 1;    //將已被生長的點標記為1
                n++;    //區域點的數量加一
            }
        }
        if(seed.y < m_pBmpInfo->bmiHeader.biHeight-1)
        {
            tmp.x = seed.x;
            tmp.y = seed.y + 1;
            if(!mark[tmp.y][tmp.x] && gImageBuffer[tmp.y*m_pBmpInfo->bmiHeader.biWidth+tmp.x] == 0)
            {
                seedStack.push(tmp);
                result.push_back(tmp);
                mark[tmp.y][tmp.x] = 1; 
                n++;
            }
        }
        if(seed.x > 0)
        {
            tmp.x = seed.x - 1;
            tmp.y = seed.y;
            if(!mark[tmp.y][tmp.x] && gImageBuffer[tmp.y*m_pBmpInfo->bmiHeader.biWidth+tmp.x] == 0)
            {
                seedStack.push(tmp);
                result.push_back(tmp);
                mark[tmp.y][tmp.x] = 1; 
                n++;
            }
        }
        if(seed.y > 0)
        {
            tmp.x = seed.x;
            tmp.y = seed.y - 1;
            if(!mark[tmp.y][tmp.x] && gImageBuffer[tmp.y*m_pBmpInfo->bmiHeader.biWidth+tmp.x] == 0)
            {
                seedStack.push(tmp);
                result.push_back(tmp);
                mark[tmp.y][tmp.x] = 1;  
                n++;
            }
        }

        if(seedStack.empty())
            break;
    }
    return n;
}

目標識別

在得到了各個目標的像素信息后,如何對目標進行分類呢?由于我們要識別的物體僅限于螺絲、螺母、硬幣這樣形狀簡單的物體,我們只需通過一些簡單的特征就能將他們區分開來。

  • 螺母的中心為空,而螺絲、小扳手均為實心
  • 小扳手為L形的細桿,其長軸和短軸之比遠大于螺絲
  • 硬幣為圓形

憑借以上三條規則,就足以將螺絲、螺母、硬幣和扳手區分開來了。

小結

本文主要是整理思路,細節的地方并未涉及,希望能對讀者有一些幫助~
P.S. 此文在我新搭建的獨立博客亦有發表:
http://cyanair.me/2016/03/31/a-simple-objection-recognition-program/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 不同圖像灰度不同,邊界處一般會有明顯的邊緣,利用此特征可以分割圖像。需要說明的是:邊緣和物體間的邊界并不等同,邊緣...
    大川無敵閱讀 13,952評論 0 29
  • 1、閾值分割 1.1 簡介 圖像閾值化分割是一種傳統的最常用的圖像分割方法,因其實現簡單、計算量小、性能較穩定而成...
    木夜溯閱讀 22,661評論 9 15
  • 去年Alaph GO擊敗李世石九段,社會掀起了機器學習技術討論的熱潮,不過很多人對機器學習并不了解,本文借由手寫數...
    Sunhaorong閱讀 2,593評論 0 4
  • 圖像識別意義: 圖像是指物體的描述信息,數字圖像是一個物體的數字表示。視覺是人類感知外部世界的最重要手段,據統計,...
    木木口丁閱讀 8,491評論 1 21
  • 姓名:朱睿琦 學號:15180288015 【嵌牛導讀】:隨著數字圖像處理技術和人工智能的不斷發展,圖像識別技術無...
    BLASSREITER閱讀 3,984評論 0 0