还有很多 边缘检测算子,在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之外的 边缘检测算子。 |
|
来自: taotao_2016 > 《计算机》