C++自定义非极大值抑制(Canny边缘检测,亚像素方法)
生活随笔
收集整理的這篇文章主要介紹了
C++自定义非极大值抑制(Canny边缘检测,亚像素方法)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Mat subPixleRestrainNoMax2(Mat img)//具有更清楚的物理解釋,線插分法
{Mat oriImage = img;Mat newImage_x = Mat(img.size(), CV_32SC1, Scalar(0));Mat newImage_y = Mat(img.size(), CV_32SC1, Scalar(0));Mat newImage_xy = Mat(img.size(), CV_32SC2, Scalar(0));//包含梯度信息Mat maxImage = Mat(img.size(), CV_8UC1, Scalar(0));//非極大值抑制后的圖像//對x方向求Sobel算子梯度int width = img.cols;int hight = img.rows;int max_sobel_x = 0;//記錄x方向最大梯度絕對值for (int i = 1; i < hight - 1; i++)for (int j = 1; j < width - 1; j++){int nav_value = oriImage.at<uchar>(i + 1, j - 1) + 2 * oriImage.at<uchar>(i, j - 1)+ oriImage.at<uchar>(i - 1, j - 1);int pos_value = oriImage.at<uchar>(i + 1, j + 1) + 2 * oriImage.at<uchar>(i, j + 1)+ oriImage.at<uchar>(i - 1, j + 1);int sobel_result = ((pos_value - nav_value) / 6);//相減除以6//int sobel_result = (pos_value + 6 * 255 - nav_value) / (6 * 2); //把像素加255 再除以 2if (max_sobel_x < abs(sobel_result))max_sobel_x = abs(sobel_result);//找到梯度最大值newImage_x.at<int>(i, j) = sobel_result;}float mulit_x = (float)(255 / max_sobel_x);//按倍數(shù)擴(kuò)大像素值,使像素差距放大for (int i = 1; i < hight - 1; i++)for (int j = 1; j < width - 1; j++){newImage_x.at<int>(i, j) = (int)(newImage_x.at<int>(i, j) * mulit_x);}//對y方向求Sobel梯度int max_sobel_y = 0;//記錄最大y方向梯度絕對值for (int i = 1; i < hight - 1; i++)for (int j = 1; j < width - 1; j++){int nav_value = oriImage.at<uchar>(i - 1, j - 1) + 2 * oriImage.at<uchar>(i - 1, j)+ oriImage.at<uchar>(i - 1, j + 1);int pos_value = oriImage.at<uchar>(i + 1, j - 1) + 2 * oriImage.at<uchar>(i + 1, j)+ oriImage.at<uchar>(i + 1, j + 1);int sobel_result = ((pos_value - nav_value) / 6);//相減除以6//int sobel_result = (pos_value + 6 * 255 - nav_value) / (6 * 2); //把像素加255 再除以 2if (abs(sobel_result) > max_sobel_y)max_sobel_y = abs((sobel_result));//找到梯度最大值newImage_y.at<int>(i, j) = sobel_result;}float mulit_y = (float)(255 / max_sobel_y);//按倍數(shù)擴(kuò)大像素值,使像素差距放大for (int i = 1; i < hight - 1; i++)for (int j = 1; j < width - 1; j++){newImage_y.at<int>(i, j) = (int)(newImage_y.at<int>(i, j) * mulit_y);}//把每個像素的梯度值和梯度方向存入到newImage_xy中float direct_value;float pi = 3.141;for (int i = 1; i < hight - 1; i++)for (int j = 1; j < width - 1; j++){newImage_xy.at<Vec2i>(i, j)[0] = (abs(newImage_x.at<int>(i, j)) + abs(newImage_y.at<int>(i, j))) / 2;}//非極大值抑制處理,使用亞像素線插分方法for (int i = 1; i < hight - 1; i++)for (int j = 1; j < width - 1; j++){//case1具體原理見筆記if ((((newImage_x.at<int>(i, j) > 0) && (newImage_y.at<int>(i, j) < 0))|| ((newImage_x.at<int>(i, j) < 0) && (newImage_y.at<int>(i, j) > 0)))&& (abs(newImage_x.at<int>(i, j)) > abs(newImage_y.at<int>(i, j)))){float weight = abs((float)newImage_y.at<int>(i, j) / (float)newImage_x.at<int>(i, j));//計算沿梯度向前一個像素的插分值int front = weight * newImage_xy.at<Vec2i>(i - 1, j + 1)[0] + (1 - weight) * newImage_xy.at<Vec2i>(i, j + 1)[0];//計算沿梯度向后的一個插分值int back = weight * newImage_xy.at<Vec2i>(i + 1, j - 1)[0] + (1 - weight) * newImage_xy.at<Vec2i>(i, j - 1)[0];//判斷是否是最大值if ((newImage_xy.at<Vec2i>(i, j)[0] > front) && (newImage_xy.at<Vec2i>(i, j)[0] < back))maxImage.at<uchar>(i, j) = newImage_xy.at<Vec2i>(i, j)[0];}//case2if ((((newImage_x.at<int>(i, j) > 0) && (newImage_y.at<int>(i, j) < 0))|| ((newImage_x.at<int>(i, j) < 0) && (newImage_y.at<int>(i, j) > 0)))&& (abs(newImage_x.at<int>(i, j)) < abs(newImage_y.at<int>(i, j)))){float weight = abs((float)newImage_x.at<int>(i, j) / (float)newImage_y.at<int>(i, j));//計算沿梯度向前一個像素的插分值int front = weight * newImage_xy.at<Vec2i>(i - 1, j + 1)[0] + (1 - weight) * newImage_xy.at<Vec2i>(i-1, j )[0];//計算沿梯度向后的一個插分值int back = weight * newImage_xy.at<Vec2i>(i + 1, j - 1)[0] + (1 - weight) * newImage_xy.at<Vec2i>(i+1, j )[0];//判斷是否是最大值if ((newImage_xy.at<Vec2i>(i, j)[0] > front) && (newImage_xy.at<Vec2i>(i, j)[0] < back))maxImage.at<uchar>(i, j) = newImage_xy.at<Vec2i>(i, j)[0];}//case3if ((((newImage_x.at<int>(i, j) > 0) && (newImage_y.at<int>(i, j) > 0))|| ((newImage_x.at<int>(i, j) < 0) && (newImage_y.at<int>(i, j) < 0)))&& (abs(newImage_x.at<int>(i, j)) > abs(newImage_y.at<int>(i, j)))){float weight = abs((float)newImage_y.at<int>(i, j) / (float)newImage_x.at<int>(i, j));//計算沿梯度向前一個像素的插分值int front = weight * newImage_xy.at<Vec2i>(i +1, j + 1)[0] + (1 - weight) * newImage_xy.at<Vec2i>(i, j+1)[0];//計算沿梯度向后的一個插分值int back = weight * newImage_xy.at<Vec2i>(i - 1, j - 1)[0] + (1 - weight) * newImage_xy.at<Vec2i>(i, j-1)[0];//判斷是否是最大值if ((newImage_xy.at<Vec2i>(i, j)[0] > front) && (newImage_xy.at<Vec2i>(i, j)[0] < back))maxImage.at<uchar>(i, j) = newImage_xy.at<Vec2i>(i, j)[0];}//case4if ((((newImage_x.at<int>(i, j) > 0) && (newImage_y.at<int>(i, j) > 0))|| ((newImage_x.at<int>(i, j) < 0) && (newImage_y.at<int>(i, j) < 0)))&& (abs(newImage_x.at<int>(i, j)) < abs(newImage_y.at<int>(i, j)))){float weight = abs((float)newImage_x.at<int>(i, j) / (float)newImage_y.at<int>(i, j));//計算沿梯度向前一個像素的插分值int front = weight * newImage_xy.at<Vec2i>(i + 1, j + 1)[0] + (1 - weight) * newImage_xy.at<Vec2i>(i+1, j)[0];//計算沿梯度向后的一個插分值int back = weight * newImage_xy.at<Vec2i>(i - 1, j - 1)[0] + (1 - weight) * newImage_xy.at<Vec2i>(i-1, j)[0];//判斷是否是最大值if ((newImage_xy.at<Vec2i>(i, j)[0] > front) && (newImage_xy.at<Vec2i>(i, j)[0] < back))maxImage.at<uchar>(i, j) = newImage_xy.at<Vec2i>(i, j)[0];}//當(dāng)x方向梯度為0時else if ((newImage_x.at<int>(i, j) == 0) && (newImage_y.at<int>(i, j) != 0)){if ((newImage_xy.at<Vec2i>(i, j)[0] > newImage_xy.at<Vec2i>(i - 1, j)[0])&& (newImage_xy.at<Vec2i>(i, j)[0] < newImage_xy.at<Vec2i>(i + 1, j)[0]))maxImage.at<uchar>(i, j) = newImage_xy.at<Vec2i>(i, j)[0];}//當(dāng)y方向梯度為0時else if ((newImage_y.at<int>(i, j) == 0) && (newImage_x.at<int>(i, j) != 0)){if ((newImage_xy.at<Vec2i>(i, j)[0] > newImage_xy.at<Vec2i>(i, j - 1)[0])&& (newImage_xy.at<Vec2i>(i, j)[0] < newImage_xy.at<Vec2i>(i, j + 1)[0]))maxImage.at<uchar>(i, j) = newImage_xy.at<Vec2i>(i, j)[0];}}return maxImage;
}
總結(jié)
以上是生活随笔為你收集整理的C++自定义非极大值抑制(Canny边缘检测,亚像素方法)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++自定义sobel求梯度
- 下一篇: OpenGL画图设备上下文与MFC设备上