1. 程式人生 > >opencv 骨架提取/影象細化

opencv 骨架提取/影象細化

骨架提取/影象細,相信很多人都聽說過,影象細化原理 可以參看這篇博文。由於opencv沒有現成的函式,因此,看懂了原理之後,自己寫了一個函數出來。

現在分享一下程式碼。

現在越來越覺得C部落格的好處,可以看到好多前輩分享的程式碼,大大縮短了自己掌握影象處理技巧的時間。

這種樂於分享的氛圍,必將極大的促進技術的進步和革新。

本程式碼配置條件  opencv2.4.9+vs2013  應該其他版本的vs和opencv也可以跑起來

輸入的srcimage為二值化後的影象,其中白色為要細化的特徵

void chao_thinimage(Mat &srcimage)//單通道、二值化後的影象
{
	vector<Point> deletelist1;
	int Zhangmude[9];
	int nl = srcimage.rows;
	int nc = srcimage.cols;
	while (true)
	{
		for (int j = 1; j<(nl - 1); j++)
		{
			uchar* data_last = srcimage.ptr<uchar>(j - 1);
			uchar* data = srcimage.ptr<uchar>(j);
			uchar* data_next = srcimage.ptr<uchar>(j + 1);
			for (int i = 1; i<(nc - 1); i++)
			{
				if (data[i] == 255)
				{
					Zhangmude[0] = 1;
					if (data_last[i] == 255) Zhangmude[1] = 1;
					else  Zhangmude[1] = 0;
					if (data_last[i + 1] == 255) Zhangmude[2] = 1;
					else  Zhangmude[2] = 0;
					if (data[i + 1] == 255) Zhangmude[3] = 1;
					else  Zhangmude[3] = 0;
					if (data_next[i + 1] == 255) Zhangmude[4] = 1;
					else  Zhangmude[4] = 0;
					if (data_next[i] == 255) Zhangmude[5] = 1;
					else  Zhangmude[5] = 0;
					if (data_next[i - 1] == 255) Zhangmude[6] = 1;
					else  Zhangmude[6] = 0;
					if (data[i - 1] == 255) Zhangmude[7] = 1;
					else  Zhangmude[7] = 0;
					if (data_last[i - 1] == 255) Zhangmude[8] = 1;
					else  Zhangmude[8] = 0;
					int whitepointtotal = 0;
					for (int k = 1; k < 9; k++)
					{
						whitepointtotal = whitepointtotal + Zhangmude[k];
					}
					if ((whitepointtotal >= 2) && (whitepointtotal <= 6))
					{
						int ap = 0;
						if ((Zhangmude[1] == 0) && (Zhangmude[2] == 1)) ap++;
						if ((Zhangmude[2] == 0) && (Zhangmude[3] == 1)) ap++;
						if ((Zhangmude[3] == 0) && (Zhangmude[4] == 1)) ap++;
						if ((Zhangmude[4] == 0) && (Zhangmude[5] == 1)) ap++;
						if ((Zhangmude[5] == 0) && (Zhangmude[6] == 1)) ap++;
						if ((Zhangmude[6] == 0) && (Zhangmude[7] == 1)) ap++;
						if ((Zhangmude[7] == 0) && (Zhangmude[8] == 1)) ap++;
						if ((Zhangmude[8] == 0) && (Zhangmude[1] == 1)) ap++;
						if (ap == 1)
						{
							if ((Zhangmude[1] * Zhangmude[7] * Zhangmude[5] == 0) && (Zhangmude[3] * Zhangmude[5] * Zhangmude[7] == 0))
							{
								deletelist1.push_back(Point(i, j));
							}
						}
					}
				}
			}
		}
		if (deletelist1.size() == 0) break;
		for (size_t i = 0; i < deletelist1.size(); i++)
		{
			Point tem;
			tem = deletelist1[i];
			uchar* data = srcimage.ptr<uchar>(tem.y);
			data[tem.x] = 0;
		}
		deletelist1.clear();

		for (int j = 1; j<(nl - 1); j++)
		{
			uchar* data_last = srcimage.ptr<uchar>(j - 1);
			uchar* data = srcimage.ptr<uchar>(j);
			uchar* data_next = srcimage.ptr<uchar>(j + 1);
			for (int i = 1; i<(nc - 1); i++)
			{
				if (data[i] == 255)
				{
					Zhangmude[0] = 1;
					if (data_last[i] == 255) Zhangmude[1] = 1;
					else  Zhangmude[1] = 0;
					if (data_last[i + 1] == 255) Zhangmude[2] = 1;
					else  Zhangmude[2] = 0;
					if (data[i + 1] == 255) Zhangmude[3] = 1;
					else  Zhangmude[3] = 0;
					if (data_next[i + 1] == 255) Zhangmude[4] = 1;
					else  Zhangmude[4] = 0;
					if (data_next[i] == 255) Zhangmude[5] = 1;
					else  Zhangmude[5] = 0;
					if (data_next[i - 1] == 255) Zhangmude[6] = 1;
					else  Zhangmude[6] = 0;
					if (data[i - 1] == 255) Zhangmude[7] = 1;
					else  Zhangmude[7] = 0;
					if (data_last[i - 1] == 255) Zhangmude[8] = 1;
					else  Zhangmude[8] = 0;
					int whitepointtotal = 0;
					for (int k = 1; k < 9; k++)
					{
						whitepointtotal = whitepointtotal + Zhangmude[k];
					}
					if ((whitepointtotal >= 2) && (whitepointtotal <= 6))
					{
						int ap = 0;
						if ((Zhangmude[1] == 0) && (Zhangmude[2] == 1)) ap++;
						if ((Zhangmude[2] == 0) && (Zhangmude[3] == 1)) ap++;
						if ((Zhangmude[3] == 0) && (Zhangmude[4] == 1)) ap++;
						if ((Zhangmude[4] == 0) && (Zhangmude[5] == 1)) ap++;
						if ((Zhangmude[5] == 0) && (Zhangmude[6] == 1)) ap++;
						if ((Zhangmude[6] == 0) && (Zhangmude[7] == 1)) ap++;
						if ((Zhangmude[7] == 0) && (Zhangmude[8] == 1)) ap++;
						if ((Zhangmude[8] == 0) && (Zhangmude[1] == 1)) ap++;
						if (ap == 1)
						{
							if ((Zhangmude[1] * Zhangmude[3] * Zhangmude[5] == 0) && (Zhangmude[3] * Zhangmude[1] * Zhangmude[7] == 0))
							{
								deletelist1.push_back(Point(i, j));
							}
						}
					}
				}
			}
		}
		if (deletelist1.size() == 0) break;
		for (size_t i = 0; i < deletelist1.size(); i++)
		{
			Point tem;
			tem = deletelist1[i];
			uchar* data = srcimage.ptr<uchar>(tem.y);
			data[tem.x] = 0;
		}
		deletelist1.clear();
	}

效果如下圖所示


相關推薦

opencv 骨架提取/影象細化

骨架提取/影象細,相信很多人都聽說過,影象細化原理 可以參看這篇博文。由於opencv沒有現成的函式,因此,看懂了原理之後,自己寫了一個函數出來。 現在分享一下程式碼。 現在越來越覺得C部落格的好處,可以看到好多前輩分享的程式碼,大大縮短了自己掌握影象處理技巧的時間。 這種

Opencv提取影象中的輪廓及中心點

// contourStudy.cpp : 定義控制檯應用程式的入口點。 //本文所提取的輪廓具有的特徵: 只有一個無孔洞的內連通 #include "stdafx.h" #include <opencv2/opencv.hpp> #include <iostream> #includ

opencv】經典的細化提取骨架理論及原始碼

本章我們學習一下Hilditch演算法的基本原理,從網上找資料的時候,竟然發現兩個有很大差別的演算法描述,而且都叫Hilditch演算法。不知道那一個才是正宗的,兩個演算法實現的效果接近,第一種演算法更好一些。 第一種演算法描述參考paper和程式碼: Linear

OpenCV函式cvFindContous提取影象輪廓

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

OpenCV影象金字塔提取影象輪廓

程式碼位置:13-ImagePyramid.py import cv2 import numpy as np img = cv2.imread('./res/aero3.jpg') imgDown1 = cv2.pyrDown(img) imgDown2 = cv2.pyrDown(

opencv提取影象中的顏色直方圖(RGB、HSV)

本篇部落格主要介紹利用opencv工具提取一幅影象中的顏色直方圖特徵。所謂顏色直方圖,指的是一幅影象中的顏色分佈,與影象中的特定的物體無關,只是用來表示人的眼睛觀察到的影象中的顏色分佈情況,例如說,一幅圖中紅色佔了多少比例,綠色佔了多少比例等。 我們知道,計算機色彩顯示器採

影象扭正確。利用OpenCV檢測影象中的長方形畫布或紙張並提取影象內容

也就是在一張照片裡,已知有個長方形的物體,但是經過了透視投影,已經不再是規則的長方形,那麼如何提取這個圖形裡的內容呢?這是個很常見的場景,比如在博物館裡看到一幅很喜歡的畫,用手機找了下來,可是回家一看歪歪斜斜,腦補原畫內容又覺得不對,那麼就需要演算法輔助來從原圖裡提取原來的內容了。不妨把應用的場景分為以下

OpenCV特徵提取影象檢索實現(附程式碼)

翻譯 | AI科技大本營(ID:rgznai100) 參與 | 張蔚敏 審校 | reason_W “拍立淘”“一鍵識花”“街景匹配”……不知道大家在使用這些神奇的功能的時候,有沒有好奇過它們背後的技術原理?其實這些技術都離不開最基本的影象檢索技術。本篇文

OpenCV實現二值影象細化的演算法

        細化演算法通常和骨骼化、骨架化演算法是相同的意思,也就是thin演算法或者skeleton演算法。雖然很多影象處理的教材上不是這麼寫的,具體原因可以看這篇論文,Louisa Lam, Seong-Whan Lee, Ching Y. Suen,“Thinni

提取影象骨架(Skeleton)演算法

影象的骨架似乎沒有嚴格的數學定義,可認為是影象細化(Thinning)的產物(中軸可以看作一種骨架,其有嚴格的數學定義)。目前已經有許多細化演算法,這些演算法得到的骨架可能略有差異。本文實現了Khalid Sheed 的 K3M演算法。該演算法屬於迭代腐蝕邊界的一類演算法,

OpenCV學習筆記_影象細化

#include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> using name

OpenCV入門:影象邊緣提取

本文將介紹如何利用OpenCV進行邊緣提取,原始碼如下: // // main.cpp // Edge_Detection // // Created by 黃露 on 16/3/21. // Copyright © 2016年 huanglu_thu13. All

利用MSER演算法提取影象區域(車牌區域)的OpenCV程式碼~

我的部落格中前面已經寫了兩種方法來實現車牌區域的提取了,大家可以參看下面這篇博文: MSER的全稱是maximally stable extremal region,翻譯過來為“最穩定極值區域”,extremal 意思的極值的意思。 下面說下這種方法的大致思路,如果要

python3.6 windows安裝python-contrib-opencv安裝及提取影象的SIFT特徵

#前言 最近幾天在做水果分類的一個Project,看到有人說SIFT特徵比較有用。由於Project的其他部分都是在python中完成的,所以想在python中提取影象的SIFT特徵。上網上一查立馬就發現了很多程式碼,原來python的opencv庫就封裝後SI

兩種影象骨架提取演算法的研究(2)實現程式碼

1 K3M #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/objdetect/objdetect.hpp> #include <opencv2/highgui/hig

二值影象骨架提取

  本文介紹的二值影象細化演算法是來自 T.Y. Zhang and C.Y. Suen 1984 年發表的論文 “A fast parallel algorithm for thinning digital patterns” 中所介紹的演算法。 演算法介紹

基於輪廓提取影象文字2---OpenCV-Python教程(11、輪廓檢測)

https://blog.csdn.net/sunny2038/article/details/12889059相比C++而言,Python適合做原型。本系列的文章介紹如何在Python中用OpenCV圖形庫,以及與C++呼叫相應OpenCV函式的不同之處。這篇文章介紹在Py

基於Mat變換的骨架提取Java

and ati ++ index turn 證明 public phi ont 針對一副二值圖像,區域內的點只有背景點(白點,0值)和前景點(黑點,1值)。對於給定區域的像素點逐次應用兩個基本步驟,以提取骨架: step1,如果一個像素點滿足下列4個條件,那麽將它標記為要刪

使用OpenCV對一系列影象生成視訊avi

直接上程式碼了,過程很簡單,注意路徑,環境:opencv3,macos //功能:將連續圖片合成視訊AVI //注意:檢查路徑是否存在空格,否則影響結果 //注意:根據檔名設定迴圈,何時開始迴圈 #include<opencv2/opencv.hpp> #include<

opencv 兩幅影象直接相減

關鍵函式cvAbsDiff() ,程式碼如下: #include "cv.h" #include "highgui.h" #include "cxcore.h" int main(int argc,char** argv) {cvNamedWindow("a",0);