运动模糊时,模糊后图片某点的值应该与原图沿运动角度方向前面的点有关,并且越近邻影响越大,即权值越大。所以除了确定卷积核之外,还确定了锚点(anchor)
右下角60度移动,距离50
代码实现:
#include "opencv2/opencv.hpp"
typedef cv::Mat Mat;
void genaratePsf(Mat &psf, cv::Point &anchor, double len,double angle);
int main(int argc, char * argv[])
{
if( argc != 2){
std::cerr << "Usage: " << argv[0] << "
return -1;
}
Mat srcImage = cv::imread(argv[1], cv::IMREAD_COLOR);
if( srcImage.empty() )
return -1;
imshow( "src_img", srcImage );
double len = 50;
double angle = -60;
Mat ker, dst;
cv::Point anchor;
genaratePsf(ker, anchor, len, angle);
/// 使用滤波器
filter2D(srcImage, dst, -1 , ker, anchor );
// cv::normalize(dst_plane[0], dst_plane[0], 1, 0, CV_MINMAX);
imshow( "dest", dst );
cv::waitKey(0);
return 1;
}
void genaratePsf(Mat &psf, cv::Point &anchor, double len,double angle)
{
//生成卷积核和锚点
double half=len/2;
double alpha = (angle-floor(angle/ 180) *180) /180* CV_PI;
double cosalpha = cos(alpha);
double sinalpha = sin(alpha);
int xsign;
if (cosalpha < 0){
xsign = -1;
} else {
if (angle == 90) {
xsign = 0;
} else {
xsign = 1;
}
}
int psfwdt = 1;
//模糊核大小
int sx = (int)fabs(half*cosalpha + psfwdt*xsign - len*FLT_EPSILON );
int sy = (int)fabs(half*sinalpha + psfwdt - len*FLT_EPSILON);
cv::Mat_
//psf1是左上角的权值较大,越往右下角权值越小的核。
//这时运动像是从右下角到左上角移动
for (int i = 0; i < sy; i++){
double* pvalue = psf1.ptr
for (int j = 0; j < sx; j++){
pvalue[j] = i*fabs(cosalpha) - j*sinalpha;
double rad = sqrt(i*i + j*j);
if (rad >= half && fabs(pvalue[j]) <= psfwdt){
double temp = half - fabs((j + pvalue[j] * sinalpha) / cosalpha);
pvalue[j] = sqrt(pvalue[j] * pvalue[j] + temp*temp);
}
pvalue[j] = psfwdt + FLT_EPSILON - fabs(pvalue[j]);
if (pvalue[j] < 0){
pvalue[j] = 0;
}
}
}
// 运动方向是往左上运动,锚点在(0,0)
anchor.x = 0;
anchor.y = 0;
// 运动方向是往右上角移动,锚点一个在右上角
// 同时,左右翻转核函数,使得越靠近锚点,权值越大
if (angle<90 && angle>0){
flip(psf1, psf1, 1);
anchor.x =psf1.cols-1;
anchor.y = 0;
}else if( angle>-90 && angle<0){ //同理:往右下角移动
flip(psf1, psf1, -1);
anchor.x =psf1.cols-1;
anchor.y = psf1.rows-1;
}else if( angle<-90){ //同理:往左下角移动
flip(psf1, psf1, 0);
anchor.x = 0;
anchor.y = psf1.rows-1;
}
/*保持图像总能量不变,归一化矩阵*/
double sum = 0;
for (int i = 0; i < sy; i++) {
for (int j = 0; j < sx; j++){
sum+= psf1[i][j];
}
}
psf = psf1 / sum;
}
参考:
https://www.cnblogs.com/wyh1993/p/7118559.html
https://blog.csdn.net/lei_yin/article/details/27318955