各向异性的概念
各向异性(anisotropy)是指材料在各个方向的力学和物理性能呈现差异的特征。晶体的各向异性即沿晶格的不同方向,原子排列的周期性和疏密程度不尽相同,由此导致晶体在不同方向的物理化学特性也不同,这就是晶体的各向异性。亦称“非均匀性”. 物体的全部或部分物理、化学等性质随方向的不同而各自表现出一定的差异的特性。即在不同的方向所测得的性能数值不同。对图像来说各向异性就是在每个像素点周围四个方向上梯度变化都不一样,滤波的时候我们要考虑图像的各向异性对图像的影响,而各向同性显然是说各个方向的值都一样,常见的图像均值或者高斯均值滤波可以看成是各向同性滤波。
各向异性滤波
是将图像看成物理学的力场或者热流场,图像像素总是向跟他的值相异不是很大的地方流动或者运动,这样那些差异大的地方(边缘)就得以保留,所以本质上各向异性滤波是图像边缘保留滤波器(EPF)。它在各个方向的扩散可以表示如下公式:
导热系数相关的k,取值越大越平滑,越不易保留边缘;lambda同样也是取值越大越平滑。
#include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/opencv.hpp> #include <iostream> #include <vector> using namespace cv; using namespace std; float k = 15; float lambda = 0.25; int N = 20; void anisotropy_demo(Mat &image, Mat &result); int main(int argc, char *argv[]) { cv::Mat src = cv::imread("tong.jpg"); if(src.empty()) { cout << "could not load image..." << endl; return -1; } namedWindow( "input image", CV_WINDOW_AUTOSIZE ); imshow("input image", src); vector<Mat> mv; vector<Mat> results; split(src, mv); for (int i = 0; i < mv.size(); i++) { Mat m = Mat::zeros(src.size(), CV_32FC1); mv[i].convertTo(m, CV_32FC1); results.push_back(m); } int w = src.cols; int h = src.rows; Mat cpy = Mat::zeros(src.size(), CV_32FC1); for (int i = 0; i < N; i++) { for ( int n = 0; n < results.size(); n++) { anisotropy_demo(results[n], cpy); cpy.copyTo(results[n]); } } Mat output; for (int i = 0; i < mv.size(); i++) { normalize(results[i], results[i], 0, 255, NORM_MINMAX); results[i].convertTo(mv[i], CV_8UC1); } Mat dst; merge(mv, dst); imshow("result", dst); imwrite("yang_result.png", dst); waitKey(0); return 0; } void anisotropy_demo(Mat &image, Mat &result) { int width = image.cols; int height = image.rows; //four neighborhood gradient float n = 0, s = 0, e = 0, w = 0; float nc = 0, sc = 0, ec = 0, wc = 0; float k2 = k * k; for (int row = 1; row < height - 1; row++) { for (int col = 1; col < width - 1; col++) { n = image.at<float>(row - 1, col) - image.at<float>(row, col); s = image.at<float>(row + 1, col) - image.at<float>(row, col); e = image.at<float>(row, col - 1) - image.at<float>(row, col); w = image.at<float>(row, col + 1) - image.at<float>(row, col); nc = exp(-n*n / k2); sc = exp(-s*s / k2); ec = exp(-e*e / k2); wc = exp(-w*w / k2); result.at<float>(row, col) = image.at<float>(row, col) + lambda * (n*nc + s*sc + e*ec + w*wc); } } }