记录一下图像骨架提取算法,转载至 两种图像骨架提取算法的研究(1)原理部分
基于OpenCV的实现代码如下,代码部分参考 opencv骨架提取/图像细化
void thinImage(Mat & srcImg) { vector<Point> deleteList; int neighbourhood[9]; int nl = srcImg.rows; int nc = srcImg.cols; bool inOddIterations = true; while (true) { for (int j = 1; j < (nl - 1); j++) { uchar* data_last = srcImg.ptr<uchar>(j - 1); uchar* data = srcImg.ptr<uchar>(j); uchar* data_next = srcImg.ptr<uchar>(j + 1); for (int i = 1; i < (nc - 1); i++) { if (data[i] == 255) { int whitePointCount = 0; neighbourhood[0] = 1; if (data_last[i] == 255) neighbourhood[1] = 1; else neighbourhood[1] = 0; if (data_last[i + 1] == 255) neighbourhood[2] = 1; else neighbourhood[2] = 0; if (data[i + 1] == 255) neighbourhood[3] = 1; else neighbourhood[3] = 0; if (data_next[i + 1] == 255) neighbourhood[4] = 1; else neighbourhood[4] = 0; if (data_next[i] == 255) neighbourhood[5] = 1; else neighbourhood[5] = 0; if (data_next[i - 1] == 255) neighbourhood[6] = 1; else neighbourhood[6] = 0; if (data[i - 1] == 255) neighbourhood[7] = 1; else neighbourhood[7] = 0; if (data_last[i - 1] == 255) neighbourhood[8] = 1; else neighbourhood[8] = 0; for (int k = 1; k < 9; k++) { whitePointCount += neighbourhood[k]; } if ((whitePointCount >= 2) && (whitePointCount <= 6)) { int ap = 0; if ((neighbourhood[1] == 0) && (neighbourhood[2] == 1)) ap++; if ((neighbourhood[2] == 0) && (neighbourhood[3] == 1)) ap++; if ((neighbourhood[3] == 0) && (neighbourhood[4] == 1)) ap++; if ((neighbourhood[4] == 0) && (neighbourhood[5] == 1)) ap++; if ((neighbourhood[5] == 0) && (neighbourhood[6] == 1)) ap++; if ((neighbourhood[6] == 0) && (neighbourhood[7] == 1)) ap++; if ((neighbourhood[7] == 0) && (neighbourhood[8] == 1)) ap++; if ((neighbourhood[8] == 0) && (neighbourhood[1] == 1)) ap++; if (ap == 1) { if (inOddIterations && (neighbourhood[3] * neighbourhood[5] * neighbourhood[7] == 0) && (neighbourhood[1] * neighbourhood[3] * neighbourhood[5] == 0)) { deleteList.push_back(Point(i, j)); } else if (!inOddIterations && (neighbourhood[1] * neighbourhood[5] * neighbourhood[7] == 0) && (neighbourhood[1] * neighbourhood[3] * neighbourhood[7] == 0)) { deleteList.push_back(Point(i, j)); } } } } } } if (deleteList.size() == 0) break; for (size_t i = 0; i < deleteList.size(); i++) { Point tem; tem = deleteList[i]; uchar* data = srcImg.ptr<uchar>(tem.y); data[tem.x] = 0; } deleteList.clear(); inOddIterations = !inOddIterations; } }
原图和细化结果如下: