边缘检测算法4.-教你动手实现kirsch和robinson算子
还有很多 边缘检测算子,在OpenCV中没有实现代码。
所以,我们得掌握看懂算法,然后扩展 算法得能力。
比如,我已知的一些 边缘检测核心:
Kirsch 8方向算子
Robinson 8方向算子
这个时候,需要我们自己去实现这个算子。
这些算子的具体介绍,其实就是 用 8个核,进行8个方向卷积,然后选取 最大值做响应。
比如 实现 kirsch 算子
KLIB_DECL void edge_kirsch_all_direction(const Mat& grayImg, Mat& edgeImg, double scale = 1, double delta = 0) { edgeImg.create(grayImg.size(), CV_16S); edgeImg.setTo(0); ushort* pDst = (ushort*)edgeImg.data; uchar* pSrc = grayImg.data; int w = grayImg.cols; int h = grayImg.rows; vector<int> vals(8); for(int i = 1; i< h - 1; ++i) for (int j = 1; j < w - 1; ++j) { uchar v1 = pSrc[(i - 1)*w + j - 1]; uchar v2 = pSrc[(i - 1)*w + j]; uchar v3 = pSrc[(i - 1)*w + j + 1]; uchar v4 = pSrc[ i*w + j - 1]; uchar v6 = pSrc[ i*w + j + 1]; uchar v7 = pSrc[(i + 1)*w + j - 1]; uchar v8 = pSrc[(i + 1)*w + j]; uchar v9 = pSrc[(i + 1)*w + j + 1]; vals[0] = 5 * (v1 + v2 + v3) - 3 * (v4 + v6 + v7 + v8 + v9); vals[1] = 5 * (v6 + v2 + v3) - 3 * (v4 + v1 + v7 + v8 + v9); vals[2] = 5 * (v6 + v9 + v3) - 3 * (v4 + v1 + v7 + v8 + v2); vals[3] = 5 * (v6 + v9 + v8) - 3 * (v4 + v1 + v7 + v3 + v2); vals[4] = 5 * (v7 + v9 + v8) - 3 * (v4 + v1 + v6 + v3 + v2); vals[5] = 5 * (v7 + v4 + v8) - 3 * (v9 + v1 + v6 + v3 + v2); vals[6] = 5 * (v7 + v4 + v1) - 3 * (v9 + v8 + v6 + v3 + v2); vals[7] = 5 * (v2 + v4 + v1) - 3 * (v9 + v8 + v6 + v3 + v7); int maxV = *(std::max_element(vals.begin(), vals.end())); pDst[i*w + j] = scale * maxV + delta; }}
调用的方法:
调用 Kirsch算子
同理 实现 Robinson 算子:
KLIB_DECL void edge_robinson_all_direction(const Mat& grayImg, Mat& edgeImg, double scale = 1, double delta = 0){ edgeImg.create(grayImg.size(), CV_16S); edgeImg.setTo(0); ushort* pDst = (ushort*)edgeImg.data; uchar* pSrc = grayImg.data; int w = grayImg.cols; int h = grayImg.rows; vector<int> vals(8); for (int i = 1; i < h - 1; ++i) for (int j = 1; j < w - 1; ++j) { uchar v1 = pSrc[(i - 1)*w + j - 1]; uchar v2 = pSrc[(i - 1)*w + j]; uchar v3 = pSrc[(i - 1)*w + j + 1]; uchar v4 = pSrc[i*w + j - 1]; uchar v6 = pSrc[i*w + j + 1]; uchar v7 = pSrc[(i + 1)*w + j - 1]; uchar v8 = pSrc[(i + 1)*w + j]; uchar v9 = pSrc[(i + 1)*w + j + 1]; vals[0] = 1 * (v1 + v3) + 2 * (v2 - v8) - 1 * (v7 + v9); vals[1] = 1 * (v2 + v6) + 2 * (v3 - v7) - 1 * (v4 + v8); vals[2] = 1 * (v3 + v9) + 2 * (v6 - v4) - 1 * (v1 + v7); vals[3] = 1 * (v6 + v8) + 2 * (v9 - v1) - 1 * (v2 + v4); vals[4] = 1 * (v7 + v9) + 2 * (v8 - v2) - 1 * (v1 + v3); vals[5] = 1 * (v4 + v8) + 2 * (v7 - v3) - 1 * (v2 + v6); vals[6] = 1 * (v1 + v7) + 2 * (v4 - v6) - 1 * (v3 + v9); vals[7] = 1 * (v2 + v4) + 2 * (v1 - v9) - 1 * (v8 + v6); int maxV = *(std::max_element(vals.begin(), vals.end())); pDst[i*w + j] = scale * maxV + delta; }}
调用的方法类似。
然后编译为一个 插件,加载到平台测试:
Krisch cast模式
Krisch abs模式
Krish nono模式
测试 Robinson算子,效果类似:
Robinson 算子 响应弱一些
这就是 其他人的博客里面 提到的 Kirsch 算子和 Robinson算子。
对比知道:
Laplace 边缘响应最弱
Sobel 边缘响应稍强
Robinson 边缘响应更强
Kirsch 边缘响应最强
希望大家学会了OpenCV之外的 边缘检测算子。
赞 (0)