OpenCV 距离变换的笔记
生活随笔
收集整理的這篇文章主要介紹了
OpenCV 距离变换的笔记
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
目前正在學(xué)習(xí)<圖像處理,分析與機(jī)器視覺>里面有提到距離變換計算,以此筆記記錄生活。?
距離變換的定義?:計算圖像中像素點(diǎn)到最近零像素點(diǎn)的距離,也就是零像素點(diǎn)的最短距離。
- 1
- 2
- 3
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
我們的type是CV_32FC1,所以每個像素是4個字節(jié),為了能保存圖像,在進(jìn)行歸一化處理之后,需要用距離*255,然后作為該像素點(diǎn)的亮度值。
distanceTransform是opencv的提供的計算距離轉(zhuǎn)換的函數(shù),個人覺得要主要是dest的輸出,存的是距離的矩陣,所以這里我們創(chuàng)建的時候type是CV_32FC1。?
其中距離的計算方法:?
為了減少計算了量,我們采用的是一種倒角模版的算法,只需要對圖像進(jìn)行兩次掃描玖可以實(shí)現(xiàn)距離變換,該方法被稱為chamfer倒角距離變換,該模版如下:?
網(wǎng)絡(luò)代碼參考:
//距離變換的掃描實(shí)現(xiàn) #include <iostream> #include <opencv2\core\core.hpp> #include <opencv2\highgui\highgui.hpp> #include <opencv2\imgproc\imgproc.hpp> using namespace cv; using namespace std; //計算歐氏距離的函數(shù) float calcEuclideanDiatance(int x1, int y1, int x2, int y2) { return sqrt(float((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))); } //計算棋盤距離的函數(shù) int calcChessboardDistance(int x1, int y1, int x2, int y2) { return cv::max(abs(x1 - x2), (y1 - y2)); } //計算麥哈頓距離(街區(qū)距離) int calcBlockDistance(int x1, int y1, int x2, int y2) { return abs(x1 - x2) + abs(y1 - y2); } //距離變換函數(shù)的實(shí)現(xiàn) void distanceTrans(Mat &srcImage, Mat &dstImage) { CV_Assert(srcImage.data != nullptr); //CV_Assert()若括號中的表達(dá)式值為false,則返回一個錯誤信息。 //定義灰度圖像的二值圖像 Mat grayImage, binaryImage; //將原圖像轉(zhuǎn)換為灰度圖像 cvtColor(srcImage, grayImage, CV_BGR2GRAY); //將灰度圖像轉(zhuǎn)換為二值圖像 threshold(grayImage, binaryImage, 100, 255, THRESH_BINARY); imshow("二值化圖像", binaryImage); int rows = binaryImage.rows; int cols = binaryImage.cols; uchar *pDataOne; uchar *pDataTwo; float disPara = 0; float fDisMIn = 0; //第一遍遍歷圖像,使用左模板更新像素值 for (int i = 1; i < rows - 1; i++) { //圖像的行指針的獲取 pDataOne = binaryImage.ptr<uchar>(i); for (int j = 1; j < cols; j++) { //分別計算左模板掩碼的相關(guān)距離 //PL PL //PL P //PL pDataTwo = binaryImage.ptr<uchar>(i - 1); disPara = calcEuclideanDiatance(i, j, i - 1, j - 1); fDisMIn = cv::min((float)pDataOne[j], disPara + pDataTwo[j - 1]); disPara = calcEuclideanDiatance(i, j, i - 1, j); fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j]); pDataTwo = binaryImage.ptr<uchar>(i); disPara = calcEuclideanDiatance(i, j, i, j - 1); fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j-1]); pDataTwo = binaryImage.ptr<uchar>(i+1); disPara = calcEuclideanDiatance(i, j, i+1,j-1); fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j - 1]); pDataOne[j] = (uchar)cvRound(fDisMIn); } } //第二遍遍歷圖像,使用右模板更新像素值 for (int i = rows - 2; i > 0; i--) { pDataOne = binaryImage.ptr<uchar>(i); for (int j = cols - 1; j >= 0; j--) { //分別計算右模板掩碼的相關(guān)距離 //pR pR //pR p //pR pDataTwo = binaryImage.ptr<uchar>(i + 1); disPara = calcEuclideanDiatance(i, j, i + 1, j); fDisMIn = cv::min((float)pDataOne[j], disPara + pDataTwo[j]); disPara = calcEuclideanDiatance(i, j, i + 1, j + 1); fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j+1]); pDataTwo = binaryImage.ptr<uchar>(i); disPara = calcEuclideanDiatance(i, j, i, j +1); fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j + 1]); pDataTwo = binaryImage.ptr<uchar>(i - 1); disPara = calcEuclideanDiatance(i, j, i - 1, j + 1); fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j + 1]); pDataOne[j] = (uchar)cvRound(fDisMIn); } } dstImage = binaryImage.clone(); } //主函數(shù) int main() { Mat srcImage = imread("2345.jpg"); if (!srcImage.data) { cout << "讀入圖片錯誤!" << endl; system("pause"); return -1; } Mat dstImage; distanceTrans(srcImage, dstImage); imshow("距離變換圖像", dstImage); waitKey(); return 0; } 與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的OpenCV 距离变换的笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CNN for Semantic Seg
- 下一篇: 二值图像的距离变换研究