图像细化
?在我們進(jìn)行圖像處理的時(shí)候,有可能需要對(duì)圖像進(jìn)行細(xì)化,提取出圖像的骨架信息,進(jìn)行更加有效的分析。
???? 圖像細(xì)化(Image Thinning),一般指二值圖像的骨架化(Image Skeletonization) 的一種操作運(yùn)算。
???? 所謂的細(xì)化就是經(jīng)過一層層的剝離,從原來的圖中去掉一些點(diǎn),但仍要保持原來的形狀,直到得到圖像的骨架。骨架,可以理解為圖象的中軸。
???? 好的細(xì)化算法一定要滿足:- 收斂性;
- 保證細(xì)化后細(xì)線的連通性;
- 保持原圖的基本形狀;
- 減少筆畫相交處的畸變;
- 細(xì)化結(jié)果是原圖像的中心線;
- 細(xì)化的快速性和迭代次數(shù)少;
????這里,我們對(duì)“Zhang并行快速細(xì)化算法”進(jìn)行了實(shí)現(xiàn)(注意,該算法為并行算法,而我們?cè)趯?shí)現(xiàn)過程中并沒有并行化處理,所以,效率并沒有達(dá)到最好)。
????參考資料
- 細(xì)化算法
- 論文 A fast parallel algorithm for thinning digital patterns [cpp]?view plaincopy
- #include?<opencv2/opencv.hpp>??
- #include?<opencv2/core/core.hpp>??
- #include?<iostream>??
- #include?<vector>??
- ??
- ??
- /**?
- ?*?@brief?對(duì)輸入圖像進(jìn)行細(xì)化?
- ?*?@param?src為輸入圖像,用cvThreshold函數(shù)處理過的8位灰度圖像格式,元素中只有0與1,1代表有元素,0代表為空白?
- ?*?@param?maxIterations限制迭代次數(shù),如果不進(jìn)行限制,默認(rèn)為-1,代表不限制迭代次數(shù),直到獲得最終結(jié)果?
- ?*?@return?為對(duì)src細(xì)化后的輸出圖像,格式與src格式相同,元素中只有0與1,1代表有元素,0代表為空白?
- ?*/??
- cv::Mat?thinImage(const?cv::Mat?&?src,?const?int?maxIterations?=?-1)??
- {??
- ????assert(src.type()?==?CV_8UC1);??
- ????cv::Mat?dst;??
- ????int?width??=?src.cols;??
- ????int?height?=?src.rows;??
- ????src.copyTo(dst);??
- ????int?count?=?0;??//記錄迭代次數(shù)??
- ????while?(true)??
- ????{??
- ????????count++;??
- ????????if?(maxIterations?!=?-1?&&?count?>?maxIterations)?//限制次數(shù)并且迭代次數(shù)到達(dá)??
- ????????????break;??
- ????????std::vector<uchar?*>?mFlag;?//用于標(biāo)記需要?jiǎng)h除的點(diǎn)??
- ????????//對(duì)點(diǎn)標(biāo)記??
- ????????for?(int?i?=?0;?i?<?height?;++i)??
- ????????{??
- ????????????uchar?*?p?=?dst.ptr<uchar>(i);??
- ????????????for?(int?j?=?0;?j?<?width;?++j)??
- ????????????{??
- ????????????????//如果滿足四個(gè)條件,進(jìn)行標(biāo)記??
- ????????????????//??p9?p2?p3??
- ????????????????//??p8?p1?p4??
- ????????????????//??p7?p6?p5??
- ????????????????uchar?p1?=?p[j];??
- ????????????????if?(p1?!=?1)?continue;??
- ????????????????uchar?p4?=?(j?==?width?-?1)???0?:?*(p?+?j?+?1);??
- ????????????????uchar?p8?=?(j?==?0)???0?:?*(p?+?j?-?1);??
- ????????????????uchar?p2?=?(i?==?0)???0?:?*(p?-?dst.step?+?j);??
- ????????????????uchar?p3?=?(i?==?0?||?j?==?width?-?1)???0?:?*(p?-?dst.step?+?j?+?1);??
- ????????????????uchar?p9?=?(i?==?0?||?j?==?0)???0?:?*(p?-?dst.step?+?j?-?1);??
- ????????????????uchar?p6?=?(i?==?height?-?1)???0?:?*(p?+?dst.step?+?j);??
- ????????????????uchar?p5?=?(i?==?height?-?1?||?j?==?width?-?1)???0?:?*(p?+?dst.step?+?j?+?1);??
- ????????????????uchar?p7?=?(i?==?height?-?1?||?j?==?0)???0?:?*(p?+?dst.step?+?j?-?1);??
- ????????????????if?((p2?+?p3?+?p4?+?p5?+?p6?+?p7?+?p8?+?p9)?>=?2?&&?(p2?+?p3?+?p4?+?p5?+?p6?+?p7?+?p8?+?p9)?<=?6)??
- ????????????????{??
- ????????????????????int?ap?=?0;??
- ????????????????????if?(p2?==?0?&&?p3?==?1)?++ap;??
- ????????????????????if?(p3?==?0?&&?p4?==?1)?++ap;??
- ????????????????????if?(p4?==?0?&&?p5?==?1)?++ap;??
- ????????????????????if?(p5?==?0?&&?p6?==?1)?++ap;??
- ????????????????????if?(p6?==?0?&&?p7?==?1)?++ap;??
- ????????????????????if?(p7?==?0?&&?p8?==?1)?++ap;??
- ????????????????????if?(p8?==?0?&&?p9?==?1)?++ap;??
- ????????????????????if?(p9?==?0?&&?p2?==?1)?++ap;??
- ??
- ????????????????????if?(ap?==?1?&&?p2?*?p4?*?p6?==?0?&&?p4?*?p6?*?p8?==?0)??
- ????????????????????{??
- ????????????????????????//標(biāo)記??
- ????????????????????????mFlag.push_back(p+j);??
- ????????????????????}??
- ????????????????}??
- ????????????}??
- ????????}??
- ??
- ????????//將標(biāo)記的點(diǎn)刪除??
- ????????for?(std::vector<uchar?*>::iterator?i?=?mFlag.begin();?i?!=?mFlag.end();?++i)??
- ????????{??
- ????????????**i?=?0;??
- ????????}??
- ??
- ????????//直到?jīng)]有點(diǎn)滿足,算法結(jié)束??
- ????????if?(mFlag.empty())??
- ????????{??
- ????????????break;??
- ????????}??
- ????????else??
- ????????{??
- ????????????mFlag.clear();//將mFlag清空??
- ????????}??
- ??
- ????????//對(duì)點(diǎn)標(biāo)記??
- ????????for?(int?i?=?0;?i?<?height;?++i)??
- ????????{??
- ????????????uchar?*?p?=?dst.ptr<uchar>(i);??
- ????????????for?(int?j?=?0;?j?<?width;?++j)??
- ????????????{??
- ????????????????//如果滿足四個(gè)條件,進(jìn)行標(biāo)記??
- ????????????????//??p9?p2?p3??
- ????????????????//??p8?p1?p4??
- ????????????????//??p7?p6?p5??
- ????????????????uchar?p1?=?p[j];??
- ????????????????if?(p1?!=?1)?continue;??
- ????????????????uchar?p4?=?(j?==?width?-?1)???0?:?*(p?+?j?+?1);??
- ????????????????uchar?p8?=?(j?==?0)???0?:?*(p?+?j?-?1);??
- ????????????????uchar?p2?=?(i?==?0)???0?:?*(p?-?dst.step?+?j);??
- ????????????????uchar?p3?=?(i?==?0?||?j?==?width?-?1)???0?:?*(p?-?dst.step?+?j?+?1);??
- ????????????????uchar?p9?=?(i?==?0?||?j?==?0)???0?:?*(p?-?dst.step?+?j?-?1);??
- ????????????????uchar?p6?=?(i?==?height?-?1)???0?:?*(p?+?dst.step?+?j);??
- ????????????????uchar?p5?=?(i?==?height?-?1?||?j?==?width?-?1)???0?:?*(p?+?dst.step?+?j?+?1);??
- ????????????????uchar?p7?=?(i?==?height?-?1?||?j?==?0)???0?:?*(p?+?dst.step?+?j?-?1);??
- ??
- ????????????????if?((p2?+?p3?+?p4?+?p5?+?p6?+?p7?+?p8?+?p9)?>=?2?&&?(p2?+?p3?+?p4?+?p5?+?p6?+?p7?+?p8?+?p9)?<=?6)??
- ????????????????{??
- ????????????????????int?ap?=?0;??
- ????????????????????if?(p2?==?0?&&?p3?==?1)?++ap;??
- ????????????????????if?(p3?==?0?&&?p4?==?1)?++ap;??
- ????????????????????if?(p4?==?0?&&?p5?==?1)?++ap;??
- ????????????????????if?(p5?==?0?&&?p6?==?1)?++ap;??
- ????????????????????if?(p6?==?0?&&?p7?==?1)?++ap;??
- ????????????????????if?(p7?==?0?&&?p8?==?1)?++ap;??
- ????????????????????if?(p8?==?0?&&?p9?==?1)?++ap;??
- ????????????????????if?(p9?==?0?&&?p2?==?1)?++ap;??
- ??
- ????????????????????if?(ap?==?1?&&?p2?*?p4?*?p8?==?0?&&?p2?*?p6?*?p8?==?0)??
- ????????????????????{??
- ????????????????????????//標(biāo)記??
- ????????????????????????mFlag.push_back(p+j);??
- ????????????????????}??
- ????????????????}??
- ????????????}??
- ????????}??
- ??
- ????????//將標(biāo)記的點(diǎn)刪除??
- ????????for?(std::vector<uchar?*>::iterator?i?=?mFlag.begin();?i?!=?mFlag.end();?++i)??
- ????????{??
- ????????????**i?=?0;??
- ????????}??
- ??
- ????????//直到?jīng)]有點(diǎn)滿足,算法結(jié)束??
- ????????if?(mFlag.empty())??
- ????????{??
- ????????????break;??
- ????????}??
- ????????else??
- ????????{??
- ????????????mFlag.clear();//將mFlag清空??
- ????????}??
- ????}??
- ????return?dst;??
- }??
- ??
- ??
- int?main(int?argc,?char*argv[])??
- {??
- ????//獲取圖像??
- ????if?(argc?!=?2)??
- ????{??
- ????????std::cout?<<?"參數(shù)個(gè)數(shù)錯(cuò)誤!"?<<?std::endl;??
- ????????return?-1;??
- ????}??
- ????cv::Mat?src?=?cv::imread(argv[1],?cv::IMREAD_GRAYSCALE);??
- ????if?(src.empty())??
- ????{??
- ????????std::cout?<<?"讀取文件失敗!"?<<?std::endl;??
- ????????return?-1;??
- ????}??
- ??
- ????//將原圖像轉(zhuǎn)換為二值圖像??
- ????cv::threshold(src,?src,?128,?1,?cv::THRESH_BINARY);??
- ????//圖像細(xì)化??
- ????cv::Mat?dst?=?thinImage(src);??
- ????//顯示圖像??
- ????dst?=?dst?*?255;??
- ????cv::namedWindow("src1",?CV_WINDOW_AUTOSIZE);??
- ????cv::namedWindow("dst1",?CV_WINDOW_AUTOSIZE);??
- ????cv::imshow("src1",?src);??
- ????cv::imshow("dst1",?dst);??
- ????cv::waitKey(0);??
- }??
-
運(yùn)行效果
1原圖像
2.運(yùn)行效果
總結(jié)
- 上一篇: 力场变换
- 下一篇: SSIM与PSNR的计算方式