OpenCV實(shí)現(xiàn)失焦模糊圖像恢復(fù)
點(diǎn)擊上方“小白學(xué)視覺(jué)”,選擇加"星標(biāo)"或“置頂”
重磅干貨,第一時(shí)間送達(dá)
圖像退化模型在頻率域的表示如下:

其中
S表示退化(模糊)圖像頻譜
H表示角點(diǎn)擴(kuò)散功能(PSF)的頻譜響應(yīng)
U 表示原真實(shí)圖像的頻譜
N表示疊加的頻譜噪聲
?
圓形的PSF因?yàn)橹挥幸粋€(gè)半徑參數(shù)R,是一個(gè)非常好的失焦畸變近似,所以算法采用圓形的PSF。

模糊恢復(fù),模板恢復(fù)本質(zhì)是獲得一個(gè)對(duì)原圖的近似估算圖像,在頻率域可以表示如下:

其中SNR表示信噪比,因此可以基于維納濾波恢復(fù)離焦圖像,實(shí)現(xiàn)圖像反模糊。這個(gè)過(guò)程最終重要的兩個(gè)參數(shù),分別是半徑R與信噪比SNR,在反模糊圖像時(shí)候,要先嘗試調(diào)整R,然后再嘗試調(diào)整SNR。
計(jì)算PSF的代碼如下:
void?calcPSF(Mat&?outputImg,?Size?filterSize,?int?R)
{
????Mat?h(filterSize,?CV_32F,?Scalar(0));
????Point?point(filterSize.width?/?2,?filterSize.height?/?2);
????circle(h,?point,?R,?255,?-1,?8);
????Scalar?summa?=?sum(h);
????outputImg?=?h?/?summa[0];
}生成維納濾波的代碼如下:
void?calcWnrFilter(const?Mat&?input_h_PSF,?Mat&?output_G,?double?nsr)
{
????Mat?h_PSF_shifted;
????fftshift(input_h_PSF,?h_PSF_shifted);
????Mat?planes[2]?=?{?Mat_<float>(h_PSF_shifted.clone()),?Mat::zeros(h_PSF_shifted.size(),?CV_32F)?};
????Mat?complexI;
????merge(planes,?2,?complexI);
????dft(complexI,?complexI);
????split(complexI,?planes);
????Mat?denom;
????pow(abs(planes[0]),?2,?denom);
????denom?+=?nsr;
????divide(planes[0],?denom,?output_G);
}實(shí)現(xiàn)反模糊的代碼如下:
void?filter2DFreq(const?Mat&?inputImg,?Mat&?outputImg,?const?Mat&?H)
{
????Mat?planes[2]?=?{?Mat_<float>(inputImg.clone()),?Mat::zeros(inputImg.size(),?CV_32F)?};
????Mat?complexI;
????merge(planes,?2,?complexI);
????dft(complexI,?complexI,?DFT_SCALE);
????Mat?planesH[2]?=?{?Mat_<float>(H.clone()),?Mat::zeros(H.size(),?CV_32F)?};
????Mat?complexH;
????merge(planesH,?2,?complexH);
????Mat?complexIH;
????mulSpectrums(complexI,?complexH,?complexIH,?0);
????idft(complexIH,?complexIH);
????split(complexIH,?planes);
????outputImg?=?planes[0];
}調(diào)用步驟:?
void?adjust_filter(int,?void*)?{
????Mat?imgOut;
????//?偶數(shù)處理,神級(jí)操作
????Rect?roi?=?Rect(0,?0,?src.cols?&?-2,?src.rows?&?-2);
????printf("roi.x=%d,?y=%d,?w=%d,?h=%d",?roi.x,?roi.y,?roi.width,?roi.height);
????//?生成PSF與維納濾波器
????Mat?Hw,?h;
????calcPSF(h,?roi.size(),?adjust_r);
????calcWnrFilter(h,?Hw,?1.0?/?double(snr));
????//?反模糊
????filter2DFreq(src(roi),?imgOut,?Hw);
????//?歸一化顯示
????imgOut.convertTo(imgOut,?CV_8U);
????normalize(imgOut,?imgOut,?0,?255,?NORM_MINMAX);
????imwrite("D:/deblur_result.jpg",?imgOut);
????imshow("deblur_result",?imgOut);
}圖像傅里葉變換
void?fftshift(const?Mat&?inputImg,?Mat&?outputImg)
{
????outputImg?=?inputImg.clone();
????int?cx?=?outputImg.cols?/?2;
????int?cy?=?outputImg.rows?/?2;
????Mat?q0(outputImg,?Rect(0,?0,?cx,?cy));
????Mat?q1(outputImg,?Rect(cx,?0,?cx,?cy));
????Mat?q2(outputImg,?Rect(0,?cy,?cx,?cy));
????Mat?q3(outputImg,?Rect(cx,?cy,?cx,?cy));
????Mat?tmp;
????q0.copyTo(tmp);
????q3.copyTo(q0);
????tmp.copyTo(q3);
????q1.copyTo(tmp);
????q2.copyTo(q1);
????tmp.copyTo(q2);
}原圖: 肉眼無(wú)法辨識(shí)

R=10, SNR=40時(shí)候的運(yùn)行效果:基本肉眼可以辨識(shí)!

交流群
歡迎加入公眾號(hào)讀者群一起和同行交流,目前有SLAM、三維視覺(jué)、傳感器、自動(dòng)駕駛、計(jì)算攝影、檢測(cè)、分割、識(shí)別、醫(yī)學(xué)影像、GAN、算法競(jìng)賽等微信群(以后會(huì)逐漸細(xì)分),請(qǐng)掃描下面微信號(hào)加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三?+?上海交大?+?視覺(jué)SLAM“。請(qǐng)按照格式備注,否則不予通過(guò)。添加成功后會(huì)根據(jù)研究方向邀請(qǐng)進(jìn)入相關(guān)微信群。請(qǐng)勿在群內(nèi)發(fā)送廣告,否則會(huì)請(qǐng)出群,謝謝理解~

