?? imagerestoreext.cpp
字號(hào):
/*
* 運(yùn)動(dòng)模糊恢復(fù)類
* 馮昊
* Sep.25th,2007 整理
* 說明:
* 本類包含三種方法的運(yùn)動(dòng)模糊恢復(fù)功能,維納濾波、
* 逆濾波和投影迭代法。這些方法都是根據(jù)先驗(yàn)信息進(jìn)行
* 運(yùn)動(dòng)模糊恢復(fù)的。因此首先要獲得點(diǎn)擴(kuò)散函數(shù),本類提
* 供了計(jì)算點(diǎn)擴(kuò)散函數(shù)的方法。
* 本類需要配合ComFourierTransform傅里葉變換類
* 使用。即需要?jiǎng)討B(tài)運(yùn)行庫ComFourierTransform.dll
* VC++ 6.0編譯
*/
#include "stdafx.h"
#include "ImageRestore.h"
#include <math.h>
#include "FourierTransform.h"
#define PI 3.1415926
#pragma comment(lib,"FourierTransformLib8")
ImageRestore::ImageRestore(void) :
mask(NULL),mask_width(0),mask_height(0)
{
}
ImageRestore::~ImageRestore(void)
{
if(mask != NULL)
free(mask);
}
/*
* MapRestoreByteVar
* 功能:投影法運(yùn)動(dòng)模糊恢復(fù)
* 參數(shù):
* imgBufIn 輸入圖像數(shù)據(jù)
* imgWidth 圖像寬度
* imgHeight 圖像高度
* pxWidth 像素寬度
* cycleCount 迭代次數(shù)
* 具體原理的理解 由卷積的步驟 H * F整體把握理解
*/
void ImageRestore::MapRestoreByteVar(unsigned char *imgBufIn ,int imgWidth, int imgHeight,int pxWidth ,int cycleCount)
{
if(imgBufIn == NULL || mask == NULL)
return;
BYTE* out;
int terminal_count = 0;
out = (BYTE*)malloc(sizeof(BYTE) * imgWidth * imgHeight * pxWidth);
memcpy(out,imgBufIn,sizeof(BYTE)*imgWidth*imgHeight* pxWidth);
double *stencil=(double*)malloc(sizeof(double)*mask_height*mask_width);
for(int p=0 ;p < cycleCount ;p++){
for(int h = 0;h< imgHeight ;h++){
for(int w =0; w < imgWidth ; w=w+1){
if(w < (float)mask_width/2 || w> (float)(imgWidth - (float)mask_width/2))
continue;
if(h < (float)mask_height/2 || h> (float)(imgHeight - (float)mask_height/2))
continue;
int acce=0;
for(int j = h - mask_height/2; j< h + mask_height/2 +mask_height%2?1:0 ;j++){
for(int i = w - mask_width/2; i< w + mask_width/2 + mask_width%2?1:0 ; i++){
stencil[acce] = imgBufIn[j * imgWidth * pxWidth + i * pxWidth];
acce++;
}
}
double tempa = 0;
double temph = 0;
for(int i=0;i<mask_height*mask_width;i++){
tempa += (stencil[i] * mask[i]);
temph += mask[i] * mask[i];
}
double blured_pixel = out[h * imgWidth * pxWidth + w * pxWidth + 15 * pxWidth];
tempa = (tempa - blured_pixel) / temph;
if(((int)tempa)==0){
terminal_count ++;
}
for(int i=0;i<mask_height*mask_width;i++){
stencil[i] = stencil[i] - tempa * mask[i];
}
acce=0;
for(int j = h - mask_height/2; j< h + mask_height/2 +mask_height%2?1:0 ;j++){
for(int i = w - mask_width/2; i< w + mask_width/2 + mask_width%2?1:0 ; i++){
if(stencil[acce] >255) stencil[acce]=255;
if(stencil[acce] <0) stencil[acce]=0;
for(int pxByteCount = 0;pxByteCount < pxWidth ; pxByteCount ++)
imgBufIn[j * imgWidth *pxWidth + i * pxWidth + pxByteCount] = stencil[acce];
acce++;
}
}
}
}
}
double max=-10000,min=10000;
for (int i = 0; i < imgHeight; i++)
{
for (int j = 0; j < imgWidth * pxWidth; j++)
{
if(imgBufIn[i * imgWidth * pxWidth + j] < min) min = imgBufIn[i * imgWidth * pxWidth + j];
if(imgBufIn[i * imgWidth * pxWidth + j] > max) max = imgBufIn[i * imgWidth * pxWidth + j];
}
}
for (int i = 0; i < imgHeight; i++)
{
for (int j = 0; j < imgWidth * pxWidth; j++)
{
*(imgBufIn + i * imgWidth * pxWidth + j) = (unsigned char)(((imgBufIn[i * imgWidth * pxWidth + j]-min)/(max-min))*255);
}
}
free(stencil);
free(out);
}
/*
* WienerRestoreByteVar
* 功能:維納濾波運(yùn)動(dòng)模糊恢復(fù)
* 參數(shù)說明:
* imgBufIn 輸入圖像數(shù)據(jù)(8位灰度)
* imgWidth 圖像寬度
* imgHeight 圖像高度
* pxWidth 圖像位寬( 設(shè)置為1)
* k 參數(shù)(0- 1)
*/
bool ImageRestore::WienerRestoreByteVar(unsigned char *imgBufIn,int imgWidth,int imgHeight,int pxWidth,double k)
{
if(imgBufIn == NULL || mask == NULL)
return false;
BYTE* Y = imgBufIn;
int w=1,h=1;
//計(jì)算大于等于原始圖像大小的2的冪
while(w < imgWidth)
{
w *= 2;
}
while(h < imgHeight)
{
h *= 2;
}
complex<double> *freqData= new complex<double>[w * h * pxWidth];
FourierTransform ftm;
//對(duì)圖像進(jìn)行傅里葉變換
ftm.ImageFourierEx(imgBufIn, imgWidth, imgHeight, freqData,1);
//模板數(shù)據(jù)
complex<double> *timeMaskData;
complex<double> *freqMaskData;
timeMaskData = new complex<double>[w * h * pxWidth];
freqMaskData = new complex<double>[w * h * pxWidth];
int i = 0,j = 0;
int acce = 0;
//填充模板,調(diào)整模板為2的整數(shù)次冪,多余的部分填充0
for(i = 0; i < h; i++){
for(j = 0; j < w * pxWidth; j= j + 1){
if(i < mask_height && j < mask_width * pxWidth){
double Value = *((double*)mask + acce);
acce ++ ;
timeMaskData[w * i * pxWidth + j] = complex<double>(Value, 0.0f);
}
else{
timeMaskData[w * i * pxWidth + j] = complex<double>(0.0f, 0.0f);
}
}
}
//對(duì)模板進(jìn)行傅里葉變換
if (ftm.Fourier(timeMaskData, w, h, freqMaskData,pxWidth) == FALSE){
return false;
}
double conf=0;
//維納濾波
for(i = 0; i < h; i++){
for(j = 0; j < w * pxWidth ; j = j + 1){
complex<double> mask_item =freqMaskData[w * i * pxWidth + j];
conf=(abs(mask_item) * abs(mask_item)) / ((abs(mask_item) * abs(mask_item)) + k);
freqData[w * i * pxWidth + j] = (freqData[w * i * pxWidth + j] * complex<double>(conf,conf) ) / mask_item;
}
}
//對(duì)濾波結(jié)果進(jìn)行逆變換
if (ftm.IFourier(
Y, imgWidth, imgHeight, freqData,1) == FALSE){
return false;
}
delete[] freqMaskData;
delete[] timeMaskData;
delete[] freqData;
return true;
}
/**************************************************************************
*函數(shù)名
* InverseFilterByte()
*
*參數(shù)名
* unsigned char *imgBufIn -輸入圖像緩沖
* int imgWidth -圖像寬度
* int imgHeight -圖像高度
* int pxWidth -像素寬度(8位灰度圖像請(qǐng)將該參數(shù)設(shè)置為 1)
*
*返回值
* 無
*
*說明:該函數(shù)將輸入圖像 imgBufIn作為輸入圖像,并按照計(jì)算好的點(diǎn)擴(kuò)散函數(shù)進(jìn)行
逆濾波恢復(fù)。注意在調(diào)用該函數(shù)前,請(qǐng)先使用GeneratePSF產(chǎn)生點(diǎn)擴(kuò)散函數(shù)。
***************************************************************************/
bool ImageRestore::InverseFilterByte(unsigned char *imgBufIn,int imgWidth,int imgHeight,int pxWidth)
{
if(imgBufIn == NULL || mask == NULL)
return false;
BYTE* Y = imgBufIn;
int w=1,h=1;
// 計(jì)算大于等于原始圖像大小的2的冪
while(w < imgWidth)
{
w *= 2;
}
while(h < imgHeight)
{
h *= 2;
}
complex<double> *freqData= new complex<double>[w * h * pxWidth];
FourierTransform ftm;
// 對(duì)圖像進(jìn)行傅里葉變換,freqData為輸出結(jié)果
ftm.ImageFourier(imgBufIn, imgWidth, imgHeight, freqData,pxWidth);
// 申請(qǐng)點(diǎn)擴(kuò)散函數(shù)空域和頻域空間
complex<double> *timeMaskData = new complex<double>[w * h * pxWidth];
complex<double> *freqMaskData = new complex<double>[w * h * pxWidth];
int i = 0, j = 0;
// 填充點(diǎn)擴(kuò)散函數(shù)空間,調(diào)整模板為2的整數(shù)次冪,多余的部分填充0
int acce = 0;
for(i = 0; i < h; i++){
for(j = 0; j < w * pxWidth; j= j + 1){
if(i < mask_height && j < mask_width * pxWidth){
double Value = *((double*)mask + acce);
acce ++ ;
timeMaskData[w * i * pxWidth + j] = complex<double>(Value, 0.0f);
}
else{
timeMaskData[w * i * pxWidth + j] = complex<double>(0.0f, 0.0f);
}
}
}
// 對(duì)模板進(jìn)行傅里葉變換
if (ftm.Fourier(timeMaskData, w, h, freqMaskData,pxWidth) == FALSE)
return false;
double conf=0;
// 逆濾波
for(i = 0; i < h; i++){
for(j = 0; j < w * pxWidth ; j = j + 1){
complex<double> mask=freqMaskData[w * i * pxWidth + j];
if(mask.real() * mask.real() + mask.imag() * mask.imag()!= 0)
freqData[w * i * pxWidth + j] = freqData[w * i * pxWidth + j] / mask;
else
freqData[w * i * pxWidth + j] = 0;
}
}
// 對(duì)濾波結(jié)果進(jìn)行逆變換
if (ftm.IFourier(Y, imgWidth, imgHeight, freqData, pxWidth) == FALSE)
return false;
// 釋放緩沖區(qū)
delete[] timeMaskData;
delete[] freqMaskData;
delete[] freqData;
return true;
}
/*
* GeneratePSF
* 功能:產(chǎn)生點(diǎn)擴(kuò)散函數(shù)矩陣
* length 模糊長度
* angle 模糊角度
* 說明:采用先驗(yàn)信息的恢復(fù)方法是首先根據(jù)模糊信息產(chǎn)生電擴(kuò)散函數(shù)
* 再使用逆濾波等恢復(fù)程序進(jìn)行運(yùn)動(dòng)模糊恢復(fù)。
*/
void ImageRestore::GeneratePSF(double length, double angle)
{
float half = length;
double phi = (double)(angle/180)*PI; //轉(zhuǎn)化為弧度
double cosphi = cos(phi);
double sinphi = sin(phi);
int xsign = cosphi?(cosphi>0?1:-1):0;
if(cosphi<0)
xsign = -1;
//線寬度
int linewdt = 1;
//計(jì)算一半圖像的長和寬
int sx = (int)(half * cosphi * xsign + linewdt + 0.5);
int sy = (int)(half * sinphi + linewdt + 0.5);
mask_width = sx;
mask_height = sy;
//距離計(jì)算空間
//分配相應(yīng)的內(nèi)存空間
if(mask != NULL)
free(mask);
mask = (double*)malloc(sizeof(double)*sx*sy);
double **dist2line_matrix = (double**)malloc(sizeof(double*)*sy); //行組織
int i = 0,j = 0;
//指針指向每一行的首地址
if(xsign == 1){
for(i = 0; i< sy ; i++){
dist2line_matrix[i] = mask + i * sx;
}
}
else{
for(i = sy - 1; i >= 0 ; i--){
dist2line_matrix[i] = mask + (sy - i - 1) * sx;
}
}
//弧度定義變量
double rad = 0;
//--考慮到:對(duì)于90到180之間,只是在x方向的反向,因此在控制邏輯上只需控制x遍歷順序即可
int x_position = 0,x_start = 0;
x_start = 0;
//定義從一個(gè)點(diǎn)到旋轉(zhuǎn)線的最短距離
//距離垂直于旋轉(zhuǎn)線
for(i = 0; i < sy ; i ++){
x_position = x_start;
for(j = 0; j < sx; j++){
//線距離
dist2line_matrix[i][j] = i * abs(cosphi) - j * sinphi;
//半徑距離
rad = sqrt((double)(i * i + j * j));
if(rad >= half && abs(dist2line_matrix[i][j]) <= linewdt){
int x2lastpix = half - abs((x_position + dist2line_matrix[i][j] * sinphi) / cosphi);
dist2line_matrix[i][j] = sqrt(dist2line_matrix[i][j] * dist2line_matrix[i][j] + x2lastpix * x2lastpix);
}
dist2line_matrix[i][j] = linewdt - abs(dist2line_matrix[i][j]);
if(dist2line_matrix[i][j] < 0) dist2line_matrix[i][j]=0;
x_position ++;
}
}
double sum = 0;
for(i = 0; i < sy ; i ++){
for(j = 0; j < sx; j++){
sum += dist2line_matrix[i][j];
}
}
//對(duì)矩陣數(shù)據(jù)進(jìn)行歸一化處理
for(i = 0; i < sy ; i ++){
for(j = 0; j < sx; j++){
dist2line_matrix[i][j] /= sum;
}
}
//刪除二維矩陣
delete[] dist2line_matrix;
return;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -