// ImageProcessView.cpp : implementation of the CImageProcessView class
//
#include "stdafx.h"
#include "ImageProcess.h"
#include "ImageProcessDoc.h"
#include "ImageProcessView.h"
#include "MainFrm.h"
#include "afxole.h"
#include "math.h"
#include "atlimage.h"
#include "CDemoTimer.h"
// 编码表RGB数组
#include "ColorTable.inc" //颜色表
#include "Matrix.h"
#include "LEquations.h"
#include <stack>
#include <queue>
#include <list>
#include <afxtempl.h>
#include <vector>
//using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
const double Pi=3.14159;
const int TWOVALUE_H=0x80;
const int TWOVALUE_L=0x0;
int m_ModelWidth;
int m_ModelHeight;
unsigned char* m_pModelData=NULL;
const int TIMER_AVI=0;
// CImageProcessView
IMPLEMENT_DYNCREATE(CImageProcessView, CScrollView)
BEGIN_MESSAGE_MAP(CImageProcessView, CScrollView)
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
ON_COMMAND(ID_FILE_RE, &CImageProcessView::OnFileReOpen)
ON_UPDATE_COMMAND_UI(ID_FILE_RE, &CImageProcessView::OnUpdateFileReOpen)
ON_COMMAND(ID_EDIT_PASTE, &CImageProcessView::OnEditPaste)
ON_COMMAND(ID_EDIT_COPY, &CImageProcessView::OnEditCopy)
ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, &CImageProcessView::OnUpdateEditCopy)
ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, &CImageProcessView::OnUpdateEditPaste)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_COMMAND(ID_EDIT_CUT, &CImageProcessView::OnEditCut)
ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, &CImageProcessView::OnUpdateEditCut)
ON_COMMAND(ID_VIEW_SELECTAREAMAXIMUM, &CImageProcessView::OnViewSelectareamaximum)
ON_UPDATE_COMMAND_UI(ID_VIEW_SELECTAREAMAXIMUM, &CImageProcessView::OnUpdateViewSelectareamaximum)
ON_COMMAND(ID_VIEW_INFORMATION, &CImageProcessView::OnViewInformation)
ON_UPDATE_COMMAND_UI(ID_VIEW_INFORMATION, &CImageProcessView::OnUpdateViewInformation)
ON_COMMAND(ID_HISTGRAM_GRAY, &CImageProcessView::OnHistgramGray)
ON_UPDATE_COMMAND_UI(ID_HISTGRAM_GRAY, &CImageProcessView::OnUpdateHistgramGray)
ON_COMMAND(ID_HISTGRAM_RGB, &CImageProcessView::OnHistgramRgb)
ON_UPDATE_COMMAND_UI(ID_HISTGRAM_RGB, &CImageProcessView::OnUpdateHistgramRgb)
ON_COMMAND(ID_HISTGRAM_HSI, &CImageProcessView::OnHistgramHsi)
ON_UPDATE_COMMAND_UI(ID_HISTGRAM_HSI, &CImageProcessView::OnUpdateHistgramHsi)
ON_COMMAND(ID_PREPROCESS_GRAY, &CImageProcessView::OnPreprocessGray)
ON_UPDATE_COMMAND_UI(ID_PREPROCESS_GRAY, &CImageProcessView::OnUpdatePreprocessGray)
ON_COMMAND(ID_PREPROCESS_PSDEOCOLORDISPLAY, &CImageProcessView::OnPreprocessPsdeocolordisplay)
ON_UPDATE_COMMAND_UI(ID_PREPROCESS_PSDEOCOLORDISPLAY, &CImageProcessView::OnUpdatePreprocessPsdeocolordisplay)
ON_COMMAND(ID_PREPROCESS_NEGATIVEIMAGE, &CImageProcessView::OnPreprocessNegativeimage)
ON_UPDATE_COMMAND_UI(ID_PREPROCESS_NEGATIVEIMAGE, &CImageProcessView::OnUpdatePreprocessNegativeimage)
ON_COMMAND(ID_HISTGRAM_EQUALIZER, &CImageProcessView::OnHistgramEqualizer)
ON_UPDATE_COMMAND_UI(ID_HISTGRAM_EQUALIZER, &CImageProcessView::OnUpdateHistgramEqualizer)
ON_COMMAND(ID_HISTGRAM_ROBUSTNORMALIZATION, &CImageProcessView::OnHistgramRobustnormalization)
ON_UPDATE_COMMAND_UI(ID_HISTGRAM_ROBUSTNORMALIZATION, &CImageProcessView::OnUpdateHistgramRobustnormalization)
ON_COMMAND(ID_GAMM_BRIGHT, &CImageProcessView::OnGammBright)
ON_UPDATE_COMMAND_UI(ID_GAMM_DARK, &CImageProcessView::OnUpdateGammDark)
ON_COMMAND(ID_GAMM_DARK, &CImageProcessView::OnGammDark)
ON_UPDATE_COMMAND_UI(ID_GAMM_BRIGHT, &CImageProcessView::OnUpdateGammBright)
ON_COMMAND(ID_ADDNOISE_GUASS, &CImageProcessView::OnAddnoiseGuass)
ON_COMMAND(ID_ADDNOISE_SALTPEPPER, &CImageProcessView::OnAddnoiseSaltpepper)
ON_UPDATE_COMMAND_UI(ID_ADDNOISE_GUASS, &CImageProcessView::OnUpdateAddnoiseGuass)
ON_UPDATE_COMMAND_UI(ID_ADDNOISE_SALTPEPPER, &CImageProcessView::OnUpdateAddnoiseSaltpepper)
ON_COMMAND(ID_HISTGRAM_LOCAL, &CImageProcessView::OnHistgramLocal)
ON_UPDATE_COMMAND_UI(ID_HISTGRAM_LOCAL, &CImageProcessView::OnUpdateHistgramLocal)
ON_COMMAND(ID_PREPROCESS_LAPLACESHARPEN, &CImageProcessView::OnPreprocessLaplacesharpen)
ON_UPDATE_COMMAND_UI(ID_PREPROCESS_LAPLACESHARPEN, &CImageProcessView::OnUpdatePreprocessLaplacesharpen)
ON_COMMAND(ID_SMOOTH_MEANFILTER, &CImageProcessView::OnSmoothMeanfilter)
ON_UPDATE_COMMAND_UI(ID_SMOOTH_MEANFILTER, &CImageProcessView::OnUpdateSmoothMeanfilter)
ON_COMMAND(ID_SMOOTH_GAUSSFILTER, &CImageProcessView::OnSmoothGaussfilter)
ON_UPDATE_COMMAND_UI(ID_SMOOTH_GAUSSFILTER, &CImageProcessView::OnUpdateSmoothGaussfilter)
ON_COMMAND(ID_SMOOTH_MEDIANFILTER, &CImageProcessView::OnSmoothMedianfilter)
ON_UPDATE_COMMAND_UI(ID_SMOOTH_MEDIANFILTER, &CImageProcessView::OnUpdateSmoothMedianfilter)
ON_COMMAND(ID_SMOOTH_COLORFILTER, &CImageProcessView::OnSmoothColorfilter)
ON_UPDATE_COMMAND_UI(ID_SMOOTH_COLORFILTER, &CImageProcessView::OnUpdateSmoothColorfilter)
ON_COMMAND(ID_FREQUENCYDOMAIN_FFT, &CImageProcessView::OnFrequencydomainFft)
ON_UPDATE_COMMAND_UI(ID_FREQUENCYDOMAIN_FFT, &CImageProcessView::OnUpdateFrequencydomainFft)
ON_COMMAND(ID_BUTTERWORTH_LOWFILTER, &CImageProcessView::OnButterworthLowfilter)
ON_COMMAND(ID_BUTTERWORTH_HIGHFILTER, &CImageProcessView::OnButterworthHighfilter)
ON_UPDATE_COMMAND_UI(ID_BUTTERWORTH_LOWFILTER, &CImageProcessView::OnUpdateButterworthLowfilter)
ON_UPDATE_COMMAND_UI(ID_BUTTERWORTH_HIGHFILTER, &CImageProcessView::OnUpdateButterworthHighfilter)
ON_COMMAND(ID_FREQUENCYDOMAIN_HOMOMORPHICFILTER, &CImageProcessView::OnFrequencydomainHomomorphicfilter)
ON_UPDATE_COMMAND_UI(ID_FREQUENCYDOMAIN_HOMOMORPHICFILTER, &CImageProcessView::OnUpdateFrequencydomainHomomorphicfilter)
ON_COMMAND(ID_FILE_GETMODAL, &CImageProcessView::OnFileGetmodal)
ON_UPDATE_COMMAND_UI(ID_FILE_GETMODAL, &CImageProcessView::OnUpdateFileGetmodal)
ON_COMMAND(ID_SPATIALDOMAIN_IMAGE, &CImageProcessView::OnSpatialdomainImage)
ON_UPDATE_COMMAND_UI(ID_SPATIALDOMAIN_IMAGE, &CImageProcessView::OnUpdateSpatialdomainImage)
ON_COMMAND(ID_CONVOLUTION_MEAN, &CImageProcessView::OnConvolutionMean)
ON_UPDATE_COMMAND_UI(ID_CONVOLUTION_MEAN, &CImageProcessView::OnUpdateConvolutionMean)
ON_COMMAND(ID_CONVOLUTION_GAUSS, &CImageProcessView::OnConvolutionGauss)
ON_UPDATE_COMMAND_UI(ID_CONVOLUTION_GAUSS, &CImageProcessView::OnUpdateConvolutionGauss)
ON_COMMAND(ID_CONVOLUTION_LAPLACE, &CImageProcessView::OnConvolutionLaplace)
ON_UPDATE_COMMAND_UI(ID_CONVOLUTION_LAPLACE, &CImageProcessView::OnUpdateConvolutionLaplace)
ON_COMMAND(ID_CONVOLUTION_MARR, &CImageProcessView::OnConvolutionMarr)
ON_UPDATE_COMMAND_UI(ID_CONVOLUTION_MARR, &CImageProcessView::OnUpdateConvolutionMarr)
ON_COMMAND(ID_CONVOLUTION_CORRELATION, &CImageProcessView::OnConvolutionCorrelation)
ON_UPDATE_COMMAND_UI(ID_CONVOLUTION_CORRELATION, &CImageProcessView::OnUpdateConvolutionCorrelation)
ON_COMMAND(ID_ADAPTIVE_NOISEREDUCTION, &CImageProcessView::OnAdaptiveNoisereduction)
ON_UPDATE_COMMAND_UI(ID_ADAPTIVE_NOISEREDUCTION, &CImageProcessView::OnUpdateAdaptiveNoisereduction)
ON_COMMAND(ID_ADAPTIVE_MEDIAN, &CImageProcessView::OnAdaptiveMedian)
ON_UPDATE_COMMAND_UI(ID_ADAPTIVE_MEDIAN, &CImageProcessView::OnUpdateAdaptiveMedian)
ON_COMMAND(ID_FREQUENCYDOMAIN_NOTCHPASSFILTER, &CImageProcessView::OnFrequencydomainNotchpassfilter)
ON_UPDATE_COMMAND_UI(ID_FREQUENCYDOMAIN_NOTCHPASSFILTER, &CImageProcessView::OnUpdateFrequencydomainNotchpassfilter)
ON_COMMAND(ID_FREQUENCYDOMAIN_OPTIMUMNOTCHFILTER, &CImageProcessView::OnFrequencydomainOptimumnotchfilter)
ON_UPDATE_COMMAND_UI(ID_FREQUENCYDOMAIN_OPTIMUMNOTCHFILTER, &CImageProcessView::OnUpdateFrequencydomainOptimumnotchfilter)
ON_COMMAND(ID_FREQUENCYDOMAIN_WINNERFILTER, &CImageProcessView::OnFrequencydomainWinnerfilter)
ON_UPDATE_COMMAND_UI(ID_FREQUENCYDOMAIN_WINNERFILTER, &CImageProcessView::OnUpdateFrequencydomainWinnerfilter)
ON_COMMAND(ID_FREQUENCYDOMAIN_LEASTSQUARESFILTER, &CImageProcessView::OnFrequencydomainLeastsquaresfilter)
ON_UPDATE_COMMAND_UI(ID_FREQUENCYDOMAIN_LEASTSQUARESFILTER, &CImageProcessView::OnUpdateFrequencydomainLeastsquaresfilter)
ON_COMMAND(ID_SPATIALDOMAIN_GEOMETRICTRANSFORMATIONS, &CImageProcessView::OnSpatialdomainGeometrictransformations)
ON_UPDATE_COMMAND_UI(ID_SPATIALDOMAIN_GEOMETRICTRANSFORMATIONS, &CImageProcessView::OnUpdateSpatialdomainGeometrictransformations)
ON_COMMAND(ID_DWT_DWT, &CImageProcessView::OnDwtDwt)
ON_UPDATE_COMMAND_UI(ID_DWT_DWT, &CImageProcessView::OnUpdateDwtDwt)
ON_COMMAND(ID_DWT_IDWT, &CImageProcessView::OnDwtIdwt)
ON_UPDATE_COMMAND_UI(ID_DWT_IDWT, &CImageProcessView::OnUpdateDwtIdwt)
ON_COMMAND(ID_EDGE_ALL, &CImageProcessView::OnEdgeAll)
ON_UPDATE_COMMAND_UI(ID_EDGE_ALL, &CImageProcessView::OnUpdateEdgeAll)
ON_COMMAND(ID_EDGE_H, &CImageProcessView::OnEdgeH)
ON_UPDATE_COMMAND_UI(ID_EDGE_H, &CImageProcessView::OnUpdateEdgeH)
ON_COMMAND(ID_EDGE_V, &CImageProcessView::OnEdgeV)
ON_UPDATE_COMMAND_UI(ID_EDGE_V, &CImageProcessView::OnUpdateEdgeV)
ON_COMMAND(ID_DWT_SMOTH, &CImageProcessView::OnDwtSmooth)
ON_UPDATE_COMMAND_UI(ID_DWT_SMOTH, &CImageProcessView::OnUpdateDwtSmooth)
ON_COMMAND(ID_MORPHOLOGICAL_DILATION, &CImageProcessView::OnMorphologicalDilation)
ON_UPDATE_COMMAND_UI(ID_MORPHOLOGICAL_DILATION, &CImageProcessView::OnUpdateMorphologicalDilation)
ON_COMMAND(ID_MORPHOLOGICAL_EROSION, &CImageProcessView::OnMorphologicalErosion)
ON_UPDATE_COMMAND_UI(ID_MORPHOLOGICAL_EROSION, &CImageProcessView::OnUpdateMorphologicalErosion)
ON_COMMAND(ID_MORPHOLOGICAL_OPEN, &CImageProcessView::OnMorphologicalOpen)
ON_UPDATE_COMMAND_UI(ID_MORPHOLOGICAL_OPEN, &CImageProcessView::OnUpdateMorphologicalOpen)
ON_COMMAND(ID_MORPHOLOGICAL_CLOSE, &CImageProcessView::OnMorphologicalClose)
ON_UPDATE_COMMAND_UI(ID_MORPHOLOGICAL_CLOSE, &CImageProcessView::OnUpdateMorphologicalClose)
ON_COMMAND(ID_SEGMENTATION_FIXEDTHRESHOLD, &CImageProcessView::OnSegmentationFixedthreshold)
ON_UPDATE_COMMAND_UI(ID_SEGMENTATION_FIXEDTHRESHOLD, &CImageProcessView::OnUpdateSegmentationFixedthreshold)
ON_COMMAND(ID_MORPHOLOGICAL_HITORMISS, &CImageProcessView::OnMorphologicalHitormiss)
ON_UPDATE_COMMAND_UI(ID_MORPHOLOGICAL_HITORMISS, &CImageProcessView::OnUpdateMorphologicalHitormiss)
ON_COMMAND(ID_APPLICATION_BOUNDARYEXTRACTION, &CImageProcessView::OnApplicationBoundaryextraction)
ON_UPDATE_COMMAND_UI(ID_APPLICATION_BOUNDARYEXTRACTION, &CImageProcessView::OnUpdateApplicationBoundaryextraction)
ON_COMMAND(ID_APPLICATION_REGIONFILLING, &CImageProcessView::OnApplicationRegionfilling)
ON_UPDATE_COMMAND_UI(ID_APPLICATION_REGIONFILLING, &CImageProcessView::OnUpdateApplicationRegionfilling)
ON_COMMAND(ID_APPLICATION_CONNECTEDCOMPONENTS, &CImageProcessView::OnApplicationConnectedcomponents)
ON_UPDATE_COMMAND_UI(ID_APPLICATION_CONNECTEDCOMPONENTS, &CImageProcessView::OnUpdateApplicationConnectedcomponents)
ON_COMMAND(ID_APPLICATION_CONVEXHULL, &CImageProcessView::OnApplicationConvexhull)
ON_UPDATE_COMMAND_UI(ID_APPLICATION_CONVEXHULL, &CImageProcessView::OnUpdateApplicationConvexhull)
ON_COMMAND(ID_APPLICATION_THIN, &CImageProcessView::OnApplicationThin)
ON_UPDATE_COMMAND_UI(ID_APPLICATION_THIN, &CImageProcessView::OnUpdateApplicationThin)
ON_COMMAND(ID_APPLICATION_PRUNED, &CImageProcessView::OnApplicationPruned)
ON_UPDATE_COMMAND_UI(ID_APPLICATION_PRUNED, &CImageProcessView::OnUpdateApplicationPruned)
ON_COMMAND(ID_GRAY_DILATION, &CImageProcessView::OnGrayDilation)
ON_UPDATE_COMMAND_UI(ID_GRAY_DILATION, &CImageProcessView::OnUpdateGrayDilation)
ON_COMMAND(ID_GRAY_EROSION, &CImageProcessView::OnGrayErosion)
ON_UPDATE_COMMAND_UI(ID_GRAY_EROSION, &CImageProcessView::OnUpdateGrayErosion)
ON_COMMAND(ID_GRAY_OPEN, &CImageProcessView::OnGrayOpen)
ON_UPDATE_COMMAND_UI(ID_GRAY_OPEN, &CImageProcessView::OnUpdateGrayOpen)
ON_COMMAND(ID_GRAY_CLOSE, &CImageProcessView::OnGrayClose)
ON_UPDATE_COMMAND_UI(ID_GRAY_CLOSE, &CImageProcessView::OnUpdateGrayClose)
ON_COMMAND(ID_GRAY_GRADIENT, &CImageProcessView::OnGrayGradient)
ON_UPDATE_COMMAND_UI(ID_GRAY_GRADIENT, &CImageProcessView::OnUpdateGrayGradient)
ON_COMMAND(ID_GRAY_TOPHAT, &CImageProcessView::OnGrayTophat)
ON_UPDATE_COMMAND_UI(ID_GRAY_TOPHAT, &CImageProcessView::OnUpdateGrayTophat)
ON_COMMAND(ID_EDGE_SOBEL, &CImageProcessView::OnEdgeSobel)
ON_UPDATE_COMMAND_UI(ID_EDGE_SOBEL, &CImageProcessView::OnUpdateEdgeSobel)
ON_COMMAND(ID_EDGE_LAPLACE, &CImageProcessView::OnEdgeLaplace)
ON_UPDATE_COMMAND_UI(ID_EDGE_LAPLACE, &CImageProcessView::OnUpdateEdgeLaplace)
ON_COMMAND(ID_EDGE_LOG, &CImageProcessView::OnEdgeLog)
ON_UPDATE_COMMAND_UI(ID_EDGE_LOG, &CImageProcessView::OnUpdateEdgeLog)
ON_COMMAND(ID_HOUGH_LINES, &CImageProcessView::OnHoughLines)
ON_UPDATE_COMMAND_UI(ID_HOUGH_LINES, &CImageProcessView::OnUpdateHoughLines)
ON_COMMAND(ID_SEGMENTATION_REGIONGROWING, &CImageProcessView::OnSegmentationRegiongrowing)
ON_UPDATE_COMMAND_UI(ID_SEGMENTATION_REGIONGROWING, &CImageProcessView::OnUpdateSegmentationRegiongrowing)
ON_COMMAND(ID_SEGMENTATION_WATERSHED, &CImageProcessView::OnSegmentationWatershed)
ON_UPDATE_COMMAND_UI(ID_SEGMENTATION_WATERSHED, &CImageProcessView::OnUpdateSegmentationWatershed)
ON_COMMAND(ID_APPLICATION_THINBYCONDITION, &CImageProcessView::OnApplicationThinbycondition)
ON_UPDATE_COMMAND_UI(ID_APPLICATION_THINBYCONDITION, &CImageProcessView::OnUpdateApplicationThinbycondition)
ON_COMMAND(ID_OBJECTRECOGNITION_CORRELATIONMATCH, &CImageProcessView::OnObjectrecognitionCorrelationmatch)
ON_UPDATE_COMMAND_UI(ID_OBJECTRECOGNITION_CORRELATIONMATCH, &CImageProcessView::OnUpdateObjectrecognitionCorrelationmatch)
ON_COMMAND(ID_MORPHOLOGICAL_DISTANCETRANSFORM, &CImageProcessView::OnMorphologicalDistancetransform)
ON_UPDATE_COMMAND_UI(ID_MORPHOLOGICAL_DISTANCETRANSFORM, &CImageProcessView::OnUpdateMorphologicalDistancetransform)
ON_COMMAND(ID_APPLICATION_SEPARATEOBJECT, &CImageProcessView::OnApplicationSeparateobject)
ON_UPDATE_COMMAND_UI(ID_APPLICATION_SEPARATEOBJECT, &CImageProcessView::OnUpdateApplicationSeparateobject)
ON_COMMAND(ID_WATERSHEDPROCESS_GETSEED, &CImageProcessView::OnWatershedprocessGetseed)
ON_UPDATE_COMMAND_UI(ID_WATERSHEDPROCESS_GETSEED, &CImageProcessView::OnUpdateWatershedprocessGetseed)
ON_COMMAND(ID_WATERSHEDPROCESS_LABELMARKED, &CImageProcessView::OnWatershedprocessLabelmarked)
ON_UPDATE_COMMAND_UI(ID_WATERSHEDPROCESS_LABELMARKED, &CImageProcessView::OnUpdateWatershedprocessLabelmarked)
ON_COMMAND(ID_WATERSHEDPROCESS_GETAREAS, &CImageProcessView::OnWatershedprocessGetareas)
ON_UPDATE_COMMAND_UI(ID_WATERSHEDPROCESS_GETAREAS, &CImageProcessView::OnUpdateWatershedprocessGetareas)
ON_COMMAND(ID_SEGMENTATION_OSTU, &CImageProcessView::OnSegmentationOstu)
ON_UPDATE_COMMAND_UI(ID_SEGMENTATION_OSTU, &CImageProcessView::OnUpdateSegmentationOstu)
ON_COMMAND(ID_SEGMENTATION_ENTROPY, &CImageProcessView::OnSegmentationEntropy)
ON_UPDATE_COMMAND_UI(ID_SEGMENTATION_ENTROPY, &CImageProcessView::OnUpdateSegmentationEntropy)
ON_COMMAND(ID_SEGMENTATION_MAXLIKELIHOOD, &CImageProcessView::OnSegmentationMaxlikelihood)
ON_UPDATE_COMMAND_UI(ID_SEGMENTATION_MAXLIKELIHOOD, &CImageProcessView::OnUpdateSegmentationMaxlikelihood)
ON_COMMAND(ID_SEGMENTATION_LOCALTHRESHOLDING, &CImageProcessView::OnSegmentationLocalthresholding)
ON_UPDATE_COMMAND_UI(ID_SEGMENTATION_LOCALTHRESHOLDING, &CImageProcessView::OnUpdateSegmentationLocalthresholding)
ON_COMMAND(ID_APPLICATION_PARALLELTHIN, &CImageProcessView::OnApplicationParallelthin)
ON_UPDATE_COMMAND_UI(ID_APPLICATION_PARALLELTHIN, &CImageProcessView::OnUpdateApplicationParallelthin)
ON_COMMAND(ID_HOUGH_FONTOFNORMAL, &CImageProcessView::OnHoughFontofnormal)
ON_UPDATE_COMMAND_UI(ID_HOUGH_FONTOFNORMAL, &CImageProcessView::OnUpdateHoughFontofnormal)
ON_COMMAND(ID_CIRCLEDETECTION_CHORDBISECTIONALG, &CImageProcessView::OnCircledetectionChordbisectionalg)
ON_UPDATE_COMMAND_UI(ID_CIRCLEDETECTION_CHORDBISECTIONALG, &CImageProcessView::OnUpdateCircledetectionChordbisectionalg)
ON_COMMAND(ID_CIRCLEDETECTION_ACURR, &CImageProcessView::OnCircledetectionAcurr)
ON_UPDATE_COMMAND_UI(ID_CIRCLEDETECTION_ACURR, &CImageProcessView::OnUpdateCircledetectionAcurr)
ON_COMMAND(ID_HISTGRAM_GRAYBAR, &CImageProcessView::OnHistgramGrayBar)
ON_UPDATE_COMMAND_UI(ID_HISTGRAM_GRAYBAR, &CImageProcessView::OnUpdateHistgramGrayBar)
ON_COMMAND(ID_HISTGRAM_RGBBAR, &CImageProcessView::OnHistgramRgbbar)
ON_UPDATE_COMMAND_UI(ID_HISTGRAM_RGBBAR, &CImageProcessView::OnUpdateHistgramRgbbar)
ON_COMMAND(ID_HISTGRAM_HSIBAR, &CImageProcessView::OnHistgramHsibar)
ON_UPDATE_COMMAND_UI(ID_HISTGRAM_HSIBAR, &CImageProcessView::OnUpdateHistgramHsibar)
ON_COMMAND(ID_OBJECTRECOGNITION_PLESSEYCORNERDETECTOR, &CImageProcessView::OnObjectrecognitionPlesseycornerdetector)
ON_UPDATE_COMMAND_UI(ID_OBJECTRECOGNITION_PLESSEYCORNERDETECTOR, &CImageProcessView::OnUpdateObjectrecognitionPlesseycornerdetector)
ON_COMMAND(ID_EDGE_CANNY, &CImageProcessView::OnEdgeCanny)
ON_UPDATE_COMMAND_UI(ID_EDGE_CANNY, &CImageProcessView::OnUpdateEdgeCanny)
ON_COMMAND(ID_SEGMENTATION_OPTIMAL, &CImageProcessView::OnSegmentationOptimal)
ON_UPDATE_COMMAND_UI(ID_SEGMENTATION_OPTIMAL, &CImageProcessView::OnUpdateSegmentationOptimal)
ON_COMMAND(ID_EDGE_NON, &CImageProcessView::OnEdgeNon)
ON_UPDATE_COMMAND_UI(ID_EDGE_NON, &CImageProcessView::OnUpdateEdgeNon)
ON_COMMAND(ID_EDGE_HYSTERESIS, &CImageProcessView::OnEdgeHysteresis)
ON_UPDATE_COMMAND_UI(ID_EDGE_HYSTERESIS, &CImageProcessView::OnUpdateEdgeHysteresis)
ON_COMMAND(ID_HOUGH_CIRCLE, &CImageProcessView::OnHoughCircle)
ON_UPDATE_COMMAND_UI(ID_HOUGH_CIRCLE, &CImageProcessView::OnUpdateHoughCircle)
ON_COMMAND(ID_SEGMENTATION_DYNAMIC, &CImageProcessView::OnSegmentationDynamic)
ON_UPDATE_COMMAND_UI(ID_SEGMENTATION_DYNAMIC, &CImageProcessView::OnUpdateSegmentationDynamic)
ON_COMMAND(ID_SPATIALDOMAIN_ZOOMBILINEARINTERPOLATION, &CImageProcessView::OnSpatialdomainZoombilinearinterpolation)
ON_UPDATE_COMMAND_UI(ID_SPATIALDOMAIN_ZOOMBILINEARINTERPOLATION, &CImageProcessView::OnUpdateSpatialdomainZoombilinearinterpolation)
ON_UPDATE_COMMAND_UI(ID_APPLICATION_CONTOURTRACE, &CImageProcessView::OnUpdateApplicationContourtrace)
ON_COMMAND(ID_APPLICATION_CONTOURTRACE, &CImageProcessView::OnApplicationContourtrace)
ON_COMMAND(ID_EDGE_TRACE, &CImageProcessView::OnEdgeTrace)
ON_UPDATE_COMMAND_UI(ID_EDGE_TRACE, &CImageProcessView::OnUpdateEdgeTrace)
ON_WM_KEYDOWN()
ON_COMMAND(ID_SMOOTH_TRUN, &CImageProcessView::OnSmoothTrun)
ON_UPDATE_COMMAND_UI(ID_SMOOTH_TRUN, &CImageProcessView::OnUpdateSmoothTrun)
ON_COMMAND(ID_SMOOTH_ANISOTROPICDIFFUSION, &CImageProcessView::OnSmoothAnisotropicdiffusion)
ON_UPDATE_COMMAND_UI(ID_SMOOTH_ANISOTROPICDIFFUSION, &CImageProcessView::OnUpdateSmoothAnisotropicdiffusion)
ON_COMMAND(ID_GRAY_RECONSTRUCTION, &CImageProcessView::OnGrayReconstruction)
ON_COMMAND(ID_EDGE_RELAXATION, &CImageProcessView::OnEdgeRelaxation)
ON_UPDATE_COMMAND_UI(ID_EDGE_RELAXATION, &CImageProcessView::OnUpdateEdgeRelaxation)
ON_COMMAND(ID_SEGMENTATION_BOUNDARYTRACE, &CImageProcessView::OnSegmentationBoundarytrace)
ON_UPDATE_COMMAND_UI(ID_SEGMENTATION_BOUNDARYTRACE, &CImageProcessView::OnUpdateSegmentationBoundarytrace)
ON_COMMAND(ID_FILE_OPENAVI, &CImageProcessView::OnFileOpenavi)
ON_WM_TIMER()
ON_COMMAND(ID_FILE_BMP2AVI, &CImageProcessView::OnFileBmp2avi)
ON_WM_RBUTTONDOWN()
END_MESSAGE_MAP()
// CImageProcessView construction/destruction
CImageProcessView::CImageProcessView()
{
// TODO: add construction code here
m_bDrag=false;
m_bTwoValue=false;
m_bDWT=false;
pDlg=NULL;
THRESHOLD=100;
m_bWatershedProcGetSeed=false;
m_AviBuff=NULL;
}
CImageProcessView::~CImageProcessView()
{
if(m_pModelData)
delete []m_pModelData;
m_pModelData=NULL;//must do it else heap err !!!
m_bWatershedProcGetSeed=false;
if(pDlg)
{ delete []pDlg->pData;
delete pDlg;//无模式对话框
pDlg=NULL;
}
}
BOOL CImageProcessView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CScrollView::PreCreateWindow(cs);
}
// CImageProcessView drawing
void CImageProcessView::OnDraw(CDC* pDC)
{
CImageProcessDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
CSize sizeTotal;
if(pDoc->m_pDib->m_lpBMIH!=NULL){
//if< image size some image part cann't see!
sizeTotal.cx =pDoc->m_pDib->m_lpBMIH->biWidth+4;//change it ,no use? big enough then have bar
sizeTotal.cy= pDoc->m_pDib->m_lpBMIH->biHeight+4;//big enough then have bar
SetScrollSizes(MM_TEXT, sizeTotal);//must have ;use scroll
ResizeParentToFit( );
}
// TODO: add draw code for native data here
//填充底色为灰
CRect m_rcClient;
GetClientRect(&m_rcClient);
CBrush m_brsBG;
m_brsBG.CreateSolidBrush(RGB(192,192,192));//COLOR_GRAY;
pDC->FillRect(&m_rcClient, &m_brsBG);
if (pDoc->m_pDib->m_lpBMIH!=NULL){
CSize sizeFileDib=pDoc->m_pDib->GetDimensions();
pDoc->m_pDib->Draw(pDC,CPoint(0,0),sizeFileDib);
lWidth =pDoc->m_pDib->m_lpBMIH->biWidth; // Size of DIB - x
lHeight= pDoc->m_pDib->m_lpBMIH->biHeight; // Size of DIB - y
//if Select Area is error,init
if(pDoc->EndPoint.x-pDoc->StartPoint.x<=5 || pDoc->EndPoint.x>lWidth-1 ||
pDoc->EndPoint.y-pDoc->StartPoint.y<=5 || pDoc->EndPoint.y>lHeight-1 || pDoc->StartPoint.y<0 || pDoc->StartPoint.x<0)
{
pDoc->StartPoint.x=0;pDoc->StartPoint.y=0;
pDoc->EndPoint.x=lWidth-1;pDoc->EndPoint.y=lHeight-1;
}
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8 )
{
lLineBytes=lWidth & 0xffc;
if(lWidth%4) lLineBytes+=4;
//if TwoValue?
m_bTwoValue=true;
unsigned char* lpSrc;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{ lpSrc =(unsigned char *)pDoc->m_pDib->m_lpImage+ lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x;
// 针对每行图像每列进行操作
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
{
if(*lpSrc & 0x70)
{
m_bTwoValue=false;
i =pDoc->EndPoint.y+1;//out
j =pDoc->EndPoint.x+1;
}
lpSrc++;//
}
}
}else if(pDoc->m_pDib->m_lpBMIH->biBitCount==24 )
lLineBytes =(lWidth *3+3)/4*4;
else if(pDoc->m_pDib->m_lpBMIH->biBitCount==32 )
lLineBytes =lWidth *4;
if(pDoc->StartPoint.y >0 || pDoc->StartPoint.x >0 || pDoc->EndPoint.y <lHeight-1 || pDoc->EndPoint.x <lWidth-1 ){//not all area
CPen myPen;
myPen.CreatePen(PS_DOT, 1, RGB(255,0,0));
pDC->SelectObject(myPen);
pDC->SelectObject(GetStockObject(NULL_BRUSH));
pDC->Rectangle(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y));
}
}
else
{
pDC->SetBkMode(TRANSPARENT);
pDC->TextOut(50,100,"Open an Image !");
}
}
// CImageProcessView printing
BOOL CImageProcessView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CImageProcessView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CImageProcessView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
// CImageProcessView diagnostics
#ifdef _DEBUG
void CImageProcessView::AssertValid() const
{
CScrollView::AssertValid();
}
void CImageProcessView::Dump(CDumpContext& dc) const
{
CScrollView::Dump(dc);
}
CImageProcessDoc* CImageProcessView::GetDocument() const // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CImageProcessDoc)));
return (CImageProcessDoc*)m_pDocument;
}
#endif //_DEBUG
// CImageProcessView message handlers
void CImageProcessView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
CImageProcessDoc* pDoc = GetDocument();
static bool first=true;//do it once,must have it for DisplayNewImg()
if (pDoc->m_pDib->m_lpBMIH==NULL && first){
first=false;
CString m_fileName;//=("c:\\tu\\Iris.bmp");
char strDirName[80];
GetCurrentDirectory(80, (LPSTR)strDirName);
CString pathName;
pathName.Format(_T("%s"),strDirName);
m_fileName=pathName+"\\lena.bmp";
CFile file;
if( file.Open(m_fileName,CFile::modeRead | CFile::shareDenyWrite,NULL))
{
pDoc->m_pDib->Read(&file);file.Close();
pDoc->SetPathName(m_fileName);//if not cannot get pDoc->GetPathName
}
}
CSize sizeTotal;
if(pDoc->m_pDib->m_lpBMIH==NULL){
sizeTotal.cx =512+4;
sizeTotal.cy= 512+4;
}
else{
//if< image size some image part cann't see!
sizeTotal.cx =pDoc->m_pDib->m_lpBMIH->biWidth+4;//change it ,no use? big enough then have bar
sizeTotal.cy= pDoc->m_pDib->m_lpBMIH->biHeight+4;//big enough then have bar
}
SetScrollSizes(MM_TEXT, sizeTotal);//must have ;use scroll
ResizeParentToFit( );
}
void CImageProcessView::OnFileReOpen()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
CFile file;
if(NULL!=file.Open(pDoc->GetPathName(),CFile::modeRead | CFile::shareDenyWrite,NULL))
{
pDoc->m_pDib->Read(&file);
file.Close();
}
}
void CImageProcessView::OnUpdateFileReOpen(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnEditPaste()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
COleDataObject dataObject;
VERIFY(dataObject.AttachClipboard());
// Seems to be MOVEABLE memory, so we must use GlobalLock!
// (hDib != lpDib) GetGlobalData copies the memory, so we can
// hang onto it until we delete the CDib.
HGLOBAL hDib = dataObject.GetGlobalData(CF_DIB);
ASSERT(hDib != NULL);
LPVOID lpDib = ::GlobalLock(hDib);
ASSERT(lpDib != NULL);
pDoc->m_pDib->AttachMemory(lpDib, TRUE, hDib);
CClientDC dc(this);
pDoc->m_pDib->UsePalette(&dc);
pDoc->SetModifiedFlag();
pDoc->UpdateAllViews(NULL);
}
void CImageProcessView::OnEditCopy()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
COleDataSource* pSource = new COleDataSource();
int nHeaderSize = pDoc->m_pDib->GetSizeHeader();
int nImageSize = pDoc->m_pDib->GetSizeImage();
HGLOBAL hHeader = ::GlobalAlloc(GMEM_SHARE,
nHeaderSize + nImageSize);
LPVOID pHeader = ::GlobalLock(hHeader);
ASSERT(pHeader != NULL);
LPVOID pImage = (LPBYTE) pHeader + nHeaderSize;
memcpy(pHeader, pDoc->m_pDib->m_lpBMIH, nHeaderSize);
memcpy(pImage, pDoc->m_pDib->m_lpImage, nImageSize);
// Receiver is supposed to free the global memory
::GlobalUnlock(hHeader);
pSource->CacheGlobalData(CF_DIB, hHeader);
if (pSource)
pSource->SetClipboard(); // OLE deletes data source
}
void CImageProcessView::OnUpdateEditCopy(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnUpdateEditPaste(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
// CImageProcessDoc* pDoc = GetDocument();
COleDataObject dataObject;
BOOL bAvail = dataObject.AttachClipboard() && dataObject.IsDataAvailable(CF_DIB);
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(!m_bDrag){
m_LastStPoint = point+GetDeviceScrollPosition( );
m_LastEndPoint=m_LastStPoint;
m_bDrag = true;
}
//select seed
if(m_bWatershedProcGetSeed)
{
CPoint pt=point+GetDeviceScrollPosition( );
*(m_pModelData+lLineBytes * (lHeight - 1 - pt.y) + pt.x)=TWOVALUE_H;
}
CScrollView::OnLButtonDown(nFlags, point);
}
void CImageProcessView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CImageProcessDoc* pDoc = GetDocument();
m_bDrag = false;
//比较点大小,获取区域
CPoint pt=point+GetDeviceScrollPosition( );
CPoint pt1,pt2;
pt1.x=min(m_LastStPoint.x,pt.x);
pt1.y=min(m_LastStPoint.y,pt.y);
pt2.x=max(m_LastStPoint.x,pt.x);
pt2.y=max(m_LastStPoint.y,pt.y);
if(pt1.x>0 && pt2.x-pt1.x>5 && pt2.x<lWidth-1
&& pt1.y>0 && pt2.y-pt1.y>5 && pt2.y<lHeight-1)
{
//change select area
pDoc->StartPoint=pt1;
pDoc->EndPoint=pt2;
}
Invalidate(true);//Draw Rect
CScrollView::OnLButtonUp(nFlags, point);
}
void CImageProcessView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CImageProcessDoc* pDoc = GetDocument();
CPoint pt=point+GetDeviceScrollPosition( );
if(m_bDrag)//Draw select Rect
{
RECT lastrect, currect;
lastrect.top =min(m_LastStPoint.y,m_LastEndPoint.y)-GetDeviceScrollPosition( ).y;
lastrect.left =min(m_LastStPoint.x,m_LastEndPoint.x)-GetDeviceScrollPosition( ).x;
lastrect.right =max(m_LastStPoint.x,m_LastEndPoint.x)-GetDeviceScrollPosition( ).x;
lastrect.bottom =max(m_LastStPoint.y,m_LastEndPoint.y)-GetDeviceScrollPosition( ).y;
currect.top =min(pt.y,m_LastStPoint.y)-GetDeviceScrollPosition( ).y;
currect.left =min(pt.x,m_LastStPoint.x)-GetDeviceScrollPosition( ).x;
currect.right =max(pt.x,m_LastStPoint.x)-GetDeviceScrollPosition( ).x;
currect.bottom = max(pt.y,m_LastStPoint.y)-GetDeviceScrollPosition( ).y;
SIZE sz;
sz.cx = 1;
sz.cy = 1;
CDC *pdc = GetDC();
CBrush m_brsBG;
m_brsBG.CreateSolidBrush(RGB(255,255,255));//;
pdc->DrawDragRect(&currect, sz, &lastrect, sz, &m_brsBG,&m_brsBG);//, NULL);//no corlor
ReleaseDC(pdc);
CString str;
//CMainFrame* pFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd;
//CStatusBar* pStatus=&pFrame->m_wndStatusBar;
//if(pStatus){
// str.Format("区域(%d:%d)-(%d:%d)",currect.left,currect.top,currect.right,currect.bottom);
// pStatus->SetPaneText(0,str);
//}
// same as:
str.Format("区域(%d:%d)-(%d:%d)",currect.left,currect.top,currect.right,currect.bottom);
((CMainFrame*)AfxGetMainWnd())->m_wndStatusBar.SetPaneText(0,str);
m_LastEndPoint = pt;
}
else//display point infomation
{
m_LastEndPoint=pt;
//display point value
CString str;
str="";
if(pDoc->m_pDib->m_lpBMIH){
unsigned char *lpSrc;
if((pt.x>=0) && (pt.x<lWidth) && (pt.y>=0) && (pt.y<lHeight)){
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8 ){
lpSrc=(unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes*(lHeight - 1 -pt.y) + pt.x;
double grad=0.0;
double angle=0.0;
Gradient(pt,&grad,&angle);
str.Format("(x=%d y=%d)=%d\tGradient(%3.1f,%3.1f)",pt.x,pt.y,*lpSrc,grad,angle);
}
else if(pDoc->m_pDib->m_lpBMIH->biBitCount==24 ){
lpSrc=(unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes*(lHeight - 1 -pt.y) + pt.x*3;
RGB rgb;
HSI hsi;
rgb.b=*lpSrc;rgb.g=*(lpSrc+1);rgb.r=*(lpSrc+2);
RgbtoHsi(&rgb, &hsi);
int gray=(int)(0.114*rgb.r+0.587*rgb.g+0.299*rgb.b);
str.Format("Pos(%d %d) RGB(%d %d %d) Gray(%d) hsi(%4.1f %3.2f %3.2f--%d %d %d)",
point.x,point.y,rgb.r,rgb.g,rgb.b,gray,
hsi.Hue,hsi.Saturation,hsi.Intensity,
(int)(hsi.Hue/360.0*255.0),(int)(hsi.Saturation*255.0),(int)(hsi.Intensity*255.0));
}else if(pDoc->m_pDib->m_lpBMIH->biBitCount==32 ){
lpSrc=(unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes*(lHeight - 1 -pt.y) + pt.x*4;
RGB rgb;
HSI hsi;
rgb.b=*lpSrc;rgb.g=*(lpSrc+1);rgb.r=*(lpSrc+2);//*(lpSrc+3)==*(lpSrc+1)?????
RgbtoHsi(&rgb, &hsi);
int gray=(int)(0.114*rgb.r+0.587*rgb.g+0.299*rgb.b);
str.Format("Pos(%d %d) RGB(%d %d %d) Gray(%d) hsi(%4.1f %3.2f %3.2f--%d %d %d)",
point.x,point.y,rgb.r,rgb.g,rgb.b,gray,
hsi.Hue,hsi.Saturation,hsi.Intensity,
(int)(hsi.Hue/360.0*255.0),(int)(hsi.Saturation*255.0),(int)(hsi.Intensity*255.0));
}
((CMainFrame*)AfxGetMainWnd())->m_wndStatusBar.SetPaneText(0,str);
}
}
}
CScrollView::OnMouseMove(nFlags, point);
}
void CImageProcessView::Gradient(CPoint pt,double* grad,double* angle)
{
CImageProcessDoc* pDoc = GetDocument();
int pixel[8];
if(pt.y>2 && pt.y<lHeight-2 && pt.x>2 && pt.x<lWidth-2){
//if(pt.y>0 && pt.y<lHeight-1 && pt.x>0 && pt.x<lWidth-1){
unsigned char *lpSrc;
lpSrc = (unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - pt.y) + pt.x;
//sobel no noise Theta<1
pixel[0] = (int)*(lpSrc+lLineBytes-1);
pixel[1] = (int)*(lpSrc+lLineBytes);
pixel[2] = (int)*(lpSrc+lLineBytes+1);
pixel[3] = (int)*(lpSrc-1);
pixel[4] = (int)*(lpSrc+1);
pixel[5] = (int)*(lpSrc - lLineBytes-1);
pixel[6] = (int)*(lpSrc - lLineBytes);
pixel[7] = (int)*(lpSrc - lLineBytes+1);
// 1 2 1
// 0 0 0
// -1 -2 -1
int gy=pixel[0]+2*pixel[1]+pixel[2]-pixel[5]-2*pixel[6]-pixel[7];
// -1 0 1
// -2 0 2
// -1 0 1
int gx=pixel[2]+2*pixel[4]+pixel[7]-pixel[0]-2*pixel[3]-pixel[5];
no noise Theta<0.2
//double h[7][7]=
//{
// { 0.000, -0.646, -0.815, 0.000, 0.815, 0.646, 0.000},
// {-0.963, -1.997, -1.000, 0.000, 1.000, 1.997, 0.963},
// {-2.458, -2.000, -1.000, 0.000, 1.000, 2.000, 2.458},
// {-2.962, -2.000, -1.000, 0.000, 1.000, 2.000, 2.962},
// {-2.458, -2.000, -1.000, 0.000, 1.000, 2.000, 2.458},
// {-0.963, -1.997, -1.000, 0.000, 1.000, 1.997, 0.963},
// { 0.000, -0.646, -0.815, 0.000, 0.815, 0.646, 0.000}
//};
//double gx=0.0;
//double gy=0.0;
//for(int i=-3;i<4;i++)
// for(int j=-3;j<4;j++){
// gx+=(h[i+3][j+3]*(*(lpSrc+i*lLineBytes+j)));
// gy-=(h[j+3][i+3]*(*(lpSrc+i*lLineBytes+j)));
// }
*grad =sqrt(double(gx*gx+gy*gy));
if(gx==0){
if(gy>0) *angle=90;
else if(gy<0) *angle=270;
}else{
if(gy==0){
if(gx>0) *angle=0;
else if(gx<0) *angle=180;
}else
{
*angle=180.0/Pi*atan((double)gy/gx);
if(gx<0 && gy<0)
*angle=*angle+180;
else if(gx<0 && gy>0) *angle=*angle+180;
else if(gx>0 && gy<0)
if((*angle)<-0.5) *angle=*angle+360;
}
}
}
}
void CImageProcessView::OnEditCut()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
int w,h;
w=pDoc->EndPoint.x-pDoc->StartPoint.x+1;
h=pDoc->EndPoint.y-pDoc->StartPoint.y+1;
int n;
int l;
int biBitCount=pDoc->m_pDib->m_lpBMIH->biBitCount;
if(biBitCount==8)
{n=1;l=(w+3)/4*4;}
else if(biBitCount==24)
{n=3;l=(w*3+3)/4*4;}
else {n=4;l=w*4;}
unsigned char *lpNewDIBBits=new unsigned char [((long) h) * l];
// 判断是否内存分配失败
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
unsigned char *lpDst,*lpSrc;
for(int i = 0; i < h; i++)
{
// 列
for(int j = 0; j <w ; j++)
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i-pDoc->StartPoint.y) + (j+pDoc->StartPoint.x)*n;
lpDst = (unsigned char*)lpNewDIBBits + l * (h - 1 - i) + j*n;
*lpDst=*lpSrc;
if(n>=3){
*(lpDst+1)=*(lpSrc+1);
*(lpDst+2)=*(lpSrc+2);}
if(n==8)//32 bit
*(lpDst+3)=*(lpSrc+3);
}
}
// 复制的图像
unsigned char ColorTable[1024];
if(biBitCount==8){
lpSrc=(unsigned char*)pDoc->m_pDib->m_lpvColorTable;
memcpy(ColorTable,lpSrc,1024);
}
delete pDoc->m_pDib;
lHeight =h;
lWidth =w;
lLineBytes=l;
pDoc->m_pDib =new CDib(CSize(lLineBytes,lHeight) ,biBitCount);
pDoc->m_pDib->m_lpBMIH->biWidth=lWidth;
if(biBitCount==8){
lpSrc=(unsigned char*)pDoc->m_pDib->m_lpvColorTable;
memcpy(lpSrc,ColorTable,1024);
}
memcpy(pDoc->m_pDib->m_lpImage,lpNewDIBBits,lLineBytes*lHeight);
delete []lpNewDIBBits;
Invalidate(true);
}
void CImageProcessView::OnUpdateEditCut(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->StartPoint.y >0 || pDoc->StartPoint.x >0 || pDoc->EndPoint.y <lHeight-1 || pDoc->EndPoint.x <lWidth-1)
if(pDoc->m_pDib->m_lpBMIH!=NULL)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::RgbtoHsi(RGB *pRgb, HSI *pHsi)
{
const double ZERO_SATURATION=0.0;
const double UNDEFINED_HUE=0.000;
const double DEGREES_PER_RADIAN =180.0 / 3.14159265358979;
double R, G, B, Sum, Quotient;
double Radians, Angle, MinValue, MaxValue, TempDouble1, TempDouble2;
R = ((double) pRgb->r) / 255.0;
G = ((double) pRgb->g) / 255.0;
B = ((double) pRgb->b) / 255.0;
Sum = R + G + B;
pHsi->Intensity = Sum / 3.0;
MinValue = (R < G) ? R : G;
MinValue = (B < MinValue) ? B : MinValue;
MaxValue = (R > G) ? R : G;
MaxValue = (B > MaxValue) ? B : MaxValue;
if(pHsi->Intensity < 0.00001)
pHsi->Saturation = ZERO_SATURATION;
else
pHsi->Saturation = 1.0 - (3.0 * MinValue) / Sum;
if(MinValue == MaxValue)
{
pHsi->Hue = UNDEFINED_HUE;
pHsi->Saturation = ZERO_SATURATION;
return;
}
TempDouble1 = (((R - G) + (R - B)) / 2.0);
TempDouble2 = (R - G) * (R - G) + (R - B) * (G - B);
Quotient = (TempDouble1 / sqrt(TempDouble2));
Radians = acos(Quotient);
Angle = Radians * DEGREES_PER_RADIAN;
pHsi->Hue =(B>G) ? 360.0 - Angle : Angle;
return;
}
void CImageProcessView::OnViewSelectareamaximum()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
pDoc->StartPoint.x=0;pDoc->StartPoint.y=0;
pDoc->EndPoint.x=lWidth-1;pDoc->EndPoint.y=lHeight-1;
Invalidate(true);
}
void CImageProcessView::OnUpdateViewSelectareamaximum(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
bool bEnable=false;
if(pDoc->StartPoint.y >0 || pDoc->StartPoint.x >0 || pDoc->EndPoint.y <lHeight-1 || pDoc->EndPoint.x <lWidth-1)
bEnable=true;
pCmdUI->Enable(bEnable);
}
void CImageProcessView::OnViewInformation()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
//display info
CString str;
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8 ){
int hist[256]={0};
int min=255;
int max=0;
int total=0;
int num=(pDoc->EndPoint.x-pDoc->StartPoint.x+1)*(pDoc->EndPoint.y-pDoc->StartPoint.y+1);
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
unsigned char* lpSrc =(unsigned char *)pDoc->m_pDib->m_lpImage+ lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;//
hist[*lpSrc]++;
if(*lpSrc<min) min=*lpSrc;
if(*lpSrc>max) max=*lpSrc;
total+=*lpSrc;
}
}
if(num<1) num=1;
int mean=(int)(total/num);
int v=0;
int k_1=0,k_10=0,k_90=255,k_99=255;
for(int i=0;i<256;i++)
{
v+=hist[i];
if(v<num/100)
k_1=i;
if(v<num/10)
k_10=i;
if(v<num*9/10)
k_90=i;
if(v<num*99/100)
k_99=i;
}
if(num>20){
str.Format("\npDoc->StartPoint(%d ,%d)---pDoc->EndPoint(%d ,%d)\n Size(%dx%d)\n min=%d,max=%d,mean=%d\n\nratio\tgray\n0.01\t%d \n0.1 \t%d\n0.9 \t%d\n0.99\t%d\n",
pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y,pDoc->EndPoint.x-pDoc->StartPoint.x+1,pDoc->EndPoint.y-pDoc->StartPoint.y+1,
min,max,mean,
k_1,k_10,k_90,k_99);
//TRACE(str);
if(pDoc->EndPoint.x-pDoc->StartPoint.x+1<=16 && pDoc->EndPoint.y-pDoc->StartPoint.y+1<=16){
//for see edge
if(pDoc->EndPoint.x-pDoc->StartPoint.x<20 && pDoc->StartPoint.x<10)
{ pDoc->EndPoint.x=15;
pDoc->StartPoint.x=0;
}
if(pDoc->EndPoint.x-pDoc->StartPoint.x<20 && pDoc->EndPoint.x>lWidth-10)
{ pDoc->EndPoint.x=lWidth-1;
pDoc->StartPoint.x=lWidth-16;
}
if(pDoc->EndPoint.y-pDoc->StartPoint.y<20 && pDoc->StartPoint.y<10)
{ pDoc->EndPoint.y=15;
pDoc->StartPoint.y=0;
}
if(pDoc->EndPoint.y-pDoc->StartPoint.y<20 && pDoc->EndPoint.y>lHeight-10)
{ pDoc->EndPoint.y=lHeight-1;
pDoc->StartPoint.y=lHeight-16;
}
CString tmpstr;
str.Format("Data Size(%d x %d)[%d,%d,%d,%d]:\n",pDoc->EndPoint.x-pDoc->StartPoint.x+1,pDoc->EndPoint.y-pDoc->StartPoint.y+1,
pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y);
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
str+="\n";
unsigned char* lpSrc =(unsigned char *)pDoc->m_pDib->m_lpImage+ lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;//
if(m_bTwoValue) tmpstr.Format("%d ",*lpSrc);
else{
if(*lpSrc<10) tmpstr.Format("00%d ",*lpSrc);
else if(*lpSrc<100) tmpstr.Format("0%d ",*lpSrc);
else tmpstr.Format("%d ",*lpSrc);
}
str+=tmpstr;
}
}
tmpstr.Format("\n\n min=%d,max=%d,mean=%d\nColor=%d\n",min,max,mean,pDoc->m_pDib->m_lpBMIH->biBitCount);
str+=tmpstr;
}
MessageBox(str);
}
}
else{//color
unsigned char* lpSrc;
int mingray=255;
int maxgray=0;
RGB minRgb;
RGB maxRgb;
HSI minHsi;
HSI maxHsi;
long int totalgray=0;
long int totalrgb_r=0;
long int totalrgb_g=0;
long int totalrgb_b=0;
double totalHsi_Hue=0.0;
double totalHsi_Saturation=0.0;
double totalHsi_Intensity=0.0;
minRgb.b=minRgb.g=minRgb.r=255;
maxRgb.b=maxRgb.g=maxRgb.r=0;
minHsi.Hue=360.0;
minHsi.Saturation=minHsi.Intensity=1.0;
maxHsi.Hue=maxHsi.Saturation=maxHsi.Intensity=0.0;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
{
lpSrc=(unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes*(lHeight - 1 -i) + j*3;
RGB rgb;
HSI Hsi;
rgb.b=*lpSrc;rgb.g=*(lpSrc+1);rgb.r=*(lpSrc+2);
RgbtoHsi(&rgb, &Hsi);
int gray=(int)(0.114*rgb.r+0.587*rgb.g+0.299*rgb.b);
if(gray<mingray) mingray=gray;
if(gray>maxgray) maxgray=gray;
totalgray+=gray;
if(rgb.r<minRgb.r) minRgb.r=rgb.r;
if(rgb.r>maxRgb.r) maxRgb.r=rgb.r;
totalrgb_r+=rgb.r;
if(rgb.g<minRgb.g) minRgb.g=rgb.g;
if(rgb.g>maxRgb.g) maxRgb.g=rgb.g;
totalrgb_g+=rgb.g;
if(rgb.b<minRgb.b) minRgb.b=rgb.b;
if(rgb.b>maxRgb.b) maxRgb.b=rgb.b;
totalrgb_b+=rgb.b;
if(Hsi.Hue<minHsi.Hue) minHsi.Hue=Hsi.Hue;
if(Hsi.Hue>maxHsi.Hue) maxHsi.Hue=Hsi.Hue;
totalHsi_Hue+=Hsi.Hue;
if(Hsi.Saturation<minHsi.Saturation) minHsi.Saturation=Hsi.Saturation;
if(Hsi.Saturation>maxHsi.Saturation) maxHsi.Saturation=Hsi.Saturation;
totalHsi_Saturation+=Hsi.Saturation;
if(Hsi.Intensity<minHsi.Intensity) minHsi.Intensity=Hsi.Intensity;
if(Hsi.Intensity>maxHsi.Intensity) maxHsi.Intensity=Hsi.Intensity;
totalHsi_Intensity+=Hsi.Intensity;
}
long int num=(long(pDoc->EndPoint.x-pDoc->StartPoint.x+1))*(pDoc->EndPoint.y-pDoc->StartPoint.y+1);
if(num>20){
CString tmpStr;
str.Format("pDoc->StartPoint(%d ,%d)---pDoc->EndPoint(%d ,%d)\n Size(%d x %d)\nColor=%d\n",
pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y,pDoc->EndPoint.x-pDoc->StartPoint.x+1,
pDoc->EndPoint.y-pDoc->StartPoint.y+1,pDoc->m_pDib->m_lpBMIH->biBitCount);
tmpStr.Format("\n \tmin \tmax \tmean\n");
str+=tmpStr;
tmpStr.Format("R\t%d \t%d \t%d\n",minRgb.r,maxRgb.r,(int)(totalrgb_r/num));
str+=tmpStr;
tmpStr.Format("G\t%d \t%d \t%d\n",minRgb.g,maxRgb.g,(int)(totalrgb_g/num));
str+=tmpStr;
tmpStr.Format("B\t%d \t%d \t%d\n",minRgb.b,maxRgb.b,(int)(totalrgb_b/num));
str+=tmpStr;
tmpStr.Format("H\t%3.2f \t%3.2f \t%3.2f\n",minHsi.Hue,maxHsi.Hue,totalHsi_Hue/num);
str+=tmpStr;
tmpStr.Format("S\t%3.2f \t%3.2f \t%3.2f\n",minHsi.Saturation,maxHsi.Saturation,totalHsi_Saturation/num);
str+=tmpStr;
tmpStr.Format("I\t%3.2f \t%3.2f \t%3.2f\n",minHsi.Intensity,maxHsi.Intensity,totalHsi_Intensity/num);
str+=tmpStr;
tmpStr.Format("\nGray\t%d \t%d \t%d\n",mingray,maxgray,(int)(totalgray/num));
str+=tmpStr;
//TRACE(str);
MessageBox(str);
}
}
}
void CImageProcessView::OnUpdateViewInformation(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnHistgramGray()
{
// TODO: Add your command handler code here
// CImageProcessDoc* pDoc = GetDocument();
int Hist[256]={0};
GetHistgram(Hist,false);
DisplayDlg dlg;
dlg.pData=&Hist[0];
dlg.m_Sizex=256;
dlg.m_LinePos=100;
dlg.m_Title=_T("灰度直方图");
dlg.m_Level=1;
dlg.DoModal();
}
void CImageProcessView::GetHistgram(int* pHistgram,bool bSmooth)
{
CImageProcessDoc* pDoc = GetDocument();
//获得直方图
int iMaxGrayValue = 0;
int iMinGrayValue = 255;
unsigned char* lpSrc;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;
int pixel = (int)*lpSrc;
pHistgram[pixel]++;
//修改最大,最小灰度值
if(iMinGrayValue > pixel)
iMinGrayValue = pixel;
if(iMaxGrayValue < pixel)
iMaxGrayValue = pixel;
}
}
if(!bSmooth) return;
int tmpH[256];
memcpy(tmpH,pHistgram,256*sizeof(int));
//Gauss filter[7]2.0
//[32,60,88,100,88,60,32]
/*double d1=exp(-1/(2.0*2.0*2.0));
double d2=exp(-4/(2.0*2.0*2.0));
double d3=exp(-9/(2.0*2.0*2.0));
*/
for (int i = max(iMinGrayValue-2,2); i < min(iMaxGrayValue+2,253);i++){
int tmp=0;
tmp=(tmpH[i-2]+tmpH[i+2])*32+(tmpH[i-2]+tmpH[i+2])*60+(tmpH[i-1]+tmpH[i+1])*88+tmpH[i]*100;
pHistgram[i]=tmp/460;
}
return ;
}
void CImageProcessView::OnUpdateHistgramGray(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnHistgramRgb()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
int m_nHistRGB[256*3]={0};
unsigned char *lpSrc;
// 计算各个灰度值的计数,即得到直方图
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes*(lHeight-1-i) + j*3;//down -up
// 计数加1
m_nHistRGB[*(lpSrc+2)]++;//R
m_nHistRGB[256+*(lpSrc+1)]++;//G
m_nHistRGB[256*2+*(lpSrc)]++;//B
}
DisplayDlg dlg;
dlg.pData=&m_nHistRGB[0];
dlg.m_Sizex=256;
dlg.m_Title="彩色RGB直方图";
dlg.m_Level=3;//draw number
dlg.m_LinePos=0;
dlg.DoModal();
}
void CImageProcessView::OnUpdateHistgramRgb(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==24)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnHistgramHsi()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
int m_nHistHSI[256*3]={0};
unsigned char *lpSrc;
// 计算各个灰度值的计数,即得到直方图
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes*(lHeight-1-i) + j*3;//down -up
RGB Rgb;
HSI Hsi;
Rgb.b=*lpSrc;Rgb.g=*(lpSrc+1);Rgb.r=*(lpSrc+2);
RgbtoHsi(&Rgb, &Hsi);
unsigned int H,S,I;
H=(unsigned int) (Hsi.Hue/360.0*255.0);
S=(unsigned int) (Hsi.Saturation*255.0);
I=(unsigned int) (Hsi.Intensity*255.0);
// 计数加1
m_nHistHSI[H]++;//H
m_nHistHSI[256+S]++;//S
m_nHistHSI[256*2+I]++;//I
}
DisplayDlg dlg;
dlg.pData=&m_nHistHSI[0];
dlg.m_Sizex=256;
dlg.m_Title="彩色HSI直方图";
dlg.m_Level=3;//draw number
dlg.m_LinePos=0;
dlg.DoModal();
}
void CImageProcessView::OnUpdateHistgramHsi(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==24)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnPreprocessGray()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
// 更改光标形状
BeginWaitCursor();
// 获取指向BITMAPINFO结构的指针(Win3.0)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8 ){
//8bit to Gray
// 灰度映射表
BYTE bMap[256];
// 计算灰度映射表(保存各个颜色的灰度值),并更新DIB调色板
LPRGBQUAD pDibQuad = (LPRGBQUAD) pDoc->m_pDib->m_lpvColorTable;
for (int i = 0; i < 256; i ++)
{
// 计算该颜色对应的灰度值
bMap[i] = (BYTE)(0.299 * pDibQuad->rgbRed +
0.587 * pDibQuad->rgbGreen +
0.114 * pDibQuad->rgbBlue + 0.5);
// 更新DIB调色板红色分量
pDibQuad->rgbRed = (BYTE)i;
// 更新DIB调色板绿色分量
pDibQuad->rgbGreen =(BYTE)i;
// 更新DIB调色板蓝色分量
pDibQuad->rgbBlue = (BYTE)i;
// 更新DIB调色板保留位
pDibQuad->rgbReserved = 0;
pDibQuad++;
}
// 更换每个象素的颜色索引(即按照灰度映射表换成灰度值)
// 每行
unsigned char *lpSrc;
for(int i = 0; i < lHeight; i++)
{
// 每列
for(int j = 0; j < lWidth; j++)
{
// 指向DIB第i行,第j个象素的指针
lpSrc = pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i) + j;
*lpSrc=bMap[*lpSrc];
}
}
}
else if(pDoc->m_pDib->m_lpBMIH->biBitCount>=24){
//24bit to gray image
unsigned char* lpSrc;
// 指向转置图像对应象素的指针
unsigned char* lpDst;
lLineBytes =(lWidth *pDoc->m_pDib->m_lpBMIH->biBitCount/8+3)/4*4;
long int lNewLineBytes=(lWidth +3)/4*4;
// 指向转置图像的指针
unsigned char* lpNewDIBBits;
// 暂时分配内存,以保存新图像
lpNewDIBBits=new unsigned char [lHeight * lNewLineBytes];
memset(lpNewDIBBits,0,lHeight * lNewLineBytes);
// 判断是否内存分配失败
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
// 针对图像每行进行操作
for(int i = 0; i < lHeight; i++)
{
// 针对每行图像每列进行操作
for(int j = 0; j < lWidth; j++)
{
// 指向源DIB第i行,第j个象素的指针
lpSrc =pDoc->m_pDib->m_lpImage + lLineBytes*(lHeight - 1 - i) + j*pDoc->m_pDib->m_lpBMIH->biBitCount/8;
lpDst =lpNewDIBBits + lNewLineBytes * (lHeight - 1 - i) + j;
// 复制象素
double v;
v=0.299*(*lpSrc)+0.587*(*(lpSrc+1))+0.114*(*(lpSrc+2));//bgr
*lpDst=(unsigned char)v;//GBR?
}
}
lLineBytes=lNewLineBytes;
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"--Color");
DisplayNewImg(lpNewDIBBits,lLineBytes,lHeight,str+"Gray");
delete []lpNewDIBBits;
}
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdatePreprocessGray(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount>=24)
bAvail=true;
else if(pDoc->m_pDib->m_lpBMIH->biBitCount==8){//it's gray image?
LPRGBQUAD pDibQuad = (LPRGBQUAD) pDoc->m_pDib->m_lpvColorTable;
bAvail=false;
for (int i = 0; i < 256; i ++)
{
if((pDibQuad->rgbRed != pDibQuad->rgbGreen) || (pDibQuad->rgbRed !=pDibQuad->rgbBlue)
|| (pDibQuad->rgbGreen !=pDibQuad->rgbBlue) || (pDibQuad->rgbRed != i))
{
bAvail=true;
break;
}
pDibQuad++;
}
}
pCmdUI->Enable(bAvail);
}
void CImageProcessView::DisplayNewImg(unsigned char* lpNewImg,int Lines,int Height,CString strTitle,bool bColor)
{
CImageProcessDoc* pDoc = GetDocument();
//建立一个新视图,显示分割结果
CMainFrame* pFrame = (CMainFrame *)(AfxGetApp()->m_pMainWnd);
//发送新建文件的消息,创建一个新的文档-视图
pFrame->SendMessage(WM_COMMAND, ID_FILE_NEW);
pFrame->SendMessage(WM_COMMAND, ID_WINDOW_CASCADE);
//获取新建视图指针
CImageProcessView* pView=(CImageProcessView*)pFrame->MDIGetActive()->GetActiveView();
//获取相关联的新的文档类指针
CImageProcessDoc* pDocNew=pView->GetDocument();
delete pDocNew->m_pDib;
if(bColor==false){
pDocNew->m_pDib =new CDib(CSize(Lines,Height ) ,8);
unsigned char * lpSrc;
lpSrc=(unsigned char*)pDocNew->m_pDib->m_lpvColorTable;
for(int i=0;i<256;i++){
*lpSrc=(unsigned char)i;lpSrc++;
*lpSrc=(unsigned char)i;lpSrc++;
*lpSrc=(unsigned char)i;lpSrc++;
*lpSrc=0;lpSrc++;
}
memcpy(pDocNew->m_pDib->m_lpImage, lpNewImg, Lines * Height);
}
else{
pDocNew->m_pDib =new CDib(CSize(Lines,Height ) ,24);
memcpy(pDocNew->m_pDib->m_lpImage, lpNewImg, (Lines*3) * Height);
}
pDocNew->SetTitle(strTitle);
//display select Area
pDocNew->StartPoint=pDoc->StartPoint;
pDocNew->EndPoint=pDoc->EndPoint;
}
// 编码表含义
//******************************************
//COLOR_SCALE_COUNT=
// " 0 常规灰度编码",
// " 1 逆灰度编码",
// " 2 红色饱和度编码",
// " 3 绿色饱和度编码",
// " 4 蓝色饱和度编码",
// " 5 黄色饱和度编码",
// " 6 青色饱和度编码",
// " 7 紫色饱和度编码",
// " 8 彩虹编码 1",
// " 9 彩虹编码 2",
// " 10 热金属编码 1",
// " 11 热金属编码 2",
//*******************************************
void CImageProcessView::OnPreprocessPsdeocolordisplay()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
// 更改光标形状
BeginWaitCursor();
CString str=pDoc->GetTitle();
DisplayNewImg(pDoc->m_pDib->m_lpImage,lLineBytes,lHeight,str+"Gray");
const int CHARACT= 11;
LPRGBQUAD pDibQuad = (LPRGBQUAD) pDoc->m_pDib->m_lpvColorTable;
for (int i = 0; i < 256; i ++)
{
// 更新DIB调色板蓝色分量
pDibQuad->rgbBlue = ColorsTable[CHARACT][i][0];
// 更新DIB调色板红色分量
pDibQuad->rgbRed = ColorsTable[CHARACT][i][1];
// 更新DIB调色板绿色分量
pDibQuad->rgbGreen =ColorsTable[CHARACT][i][2];
pDibQuad++;
}
//draw display table
//color bar in bottom
unsigned char* lpSrc;
for (int i =0; i <20; i ++)
{ lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* i -1;
for (int j =0; j <lWidth; j ++)
{
lpSrc++;
*lpSrc=(BYTE)(j*256/lWidth);
}
}
pDoc->SetTitle(str+"--PsdeoColor");
// 更新视图
Invalidate(true);
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdatePreprocessPsdeocolordisplay(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8){//it's gray image?
LPRGBQUAD pDibQuad = (LPRGBQUAD) pDoc->m_pDib->m_lpvColorTable;
bAvail=true;
for (int i = 0; i < 256; i ++)
{
if((pDibQuad->rgbRed != pDibQuad->rgbGreen) || (pDibQuad->rgbRed !=pDibQuad->rgbBlue)
|| (pDibQuad->rgbGreen !=pDibQuad->rgbBlue))
{
bAvail=false;
break;
}
pDibQuad++;
}
}
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnPreprocessNegativeimage()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
// 更改光标形状
BeginWaitCursor();
CString str=pDoc->GetTitle();
DisplayNewImg(pDoc->m_pDib->m_lpImage,lLineBytes,lHeight,str);
unsigned char *lpSrc;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{ lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) +pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
{
if(!m_bTwoValue)
*lpSrc=255-*lpSrc;
else *lpSrc=TWOVALUE_H-*lpSrc;
lpSrc++;
}
}
pDoc->SetTitle(str+"--Negative");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
}
void CImageProcessView::OnUpdatePreprocessNegativeimage(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnHistgramEqualizer()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
int Hist[256]={0};
GetHistgram(Hist,false);
for(int k=1;k<256;k++) Hist[k]+=Hist[k-1];
//计算对应的灰度值
int Num=pDoc->EndPoint.y-pDoc->StartPoint.y+1;
Num*=(pDoc->EndPoint.x-pDoc->StartPoint.x+1);
for(int k=0;k<256;k++) Hist[k]=Hist[k]*255/Num;//look table
method1 Histogram equalization变换
//unsigned char *lpSrc;
//for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
//{ lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x;
//for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
//{
// *lpSrc=(unsigned char)(Hist[*lpSrc]);
// lpSrc++;
//}
//}
//method2 change lut table
LPRGBQUAD pDibQuad = (LPRGBQUAD) pDoc->m_pDib->m_lpvColorTable;
for (int i = 0; i < 256; i ++)
{
int v=Hist[i];
pDibQuad->rgbBlue = (BYTE)v;
pDibQuad->rgbRed =(BYTE)v;
pDibQuad->rgbGreen =(BYTE)v;
pDibQuad++;
}
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"--直方图均衡化");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
}
void CImageProcessView::OnUpdateHistgramEqualizer(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnHistgramRobustnormalization()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
int Hist[256]={0};
GetHistgram(Hist,false);
for(int k=1;k<256;k++) Hist[k]+=Hist[k-1];
const double Th1=0.2;
const double Th2=0.8;
int g_min=0;
int g_max=255;
int size=(pDoc->EndPoint.x-pDoc->StartPoint.x+1)*(pDoc->EndPoint.y-pDoc->StartPoint.y+1);
while(Hist[g_min]<(int)(size*Th1))
g_min++;
while(Hist[g_max]>(int)(size*Th2))
g_max--;
g_min=min(g_min,100);
g_max=min(max(g_max,128),220);
double a=255.0/(g_max-g_min);
double b=-a*g_min;
//change lut table
LPRGBQUAD pDibQuad = (LPRGBQUAD) pDoc->m_pDib->m_lpvColorTable;
for (int i = 0; i < 256; i ++)
{
int v=min(max((int)(a*i+b+0.5),0),255);
pDibQuad->rgbBlue = (BYTE)v;
pDibQuad->rgbRed =(BYTE)v;
pDibQuad->rgbGreen =(BYTE)v;
pDibQuad++;
}
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"--直方图归一化");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
}
void CImageProcessView::OnUpdateHistgramRobustnormalization(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnGammBright()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
const double r=.2;
LPRGBQUAD pDibQuad = (LPRGBQUAD) pDoc->m_pDib->m_lpvColorTable;
for (int i = 0; i < 256; i ++)
{
//double tmp=(i+1)/256.0;//only one times
double tmp=(pDibQuad->rgbBlue+1)/256.0;//can do it again
if(tmp<0.9999)
tmp=exp(r*log(tmp));
int v=(int)(tmp*256);
pDibQuad->rgbBlue = (BYTE)v;
pDibQuad->rgbRed =(BYTE)v;
pDibQuad->rgbGreen =(BYTE)v;
pDibQuad++;
}
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"--伽马校正(r<0)");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
}
void CImageProcessView::OnGammDark()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
const double r=2.0;
LPRGBQUAD pDibQuad = (LPRGBQUAD) pDoc->m_pDib->m_lpvColorTable;
for (int i = 0; i < 256; i ++)
{
//double tmp=(i+1)/256.0;//only one times
double tmp=(pDibQuad->rgbBlue+1)/256.0;//can do it again
if(tmp<0.9999)
tmp=exp(r*log(tmp));
int v=(int)(tmp*256);
pDibQuad->rgbBlue = (BYTE)v;
pDibQuad->rgbRed =(BYTE)v;
pDibQuad->rgbGreen =(BYTE)v;
pDibQuad++;
}
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"--伽马校正(r>0)");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
}
void CImageProcessView::OnUpdateGammBright(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnUpdateGammDark(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnAddnoiseGuass()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
const double Mean=0;
const double Dev=20;
//Method1:
//1、获取概率分布
//2、求累积
double p[256];
p[0]=0.0;
for(int i=-127;i<128;i++)
p[i+128]=p[i+128-1]+(double)(exp(double(-(i-Mean)*(i-Mean)/(2*Dev*Dev)))/(Dev*sqrt(2.0*Pi)));
srand( (unsigned)time( NULL ) );
double N=0.0;
double S=0.0;
unsigned char* lpSrc;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) +pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
//3、获取均匀分布值
double q=(double)rand();
q/=RAND_MAX;
//4、获取对应值
int k;
for(k=0;k<256;k++)//q==p[k]
if(q<=p[k])break;
int v;
//5、添加噪声
v=((int)*lpSrc)+128-k;//
if(v<0) v=0;
else if(v>255) v=255;
S+=v*v;//定义如此: not ((*lpSrc)*(*lpSrc));
N+=((v-*lpSrc)*(v-*lpSrc));
*lpSrc=(unsigned char)v;
lpSrc++;
}
}
Method2:
//
//srand( (unsigned)time( NULL ) );
//double N=0.0;
//double S=0.0;
//unsigned char* lpSrc;
//for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
// lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) +pDoc->StartPoint.x;
// for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x-1; j +=2){
//
// //1、获取均匀分布值
// double q=(double)rand();
// double r=q/RAND_MAX;
//
// q=(double)rand();
// double theta=q/RAND_MAX;
//
// //3、获取对应值
// double z1=Dev*cos(2*Pi*theta)*sqrt(-2*log(r));//log10
// double z2=Dev*sin(2*Pi*theta)*sqrt(-2*log(r));
//
// //4、添加噪声
//
// int v=((int)*lpSrc)+(int)z1;//
// if(v<0) v=0;
// else if(v>255) v=255;
//
// S+=(v*v);N+=((v-*lpSrc)*(v-*lpSrc));
// *lpSrc=(unsigned char)v;
//
// lpSrc++;
//
// v=((int)*lpSrc)+(int)z2;//
// if(v<0) v=0;
// else if(v>255) v=255;
//
// S+=(v*v);N+=((v-*lpSrc)*(v-*lpSrc));
// *lpSrc=(unsigned char)v;
// lpSrc++;
//
//
// }
//}
CString str=pDoc->GetTitle();
CString str1;
str1.Format("--+高斯噪声(SNR:%3.1f)",S/N);
str+=str1;
pDoc->SetTitle(str);
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
}
void CImageProcessView::OnAddnoiseSaltpepper()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
srand( (unsigned)time( NULL ) );
double N=0.0;
double S=0.0;
unsigned char* lpSrc;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) +pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
float dtmp= (float)rand();
dtmp/=RAND_MAX;
double v=*lpSrc;
if(dtmp<0.1) //10%
{
if(rand()%2) *lpSrc = 0;
else *lpSrc = 255;
}
S+=((*lpSrc) * (*lpSrc));N+=((v-*lpSrc)*(v-*lpSrc));
lpSrc++;
}
}
CString str=pDoc->GetTitle();
CString str1;
str1.Format("--+椒盐噪声(SNR:%3.1f)",S/N);
str+=str1;
pDoc->SetTitle(str);
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
}
void CImageProcessView::OnUpdateAddnoiseGuass(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnUpdateAddnoiseSaltpepper(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnHistgramLocal()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
BeginWaitCursor();
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
//获得直方图
int Hist[256]={0};
GetHistgram(Hist,false);
//get mean,segma
double Mean=0;
for (int i = 0; i < 256;i++)
{
Mean+=(i*Hist[i]);
}
Mean=Mean/(pDoc->EndPoint.x-pDoc->StartPoint.x+1)/(pDoc->EndPoint.y-pDoc->StartPoint.y+1);
double Segma=0;
for (int i = 0; i < 256;i++)
{
Segma+=((i-Mean)*(i-Mean)*Hist[i]);
}
Segma=sqrt(Segma/(pDoc->EndPoint.x-pDoc->StartPoint.x+1)/(pDoc->EndPoint.y-pDoc->StartPoint.y+1));
double E=4.0,k0=0.4,k1=0.02,k2=0.4;
int M=3,N=3;
double mean,segma;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst = lpNewDIBBits + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
if(i>M/2 && i<lHeight-1-M/2 && j>M/2 && j<lWidth-1-M/2){
//Get M*N mean
mean=0.0;
for(int m=-M/2;m<=M/2;m++)
for(int n=-N/2;n<=N/2;n++)
mean+=*(lpSrc+ lLineBytes* m+n);
mean/=(M*N);
if(mean<k0*Mean){
segma=0.0;
for(int m=-M/2;m<=M/2;m++)
for(int n=-N/2;n<=N/2;n++)
segma+=((*(lpSrc+ lLineBytes* m+n)-mean)*
(*(lpSrc+ lLineBytes*m+n)-mean));
segma=sqrt(segma/(M*N));
double dtmp;
if(segma>=k1*Segma && segma<=k2*Segma)
{
dtmp=E*(*lpSrc);
if(dtmp>255) dtmp=255;
*lpDst=(unsigned char)dtmp;//
}
}
}
}
}
CString str=pDoc->GetTitle();
DisplayNewImg(lpNewDIBBits,lLineBytes,lHeight,str+"局部增强");
// 恢复光标
EndWaitCursor();
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdateHistgramLocal(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnPreprocessLaplacesharpen()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
BeginWaitCursor();
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
int pixel[8];
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
if(i>0 && i<lHeight-1 && j>0 && j<lWidth-1){
pixel[0] = (int)*(lpSrc+lLineBytes-1);
pixel[1] = (int)*(lpSrc+lLineBytes);
pixel[2] = (int)*(lpSrc+lLineBytes+1);
pixel[3] = (int)*(lpSrc+1);
pixel[4] = (int)*(lpSrc - lLineBytes+1);
pixel[5] = (int)*(lpSrc - lLineBytes);
pixel[6] = (int)*(lpSrc - lLineBytes-1);
pixel[7] = (int)*(lpSrc-1);
int Tmp=0;
for(int k=0;k<8;k++)
Tmp+=pixel[k];
Tmp-=8*((int)*lpSrc);
if(Tmp>0) Tmp=*lpSrc+Tmp;
else Tmp=*lpSrc-Tmp;
if(Tmp>255) Tmp=255;
*lpDst=(unsigned char)Tmp;
}
}
}
CString str=pDoc->GetTitle();
DisplayNewImg(lpNewDIBBits,lLineBytes,lHeight,str+"Laplace 锐化");
// 恢复光标
EndWaitCursor();
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdatePreprocessLaplacesharpen(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnSmoothMeanfilter()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
//copy img
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
return ;
memcpy( lpNewDIBBits,pDoc->m_pDib->m_lpImage, lLineBytes * lHeight);
const int M=5;//odd
const int N=5;//odd
MeanFilter(M,N);
CString str=pDoc->GetTitle();
DisplayNewImg(pDoc->m_pDib->m_lpImage,lLineBytes,lHeight,str+"--+均值滤波");//display orignal image
//get img back
pDoc->SetTitle(str);
memcpy( pDoc->m_pDib->m_lpImage,lpNewDIBBits, lLineBytes * lHeight);
delete []lpNewDIBBits;
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdateSmoothMeanfilter(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//不计算图像边界(选择的区域边界要计算!)
//利用两次卷积合成,递归完成卷积
void CImageProcessView::MeanFilter(int M,int N)
{
CImageProcessDoc* pDoc = GetDocument();
int* lpNewDIBBits;
lpNewDIBBits=new int [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
unsigned char* lpSrc;
int* lpDst;
int v;
int half_M=M/2;
int half_N=N/2;
//若选择区域,顶、低部需要多算几行
for (int i = max(pDoc->StartPoint.y-half_N,0); i <=min(pDoc->EndPoint.y+half_N,lHeight-1); i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) +max(pDoc->StartPoint.x,half_M);//get first point
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+max(pDoc->StartPoint.x,half_M);
v=0;
for(int k=-half_M;k<=half_M;k++){//add
v+=*(lpSrc+k);
}
*lpDst=v;
for (int j =max(pDoc->StartPoint.x,half_M)+1; j <min(pDoc->EndPoint.x,lWidth-half_M); j ++){
lpSrc++;
lpDst++;
v+=(*(lpSrc+half_M)-*(lpSrc-half_M-1));
*lpDst=v;
}
}
int size=M*N;
for (int j =max(pDoc->StartPoint.x,half_M); j <min(pDoc->EndPoint.x,lWidth-half_M); j ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-max(pDoc->StartPoint.y,half_N)) + j;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - max(pDoc->StartPoint.y,half_N))+ j;
v=0;
for(int k=-half_N;k<=half_N;k++)
v+=*(lpDst+k*lLineBytes);
*lpSrc=(BYTE)(v/size);
for (int i = max(pDoc->StartPoint.y,half_N)+1; i <min(pDoc->EndPoint.y,lHeight-half_N); i ++){
lpDst-=lLineBytes;
v+=(*(lpDst-(half_N)*lLineBytes)-*(lpDst+(half_N+1)*lLineBytes));
lpSrc-=lLineBytes;
*lpSrc=(BYTE)(v/size);
}
}
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnSmoothGaussfilter()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
//copy img
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
return ;
memcpy( lpNewDIBBits,pDoc->m_pDib->m_lpImage, lLineBytes * lHeight);
const int M=7;//odd
const int N=7;//odd
const double Sigma=1.414;
GaussFilter(M,N,Sigma);
CString str=pDoc->GetTitle();
DisplayNewImg(pDoc->m_pDib->m_lpImage,lLineBytes,lHeight,str+"--+高斯滤波");//display orignal image
//get img back
pDoc->SetTitle(str);
memcpy( pDoc->m_pDib->m_lpImage,lpNewDIBBits, lLineBytes * lHeight);
delete []lpNewDIBBits;
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdateSmoothGaussfilter(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//利用两次卷积合成,M!=N 模板计算(方差也不同?不考虑)
void CImageProcessView::GaussFilter(int M,int N,double Sigma)
{
CImageProcessDoc* pDoc = GetDocument();
int* lpNewDIBBits;
lpNewDIBBits=new int [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
unsigned char* lpSrc;
int* lpDst;
int* model;
if(Sigma<0.3) Sigma=0.3;
if(M<3) M=3;
if(N<3) N=3;
N=M;
model=new int [M];
int half_M=M/2;
int half_N=N/2;
for(int i=-half_M;i<=half_M;i++){
double G=exp(-(i*i)/(2.0*Sigma*Sigma))/ (sqrt(2 * Pi) * Sigma);
model[i+half_M]=(int)(G*100+0.5);
}
int num=0;
for(int i=0;i<M;i++)
num+=model[i];
num*=num;
for (int i = max(pDoc->StartPoint.y-half_N,0); i <=min(pDoc->EndPoint.y+half_N,lHeight-1); i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) +max(pDoc->StartPoint.x,half_M);//get first point
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+max(pDoc->StartPoint.x,half_M);
for (int j =max(pDoc->StartPoint.x,half_M); j <min(pDoc->EndPoint.x,lWidth-half_M); j ++){
int v=0;
for(int k=-half_M;k<=half_M;k++){//add
v+=(*(lpSrc+k)*model[k+half_M]);
}
*lpDst=v;
lpSrc++;
lpDst++;
}
}
for (int j =max(pDoc->StartPoint.x,half_M); j <min(pDoc->EndPoint.x,lWidth-half_M); j ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-max(pDoc->StartPoint.y,half_N)) + j;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - max(pDoc->StartPoint.y,half_N))+ j;
for (int i = max(pDoc->StartPoint.y,half_N); i <min(pDoc->EndPoint.y,lHeight-half_N); i ++){
int v=0;
for(int k=-half_N;k<=half_N;k++)
v+=(*(lpDst+k*lLineBytes)*model[k+half_N]);
*lpSrc=(BYTE)(v/num);
lpDst-=lLineBytes;
lpSrc-=lLineBytes;
}
}
// 释放内存
delete []lpNewDIBBits;
delete []model;
}
void CImageProcessView::GaussFilter(double* pData,int M,int N,double Sigma)
{
CImageProcessDoc* pDoc = GetDocument();
double* lpNewDIBBits;
lpNewDIBBits=new double [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
memcpy(lpNewDIBBits,pData,lLineBytes*lHeight*sizeof(double));
double* lpSrc;
double* lpDst;
double* model;
if(Sigma<0.3) Sigma=0.3;
if(M<3) M=3;
if(N<3) N=3;
N=M;
model=new double [M];
int half_M=M/2;
int half_N=N/2;
for(int i=-half_M;i<=half_M;i++){
double G=exp(-(i*i)/(2.0*Sigma*Sigma))/ (sqrt(2 * Pi) * Sigma);
model[i+half_M]=G;
}
for (int i = max(pDoc->StartPoint.y-half_N,0); i <=min(pDoc->EndPoint.y+half_N,lHeight-1); i ++){
lpSrc =pData + lLineBytes* (lHeight-1-i) +max(pDoc->StartPoint.x,half_M);//get first point
lpDst =lpNewDIBBits+ lLineBytes * (lHeight - 1 - i)+max(pDoc->StartPoint.x,half_M);
for (int j =max(pDoc->StartPoint.x,half_M); j <min(pDoc->EndPoint.x,lWidth-half_M); j ++){
double v=0;
for(int k=-half_M;k<=half_M;k++){//add
v+=(*(lpSrc+k)*model[k+half_M]);
}
*lpDst=v;
lpSrc++;
lpDst++;
}
}
for (int j =max(pDoc->StartPoint.x,half_M); j <min(pDoc->EndPoint.x,lWidth-half_M); j ++){
lpSrc = pData + lLineBytes* (lHeight-1-max(pDoc->StartPoint.y,half_N)) + j;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - max(pDoc->StartPoint.y,half_N))+ j;
for (int i = max(pDoc->StartPoint.y,half_N); i <min(pDoc->EndPoint.y,lHeight-half_N); i ++){
double v=0;
for(int k=-half_N;k<=half_N;k++)
v+=(*(lpDst+k*lLineBytes)*model[k+half_N]);
*lpSrc=v;
lpDst-=lLineBytes;
lpSrc-=lLineBytes;
}
}
// 释放内存
delete []lpNewDIBBits;
delete []model;
}
void CImageProcessView::OnSmoothMedianfilter()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
//copy img
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
return ;
memcpy( lpNewDIBBits,pDoc->m_pDib->m_lpImage, lLineBytes * lHeight);
CDemoTimer exeTimer;
exeTimer.Reset();
const int M=3;//odd
const int N=3;//odd
MedianFilter(M,N);
TRACE("\nUsed Time is %.3f ms\n",exeTimer.GetTime(false)*1000);
CString str=pDoc->GetTitle();
DisplayNewImg(pDoc->m_pDib->m_lpImage,lLineBytes,lHeight,str+"--+中值滤波");//display orignal image
//get img back
pDoc->SetTitle(str);
memcpy( pDoc->m_pDib->m_lpImage,lpNewDIBBits, lLineBytes * lHeight);
delete []lpNewDIBBits;
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdateSmoothMedianfilter(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::MedianFilter(int M,int N)
{
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
unsigned char* lpSrc;
unsigned char* lpDst;
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
//unsigned char *v=new unsigned char[M*N];//[N*M];//line N Column M not rect (int err)
vector<unsigned char> v(M*N,0);
const int Th=(M*N)/2;//Mid Pos
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;
lpDst++;
if(i>=M/2 && i<lHeight-M/2 && j>=N/2 && j<lWidth-N/2){
//Get M*N data to v[]
int vSize=0;
for(int m=-M/2;m<=M/2;m++)
for(int n=-N/2;n<=N/2;n++)
{ v[vSize]=*(lpSrc+lLineBytes*m+n);
vSize++;}
//sort v[]
for(int m=0;m<M*N-1;m++)
for(int n=m+1;n<M*N;n++)
{
if(v[m]>v[n]){
//swap
BYTE tmp=v[m];
v[m]=v[n];
v[n]=tmp;
}
}
*(lpDst)=(unsigned char)v[Th];
}
}
}
// 释放内存
delete []lpNewDIBBits;
//delete []v;
}
//邻域内求与其它点距离最短的色点替代该点
void CImageProcessView::OnSmoothColorfilter()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
// 更改光标形状
BeginWaitCursor();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lHeight * lLineBytes];
if (lpNewDIBBits == NULL)
return ;
memcpy(lpNewDIBBits,pDoc->m_pDib->m_lpImage,lHeight * lLineBytes);
// 针对图像每行进行操作
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
// 指向源DIB第i行,第j个象素的指针
lpSrc =lpNewDIBBits + lLineBytes*(lHeight-1-i)+ j*3;
double d;
double mind=10000;
int mm=0;
int mn=0;
for(int m=-1;m<=1;m++)
for(int n=-1;n<=1;n++)
{
d=0.0;
unsigned char* lpDst1=lpSrc+lLineBytes*n+m*3;
for(int s=-1;s<=1;s++)
for(int t=-1;t<=1;t++)
{ unsigned char* lpDst2=lpSrc+lLineBytes*t+s*3;
double dtmp=(double)((*(lpDst1)-*(lpDst2))*(*(lpDst1)-*(lpDst2))+//^ is't Pow(x,y)
(*(lpDst1+1)-*(lpDst2+1))*(*(lpDst1+1)-*(lpDst2+1))+
(*(lpDst1+2)-*(lpDst2+2))*(*(lpDst1+2)-*(lpDst2+2)));
d+=sqrt(dtmp);
}
if(d<mind){
mind=d;
mm=m;mn=n;
}
}
lpSrc=lpSrc+ lLineBytes*mn+ mm*3;
lpDst =pDoc->m_pDib->m_lpImage+ lLineBytes *(lHeight-1-i) + j*3;
*lpDst=*lpSrc;*(lpDst+1)=*(lpSrc+1);*(lpDst+2)=*(lpSrc+2);
}
}
DisplayNewImg(lpNewDIBBits,(lWidth+3)/4*4,lHeight,"原图",true);//display orignal image
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"--Color Filtering");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
delete []lpNewDIBBits;
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdateSmoothColorfilter(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==24)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnFrequencydomainFft()
{
// TODO: Add your command handler code here
//CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CPoint wh=FrequencydomainSelectarea();
int w=wh.x;
int h=wh.y;
// 分配内存
complex<double> *TD = new complex<double>[w * h];
complex<double> *FD = new complex<double>[w * h];
TD[0]=complex<double>(1.0,2.0);;
DoFFT( TD, FD, w,h);
DisplayFw(FD,w, h,0.6,"|F(u,v)|");
// 恢复光标
EndWaitCursor();
// 删除临时变量
delete []TD;
delete []FD;
}
void CImageProcessView::DisplayFw(complex<double> * FD, int w, int h,double c,CString title)
{
//显示 F(jw)
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [w*h];
unsigned char* lpSrc;
if (lpNewDIBBits == NULL)
return ;
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
// 计算频谱
double dTemp =c*log(1+ sqrt((double)FD[i *w + j].real() * FD[i *w + j].real() +
FD[i *w + j].imag() * FD[i *w + j].imag()));// c ln(1+r)
dTemp=exp(dTemp*log(2.0));//log | log10
if(dTemp>255)
dTemp=255;
//freq
lpSrc = lpNewDIBBits + w * (h - 1 - i) + j;
* (lpSrc) = (BYTE)(dTemp);
}
}
DisplayNewImg(lpNewDIBBits,w,h,title);
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdateFrequencydomainFft(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
CPoint CImageProcessView::FrequencydomainSelectarea(){
//获取付立叶变换的宽度和高度(2的整数次方)
CImageProcessDoc* pDoc = GetDocument();
int w;
int h;
int wp=int(log((double) pDoc->EndPoint.x-pDoc->StartPoint.x+1)/log(2.0));
int hp=int(log((double) pDoc->EndPoint.y-pDoc->StartPoint.y+1)/log(2.0));
w=(int)pow(2.0,wp);
h=(int)pow(2.0,hp);
if((pDoc->EndPoint.x-pDoc->StartPoint.x+1==lWidth) && (pDoc->EndPoint.y-pDoc->StartPoint.y+1==lHeight))
{ //整幅图像处理
if(w<lWidth) w*=2;//add 0
if(h<lHeight) h*=2;
}
else{
if(w<256 && w<(pDoc->EndPoint.x-pDoc->StartPoint.x+1)){
w *= 2;
}
if(h<256 && h<(pDoc->EndPoint.y-pDoc->StartPoint.y+1)){
h *= 2;
}
//若非取全区域,修正区域使满足w、h整数次方
int dy=(pDoc->EndPoint.y-pDoc->StartPoint.y+1-h)/2-1;
pDoc->StartPoint.y+=dy;
if(pDoc->StartPoint.y<0) pDoc->StartPoint.y=0;
pDoc->EndPoint.y=pDoc->StartPoint.y+h-1;
int dx=(pDoc->EndPoint.x-pDoc->StartPoint.x+1-w)/2;
pDoc->StartPoint.x+=dx;
//若不在区域内,补0
if(pDoc->StartPoint.x<0) pDoc->StartPoint.x=0;
pDoc->EndPoint.x=pDoc->StartPoint.x+w-1;
if(pDoc->EndPoint.x>lWidth-1){
pDoc->EndPoint.x=lWidth-1;
pDoc->StartPoint.x=max(0,lWidth-1-w);
}
if(pDoc->EndPoint.y>lHeight-1){
pDoc->EndPoint.y=lHeight-1;
pDoc->StartPoint.y=max(0,lHeight-1-h);
}
}
//display select area change
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
return(CPoint(w,h));
}
void CImageProcessView::DoFFT(complex<double> * TD, complex<double> * FD, int w, int h)
{
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
// 行
for(int i = 0; i < h; i++)
{
// 列
for(int j = 0; j < w; j++)
{
// 指向DIB第i行,第j个象素的指针
if(i+pDoc->StartPoint.y<lHeight && pDoc->StartPoint.x+j<lWidth)
{
lpSrc = (unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i-pDoc->StartPoint.y) + pDoc->StartPoint.x+j;
// 给时域赋值
TD[j + w * i] = complex<double>(*(lpSrc), 0);//w*h
}else{
TD[j + w * i] = complex<double>(0,0);
}
}
}
FFT2(TD,FD, w, h);
}
void CImageProcessView::FFT2(complex<double> * TD, complex<double> * FD, int w,int h)
{
int wp=int(log((double) w)/log(2.0));
int hp=int(log((double) h)/log(2.0));
//1: move to center
for(int y=0; y<h; y++)
for(int x=0; x<w; x++)
if((x+y)%2) TD[y*w + x]=-TD[y*w + x];
//2:FFT
for(int i = 0; i < h; i++)
{
// 对y方向进行快速付立叶变换
FFT(&TD[w * i], &FD[w * i], wp);//w
}
// 保存变换结果
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
TD[i + h * j] = FD[j + w * i];//转置
}
}
for(int i = 0; i < w; i++)
{
// 对x方向进行快速付立叶变换
FFT(&TD[i * h], &FD[i * h], hp);//h
}
//再转置还原
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
TD[j + w * i] = FD[i + h * j];//转置
}
}
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
FD[j + w * i] = TD[j + w * i];
}
}
//FD=TD; err!!
}
void CImageProcessView::FFT(complex<double> * TD, complex<double> * FD, int r)
{
// 付立叶变换点数
LONG count;
const double PI=3.14159;
// 中间变量
int bfsize,p;
// 角度
double angle;
complex<double> *W,*X1,*X2,*X;
// 计算付立叶变换点数
count = 1 << r;
// 分配运算所需存储器
W = new complex<double>[count / 2];
X1 = new complex<double>[count];
X2 = new complex<double>[count];
// 计算加权系数
for(int i = 0; i < count / 2; i++)
{
angle = -i * PI * 2 / count;
W[i] = complex<double> (cos(angle), sin(angle));
}
// 将时域点写入X1
memcpy(X1, TD, sizeof(complex<double>) * count);
// 采用蝶形算法进行快速付立叶变换
for(int k = 0; k < r; k++)
{
for(int j = 0; j < 1 << k; j++)
{
bfsize = 1 << (r-k);
for(int i = 0; i < bfsize / 2; i++)
{
p = j * bfsize;
X2[i + p] = X1[i + p] + X1[i + p + bfsize / 2];
X2[i + p + bfsize / 2] = (X1[i + p] - X1[i + p + bfsize / 2]) * W[i * (1<<k)];
}
}
X = X1;
X1 = X2;
X2 = X;
}
// 重新排序
for(int j = 0; j < count; j++)
{
p = 0;
for(int i = 0; i < r; i++)
{
if (j&(1<<i))
{
p+=1<<(r-i-1);
}
}
FD[j]=X1[p];
}
// 释放内存
delete [] W;
delete [] X1;
delete [] X2;
}
void CImageProcessView::IFFT(complex<double> * FD, complex<double> * TD, int r)
{// 付立叶变换点数
LONG count;
complex<double> *X;
// 计算付立叶变换点数
count = 1 << r;
// 分配运算所需存储器
X = new complex<double>[count];
// 将频域点写入X
memcpy(X, FD, sizeof(complex<double>) * count);
// 求共轭
for(int i = 0; i < count; i++)
{
X[i] = complex<double> (X[i].real(), -X[i].imag());
}
// 调用快速付立叶变换
FFT(X, TD, r);
// 求时域点的共轭
for(int i = 0; i < count; i++)
{
TD[i] = complex<double> (TD[i].real() / count, -TD[i].imag() / count);
}
// 释放内存
delete [] X;
}
void CImageProcessView::OnButterworthLowfilter()
{
// TODO: Add your command handler code here
//CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CPoint wh=FrequencydomainSelectarea();
int w=wh.x;
int h=wh.y;
// 分配内存
complex<double> *TD = new complex<double>[w * h];
complex<double> *FD = new complex<double>[w * h];
DoFFT( TD, FD, w,h);
//DisplayFw(FD,w, h,0.6,"|F(u,v)|");
//filter
const double D0=30;
for(int y=0; y<h; y++)
{
for(int x=0; x<w; x++)
{
double D = (double)((y-h/2)*(y-h/2)+(x-w/2)*(x-w/2)) ;
D = D / (D0 * D0);//(D/D0)^2
//ButterWorth低通滤波
double H = 1/(1+D*D);//n=2
FD[x + y*w]=complex<double>(FD[x + y*w].real()*H,FD[x + y*w].imag()*H);//h*w
}
}
//DisplayFw(FD,w, h,0.6,"|F(u,v)H(u,v)|");
DoIFFT( TD, FD, w,h,"ButtWorth低通",CPoint(0,0));
// 恢复光标
EndWaitCursor();
// 删除临时变量
delete [] TD;
delete [] FD;
}
void CImageProcessView::OnButterworthHighfilter()
{
// TODO: Add your command handler code here
//CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CPoint wh=FrequencydomainSelectarea();
int w=wh.x;
int h=wh.y;
// 分配内存
complex<double> *TD = new complex<double>[w * h];
complex<double> *FD = new complex<double>[w * h];
DoFFT( TD, FD, w,h);
//filter
const double D0=30;
for(int y=0; y<h; y++)
{
for(int x=0; x<w; x++)
{
double D = (double)((y-h/2)*(y-h/2)+(x-w/2)*(x-w/2)) ;
D = (D0 * D0)/D;//(D0/D)^2
if(D<0.00001) D=0.00001;
//ButterWorth高通滤波
double H = 1/(1+D*D);//n=2
FD[x + y*w]=complex<double>(FD[x + y*w].real()*H,FD[x + y*w].imag()*H);//h*w
}
}
DoIFFT( TD, FD, w,h,"ButtWorth低通",CPoint(0,0));
// 恢复光标
EndWaitCursor();
// 删除临时变量
delete [] TD;
delete [] FD;
}
void CImageProcessView::OnUpdateButterworthLowfilter(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnUpdateButterworthHighfilter(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::DoIFFT(complex<double>* TD, complex<double>* FD, int w, int h,CString title,CPoint startP)//del 0,0-startP-1
{
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
unsigned char* lpSrc;
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
int wp=int(log((double) w)/log(2.0));
int hp=int(log((double) h)/log(2.0));
for(int i = 0; i < h; i++)
{
// 对x方向进行快速付立叶变换
IFFT( &FD[i * w],&TD[i * w], wp);
}
// 保存变换结果
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
FD[i + h * j] = TD[j + w * i];//w*h
}
}
for(int i = 0; i < w; i++)
{
// 对y方向进行快速付立叶变换
IFFT(&FD[h * i],&TD[h * i],hp);
}
//TD hxw //转置
double dTemp;
double dmax=0.0;
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
dTemp=TD[j * h + i].real();
//move back
if((i+j)%2) dTemp=-dTemp;
if(dTemp>dmax) dmax=dTemp;
}
}
if(dmax<255) dmax=255;//no make bright
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
dTemp=TD[j * h + i].real();
//move back
if((i+j)%2) dTemp=-dTemp;
dTemp=dTemp/dmax*255.0;
if (dTemp<0)
dTemp=0;
if(j<lWidth-pDoc->StartPoint.x && i<lHeight-pDoc->StartPoint.y)
{
lpSrc =lpNewDIBBits + lLineBytes* (lHeight - 1 - i-pDoc->StartPoint.y) + j+pDoc->StartPoint.x;
// 更新源图像
if(j<startP.x || i<startP.y)
*(lpSrc) =0;//错误处置0
else
*(lpSrc) = (BYTE)(dTemp);
}
}
}
CString str=pDoc->GetTitle();
str+=title;
DisplayNewImg(lpNewDIBBits, lLineBytes,lHeight,str);
delete []lpNewDIBBits;
return ;
}
void CImageProcessView::OnFrequencydomainHomomorphicfilter()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
//copy img
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
return ;
memcpy( lpNewDIBBits,pDoc->m_pDib->m_lpImage, lLineBytes * lHeight);
//process
CPoint wh=FrequencydomainSelectarea();
int w=wh.x;
int h=wh.y;
// 分配内存
complex<double> *TD = new complex<double>[w * h];
complex<double> *FD = new complex<double>[w * h];
//1 lnf(x,y)
unsigned char* lpSrc;
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
if(i+pDoc->StartPoint.y<lHeight && pDoc->StartPoint.x+j<lWidth)
{
lpSrc = (unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i-pDoc->StartPoint.y) + pDoc->StartPoint.x+j;
// 给时域赋值
TD[j + w * i] = complex<double>(log((double)(max(*lpSrc,1))), 0);//w*h
}else{
TD[j + w * i] = complex<double>(0,0);
}
}
}
//2:FFT
//move to center
for(int y=0; y<h; y++)
for(int x=0; x<w; x++)
if((x+y)%2) TD[y*w + x]=-TD[y*w + x];
int wp=int(log((double) w)/log(2.0));
int hp=int(log((double) h)/log(2.0));
for(int i = 0; i < h; i++)
{
// 对y方向进行快速付立叶变换
FFT(&TD[w * i], &FD[w * i], wp);//w
}
// 保存变换结果
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
TD[i + h * j] = FD[j + w * i];//h*w
}
}
for(int i = 0; i < w; i++)
{
// 对x方向进行快速付立叶变换
FFT(&TD[i * h], &FD[i * h], hp);//h
}
//3. filter
const double D0=5;
const double rH=2.0;
const double rL=.5;
const double c=1.0;
for(int y=0; y<h; y++)
{
for(int x=0; x<w; x++)
{
double D = (double)((y-h/2)*(y-h/2)+(x-w/2)*(x-w/2)) ;
D = D/(D0 * D0);
double H =(rH-rL)*(1-exp(-c*D))+rL;
if(D==0.0) H=1.0;//get bright
FD[y + x*h]=complex<double>(FD[y + x*h].real()*H,FD[y + x*h].imag()*H);//h*w
}
}
//4.IFFT
for(int i = 0; i < w; i++)
{
// 对x方向进行快速付立叶变换
IFFT( &FD[i * h],&TD[i * h], hp);
}
// 保存变换结果
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
FD[j + w * i] = TD[i + h * j];//w*h
}
}
for(int i = 0; i < h; i++)
{
// 对y方向进行快速付立叶变换
IFFT(&FD[w * i],&TD[w * i],wp);
}
//5.exp
double dTemp;
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
dTemp=TD[i * w + j].real();
//move back
if((i+j)%2) dTemp=-dTemp;
dTemp=exp(dTemp);
if (dTemp > 255)
dTemp = 255;
if(j<lWidth-pDoc->StartPoint.x && i<lHeight-pDoc->StartPoint.y)
{
lpSrc =pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i-pDoc->StartPoint.y) + j+pDoc->StartPoint.x;
// 更新源图像
* (lpSrc) = (BYTE)dTemp;
}
}
}
CString str=pDoc->GetTitle();
DisplayNewImg(pDoc->m_pDib->m_lpImage,lLineBytes,lHeight,str+"--+同态滤波");//display orignal image
//get img back
pDoc->SetTitle(str);
memcpy( pDoc->m_pDib->m_lpImage,lpNewDIBBits, lLineBytes * lHeight);
delete [] lpNewDIBBits;
// 恢复光标
EndWaitCursor();
// 删除临时变量
delete [] TD;
delete [] FD;
}
void CImageProcessView::OnUpdateFrequencydomainHomomorphicfilter(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnFileGetmodal()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
m_ModelWidth=pDoc->EndPoint.x-pDoc->StartPoint.x+1;
m_ModelWidth=(m_ModelWidth+3)/4*4;
m_ModelHeight=pDoc->EndPoint.y- pDoc->StartPoint.y+1;
if(m_pModelData)
delete []m_pModelData;
m_pModelData=new unsigned char [m_ModelWidth*m_ModelHeight];
unsigned char* lpSrc;
unsigned char* lpDst;
lpDst=m_pModelData;;
for (int i = 0; i <m_ModelHeight; i ++)
{ lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i-pDoc->StartPoint.y) + pDoc->StartPoint.x-1;
for (int j =0; j <m_ModelWidth; j ++)
{
lpSrc++;
*lpDst=*lpSrc;
lpDst++;
}
}
//DisplayNewImg(m_pModelData,m_ModelWidth,m_ModelHeight,"Moda");
}
void CImageProcessView::OnUpdateFileGetmodal(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnSpatialdomainImage()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
BeginWaitCursor();
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
for (int i = pDoc->StartPoint.y; i <=min(pDoc->EndPoint.y,m_ModelHeight-1+pDoc->StartPoint.y); i ++){
lpSrc = lpNewDIBBits + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst = m_pModelData+ m_ModelWidth * (i-pDoc->StartPoint.y)-1;
for (int j =pDoc->StartPoint.x; j <=min(pDoc->EndPoint.x,m_ModelWidth-1+pDoc->StartPoint.x); j ++){
lpSrc++;lpDst++;
int Tmp=128+*(lpSrc)-*lpDst;
if(Tmp>255) Tmp=255;
else if(Tmp<0)Tmp=0;
*lpSrc=(unsigned char)Tmp;
}
}
CString str=pDoc->GetTitle();
DisplayNewImg(lpNewDIBBits,lLineBytes,lHeight,str+"-Moda");
// 恢复光标
EndWaitCursor();
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdateSpatialdomainImage(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
if(m_pModelData)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnConvolutionMean()
{
// TODO: Add your command handler code here
// CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CPoint wh=FrequencydomainSelectarea();
int w=wh.x;
int h=wh.y;
// 分配内存
complex<double> *TD = new complex<double>[w * h];
complex<double> *FD = new complex<double>[w * h];
DoFFT( TD, FD, w,h);
complex<double> *HTD = new complex<double>[w * h];
complex<double> *HFD = new complex<double>[w * h];
for(int i = 0; i < h; i++)
for(int j = 0; j < w; j++)
HTD[j + w * i]=0.0;
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
HTD[j + w * i]=1.0/9;
FFT2( HTD, HFD, w,h);
DisplayFw(HFD,w, h,20.0,"均值滤波|H(u,v)|");
//proc
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
FD[j + w * i]*=HFD[j + w * i];
}
}
DoIFFT( TD, FD, w,h,"频域均值滤波",CPoint(2,2));//0,1 err
// 恢复光标
EndWaitCursor();
// 删除临时变量
delete [] TD;
delete [] FD;
delete [] HTD;
delete [] HFD;
}
void CImageProcessView::OnUpdateConvolutionMean(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnConvolutionGauss()
{
// TODO: Add your command handler code here
// CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CPoint wh=FrequencydomainSelectarea();
int w=wh.x;
int h=wh.y;
// 分配内存
complex<double> *TD = new complex<double>[w * h];
complex<double> *FD = new complex<double>[w * h];
DoFFT( TD, FD, w,h);
complex<double> *HTD = new complex<double>[w * h];
complex<double> *HFD = new complex<double>[w * h];
for(int i = 0; i < h; i++)
for(int j = 0; j < w; j++)
HTD[j + w * i]=0.0;
//Gauss 5*5
HTD[2 + w * 2]=12.0/76.0;
HTD[1 + w * 2]=HTD[3 + w * 2]=HTD[2 + w * 1]=HTD[2 + w * 3]=7.0/76.0;
HTD[1 + w * 1]=HTD[1 + w * 3]=HTD[3 + w * 1]=HTD[3 + w * 3]=5.0/76.0;
HTD[0 + w * 2]=HTD[2 + w * 0]=HTD[4 + w * 2]=HTD[2 + w * 4]=2.0/76.0;
HTD[0 + w * 1]=HTD[1 + w * 0]=HTD[0 + w * 3]=HTD[3 + w * 0]=1.0/76.0;
HTD[1 + w * 4]=HTD[4 + w * 1]=HTD[4 + w * 3]=HTD[3 + w * 4]=1.0/76.0;
FFT2( HTD, HFD, w,h);
DisplayFw(HFD,w, h,20.0,"高斯滤波|H(u,v)|");
//proc
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
FD[j + w * i] *=HFD[j + w * i];
}
}
DoIFFT( TD, FD, w,h,"频域高斯滤波",CPoint(4,4));
// 恢复光标
EndWaitCursor();
// 删除临时变量
delete [] TD;
delete [] FD;
delete [] HTD;
delete [] HFD;
}
void CImageProcessView::OnUpdateConvolutionGauss(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnConvolutionLaplace()
{
// TODO: Add your command handler code here
// CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CPoint wh=FrequencydomainSelectarea();
int w=wh.x;
int h=wh.y;
// 分配内存
complex<double> *TD = new complex<double>[w * h];
complex<double> *FD = new complex<double>[w * h];
DoFFT( TD, FD, w,h);
complex<double> *HTD = new complex<double>[w * h];
complex<double> *HFD = new complex<double>[w * h];
for(int i = 0; i < h; i++)
for(int j = 0; j < w; j++)
HTD[j + w * i]=0.0;
//Laplace
HTD[1 + w * 1]=4.0;
HTD[1 + w * 0]=HTD[0 + w * 1]=HTD[2 + w * 1]=HTD[1 + w * 2]=-1.0;
FFT2( HTD, HFD, w,h);
DisplayFw(HFD,w, h,20.0,"Laplace滤波|H(u,v)|");
//proc
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
FD[j + w * i]*=HFD[j + w * i];
}
}
DoIFFT( TD, FD, w,h,"频域Laplace滤波",CPoint(2,2));//0,1 err
// 恢复光标
EndWaitCursor();
// 删除临时变量
delete [] TD;
delete [] FD;
delete [] HTD;
delete [] HFD;
}
void CImageProcessView::OnUpdateConvolutionLaplace(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnConvolutionMarr()
{
// TODO: Add your command handler code here
// CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CPoint wh=FrequencydomainSelectarea();
int w=wh.x;
int h=wh.y;
// 分配内存
complex<double> *TD = new complex<double>[w * h];
complex<double> *FD = new complex<double>[w * h];
DoFFT( TD, FD, w,h);
complex<double> *HTD = new complex<double>[w * h];
complex<double> *HFD = new complex<double>[w * h];
for(int i = 0; i < h; i++)
for(int j = 0; j < w; j++)
HTD[j + w * i]=0.0;
//Marr 5*5
HTD[2 + w * 2]=24.0;
HTD[1 + w * 2]=HTD[3 + w * 2]=HTD[2 + w * 1]=HTD[2 + w * 3]=8.0;
HTD[1 + w * 1]=HTD[1 + w * 3]=HTD[3 + w * 1]=HTD[3 + w * 3]=0.0;
HTD[0 + w * 1]=HTD[0 + w * 2]=HTD[0 + w * 3]=-4.0;
HTD[1 + w * 0]=HTD[2 + w * 0]=HTD[3 + w * 0]=-4.0;
HTD[4 + w * 1]=HTD[4 + w * 2]=HTD[4 + w * 3]=-4.0;
HTD[1 + w * 4]=HTD[2 + w * 4]=HTD[3 + w * 4]=-4.0;
HTD[0 + w * 0]=HTD[4 + w * 0]=HTD[0 + w * 4]=HTD[4 + w * 4]=-2.0;
FFT2( HTD, HFD, w,h);
DisplayFw(HFD,w, h,10.0,"Marr滤波|H(u,v)|");
//proc
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
FD[j + w * i] *=HFD[j + w * i];
}
}
DoIFFT( TD, FD, w,h,"频域Marr滤波",CPoint(4,4));
// 恢复光标
EndWaitCursor();
// 删除临时变量
delete [] TD;
delete [] FD;
delete [] HTD;
delete [] HFD;
}
void CImageProcessView::OnUpdateConvolutionMarr(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnConvolutionCorrelation()
{
// TODO: Add your command handler code here
// CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CPoint wh=FrequencydomainSelectarea();
int w=wh.x;
int h=wh.y;
// 分配内存
complex<double> *TD = new complex<double>[w * h];
complex<double> *FD = new complex<double>[w * h];
DoFFT( TD, FD, w,h);
complex<double> *HTD = new complex<double>[w * h];
complex<double> *HFD = new complex<double>[w * h];
unsigned char *lpSrc;
for(int i = 0; i < h; i++){
for(int j = 0; j < w; j++){
if(i<m_ModelHeight && j<m_ModelWidth)
{
lpSrc = m_pModelData + m_ModelWidth * i + j;
// 给时域赋值
HTD[j + w * i] = complex<double>(*(lpSrc), 0);//
}else{
HTD[j + w * i] = complex<double>(0,0);
}
}
}
FFT2( HTD, HFD, w,h);
//DisplayFw(FD,w, h,.6,"|F(u,v)|");
//DisplayFw(HFD,w, h,.6,"|H(u,v)|");
//DoIFFT( TD, FD, w,h,"F(x,y)",CPoint(0,0));
//proc
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
HFD[j + w * i]=complex<double>(HFD[j + w * i].real(), -HFD[j + w * i].imag());//共轭
FD[j + w * i]*=HFD[j + w * i];//FD[j + w * i]=FD[j + w * i]*HFD[j + w * i] ; 错!
// FD[j + w * i]=complex<double>(FD[j + w * i].real(), -FD[j + w * i].imag());//共轭
// FD[j + w * i]*=HFD[j + w * i];//FD[j + w * i]=FD[j + w * i]*HFD[j + w * i] ; 错!
}
}
//DisplayFw(FD,w, h,.6,"|F*(u,v)H(u,v)|");
//DoIFFT( HTD, HFD, w,h,"h(x,y)",CPoint(0,0));
DoIFFT( TD, FD, w,h,"频域相关运算",CPoint(m_ModelWidth/2,m_ModelHeight/2));
// 恢复光标
EndWaitCursor();
// 删除临时变量
delete [] TD;
delete [] FD;
delete [] HTD;
delete [] HFD;
}
void CImageProcessView::OnUpdateConvolutionCorrelation(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
if(m_pModelData)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//利用噪声方差,判断局部方差,噪声处进行平滑,边缘处不处理
void CImageProcessView::OnAdaptiveNoisereduction()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
//copy img
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
return ;
memcpy( lpNewDIBBits,pDoc->m_pDib->m_lpImage, lLineBytes * lHeight);
const int M=7;//odd
const int N=7;//odd
double mean;
double Dev2;
unsigned char* lpSrc;
unsigned char* lpDst;
const double Dev_Noise2=1000.0;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;
lpDst++;
if(i>=M/2 && i<lHeight-M/2 && j>=N/2 && j<lWidth-N/2){
//Get M*N mean
mean=0.0;
for(int m=-M/2;m<=M/2;m++)
for(int n=-N/2;n<=N/2;n++)
mean+=*(lpSrc+ lLineBytes* m+n);
mean/=(M*N);
Dev2=0.0;
for(int m=-M/2;m<=M/2;m++)
for(int n=-N/2;n<=N/2;n++)
Dev2+=((*(lpSrc+ lLineBytes* m+n)-mean)*
(*(lpSrc+ lLineBytes*m+n)-mean));
Dev2/=(M*N);
double dtmp;
if(Dev_Noise2>Dev2)
dtmp=mean;
else
dtmp=*lpSrc-Dev_Noise2/Dev2*(*lpSrc-mean);
if(dtmp<0) {
dtmp=0;//can get min adjust
}
else if(dtmp>255) dtmp=255;
*lpDst=(unsigned char)dtmp;//
}
}
}
CString str=pDoc->GetTitle();
DisplayNewImg(lpNewDIBBits,lLineBytes,lHeight,str+"--+自适应局部噪声消除滤波");//
delete [] lpNewDIBBits;
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdateAdaptiveNoisereduction(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//判断某点是否为脉冲,若是,其中值是否为脉冲,y,扩大(小于最大值)邻域使其非脉冲
void CImageProcessView::OnAdaptiveMedian()
{
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
const int Mmax=7;//max
const int Nmax=7;//odd
const int Mmin=5;//max
const int Nmin=5;//odd
const int PluseL=20;
const int PluseH=220;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
unsigned char* lpSrc;
unsigned char* lpDst;
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
unsigned char *v=new unsigned char[Mmax*Nmax];//[N*M];//line N Column M not rect (int err)
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;
lpDst++;
if(*lpSrc>PluseL && *lpSrc<PluseH) continue;
int M=Mmin;
int N=Nmin;
bool bOver=false;
while(!bOver){
//Get M*N data to v[]
int vSize=0;
for(int m=-M/2;m<=M/2;m++){
for(int n=-N/2;n<=N/2;n++){
if(i-m>=0 && i-m<lHeight && j+n>=0 && j+n<lWidth)
{
v[vSize]=*(lpSrc+lLineBytes*m+n);
vSize++;
}
}
}
//sort v[]
for(int m=0;m<vSize-1;m++){
for(int n=m+1;n<vSize;n++)
if(v[m]>v[n]){
//swap
BYTE tmp=v[m];
v[m]=v[n];
v[n]=tmp;
}
}
int Th=vSize/2;
if(v[Th]>max(v[0],PluseL) && v[Th]<min(v[vSize-1],PluseH)){
*lpDst=v[Th];
bOver=true;
}
else
{//need change M,N bigger
M+=2;
N+=2;
if(M>Mmax)
{
bOver=true;
*lpDst=v[Th];
}
}
}
}
}
CString str=pDoc->GetTitle();
DisplayNewImg(lpNewDIBBits,lLineBytes,lHeight,str+"--+自适应中值滤波");//
// 释放内存
delete []lpNewDIBBits;
delete []v;
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdateAdaptiveMedian(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnFrequencydomainNotchpassfilter()
{
// TODO: Add your command handler code here
// CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CPoint wh=FrequencydomainSelectarea();
int w=wh.x;
int h=wh.y;
// 分配内存
complex<double> *TD = new complex<double>[w * h];
complex<double> *FD = new complex<double>[w * h];
DoFFT( TD, FD, w,h);
//DisplayFw(FD,w, h,0.6,"|F(u,v)|");
//filter
//去除水平扫描线
// const double D0=30.0;
for(int y=0; y<h; y++)
{
for(int x=w/2-3; x<=w/2+3; x++)
{
if(y<h/2-10 || y>h/2+10)
FD[x + y*w]=complex<double>(0,0);//h*w
}
}
//DisplayFw(FD,w, h,0.6,"|F(u,v)H(u,v)|");
DoIFFT( TD, FD, w,h,"陷波滤波器",CPoint(0,0));
// 恢复光标
EndWaitCursor();
// 删除临时变量
delete [] TD;
delete [] FD;
}
void CImageProcessView::OnUpdateFrequencydomainNotchpassfilter(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//不太理想,无书中图像
//提取噪声图像,利用方差最小获取比例参数w,f=g-w*n
void CImageProcessView::OnFrequencydomainOptimumnotchfilter()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CPoint wh=FrequencydomainSelectarea();
int w=wh.x;
int h=wh.y;
// 分配内存
complex<double> *TD = new complex<double>[w * h];
complex<double> *FD = new complex<double>[w * h];
DoFFT( TD, FD, w,h);
//DisplayFw(FD,w, h,0.6,"|F(u,v)|");
//filter
// const double F0=FD[h/2*w + w/2].real();
for(int y=0; y<h; y++)
{
for(int x=0; x<w; x++)
{
//if((y-h/2)*(y-h/2)+(x-w/2)*(x-w/2)<400)
if(!((y<h/2-20 || y>h/2+20) && (x>w/2-5 && x<w/2+5)))
FD[x + y*w]=complex<double>(0,0);
}
}
//DisplayFw(FD,w, h,0.6,"|F(u,v)H(u,v)|");
//IFFT
int wp=int(log((double) w)/log(2.0));
int hp=int(log((double) h)/log(2.0));
for(int i = 0; i < w; i++)
{
// 对x方向进行快速付立叶变换
IFFT( &FD[i * h],&TD[i * h], hp);
}
// 保存变换结果
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
FD[j + w * i] = TD[i + h * j];//w*h
}
}
for(int i = 0; i < h; i++)
{
// 对y方向进行快速付立叶变换
IFFT(&FD[w * i],&TD[w * i],wp);
}
//再转置还原
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
FD[j + w * i] = TD[i + h * j];//转置
}
}
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
TD[j + w * i] = FD[j + w * i];
}
}
//1.noise
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
return ;
unsigned char* lpSrc;
unsigned char* lpSrc1;
double dTemp;
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
dTemp=TD[i * w + j].real();
//move back
if((i+j)%2) dTemp=-dTemp;
if (dTemp > 255)
dTemp = 255;
if (dTemp < 0) dTemp=0;
if(j<lWidth-pDoc->StartPoint.x && i<lHeight-pDoc->StartPoint.y)
{
lpSrc =lpNewDIBBits + lLineBytes * (lHeight - 1 - i-pDoc->StartPoint.y) + j+pDoc->StartPoint.x;
lpSrc1 =pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i-pDoc->StartPoint.y) + j+pDoc->StartPoint.x;
// 更新源图像
* (lpSrc) = (BYTE)dTemp;
}
}
}
//2.方差最小
unsigned char* lpNewDIBBits1;
lpNewDIBBits1=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits1 == NULL)
return ;
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits1,lpSrc, lLineBytes * lHeight);
unsigned char* lpDst;
const int M=15;
const int N=15;
int size=M*N;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc1 =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits1 + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpSrc1++;lpDst++;
if(i>M/2 && i<lHeight-M/2 && j>N/2 && j<lWidth-N/2){//
double gAv=0.0,nAv=0.0,gnAv=0.0,n2Av=0.0;
for(int m=-M/2;m<=M/2;m++){
for(int n=-N/2;n<=N/2;n++){
gAv+=*(lpSrc-lLineBytes*m+n);
nAv+=*(lpSrc1-lLineBytes*m+n);
gnAv+=(*(lpSrc-lLineBytes*m+n)*(*(lpSrc1-lLineBytes*m+n)));
n2Av+=(*(lpSrc1-lLineBytes*m+n)*(*(lpSrc1-lLineBytes*m+n)));
}
}
gAv/=size;
nAv/=size;
gnAv/=size;
n2Av/=size;
double wi=n2Av-nAv*nAv;
if(wi>0.001 || wi<-0.001)
wi=(gnAv-gAv*nAv)/wi;
else wi=0.0;
int v=(int)(*lpSrc-wi*(*lpSrc1));
if(v>255) v=255;
else if(v<0) v=0;
*lpDst=(BYTE) v;
}
}
}
CString str=pDoc->GetTitle();
DisplayNewImg(lpNewDIBBits1,lLineBytes,lHeight,str+"最佳陷波滤波器");
DisplayNewImg(lpNewDIBBits,lLineBytes,lHeight,str+"噪声图像");
// 恢复光标
EndWaitCursor();
// 删除临时变量
delete [] TD;
delete [] FD;
delete [] lpNewDIBBits;
delete [] lpNewDIBBits1;
}
void CImageProcessView::OnUpdateFrequencydomainOptimumnotchfilter(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//最小均方误差
//已知退化系统函数,添加噪声(假设为白噪声),恢复图像
//K很难调,K=0为逆滤波
void CImageProcessView::OnFrequencydomainWinnerfilter()
{
// TODO: Add your command handler code here
// CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CPoint wh=FrequencydomainSelectarea();
int w=wh.x;
int h=wh.y;
// 分配内存
complex<double> *TD = new complex<double>[w * h];
complex<double> *FD = new complex<double>[w * h];
DoFFT( TD, FD, w,h);
//DisplayFw(FD,w, h,0.6,"|F(u,v)|");
//filter
double c1=0.1;
double c2=0.1;
double T=1.0;
double K=.025;//chg
double minH=0.001;
for(int y=0; y<h; y++)
{
for(int x=0; x<w; x++)
{
double uv=Pi*(c1*(x-w/2)+c2*(y-h/2)) ;
complex<double> H ;
if(uv==0.0)
H= complex<double>(T,0.0);
else
H= complex<double>(T/(uv)*sin(uv)*cos(uv),-T/(uv)*sin(uv)*sin(uv));
if(H.real()>=0 && H.real()<=minH)
H= complex<double>(minH,H.imag());
if(H.imag()>=0 && H.imag()<=minH)
H= complex<double>(H.real(),minH);
if(H.real()<0 && H.real()>=-minH)
H= complex<double>(-minH,H.imag());
if(H.imag()<0 && H.imag()>=-minH)
H= complex<double>(H.real(),-minH);
// |H(u,v)|*|H(u,v)|
double norm = abs(H);
// |H(u,v)|*|H(u,v)|/(|H(u,v)|*|H(u,v)|+K)
double temp = (norm*norm ) / (norm*norm +K);
// 求得f(u,v)
FD[y*w + x]*=temp;
FD[y*w + x]/=H;
}
}
//DisplayFw(FD,w, h,0.6,"|F(u,v)H(u,v)|");
DoIFFT( TD, FD, w,h,"维纳滤波器",CPoint(0,0));
// 恢复光标
EndWaitCursor();
// 删除临时变量
delete [] TD;
delete [] FD;
}
void CImageProcessView::OnUpdateFrequencydomainWinnerfilter(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnFrequencydomainLeastsquaresfilter()
{
// TODO: Add your command handler code here
// CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CPoint wh=FrequencydomainSelectarea();
int w=wh.x;
int h=wh.y;
// 分配内存
complex<double> *TD = new complex<double>[w * h];
complex<double> *FD = new complex<double>[w * h];
DoFFT( TD, FD, w,h);
//DisplayFw(FD,w, h,0.6,"|F(u,v)|");
complex<double> *PTD = new complex<double>[w * h];
complex<double> *PFD = new complex<double>[w * h];
//Laplace
for(int y=0; y<h; y++)
for(int x=0; x<w; x++)
PTD[x + w * y]=0.0;
PTD[1 + w * 1]=4.0;
PTD[1 + w * 0]=PTD[0 + w * 1]=PTD[2 + w * 1]=PTD[1 + w * 2]=-1.0;
FFT2(PTD,PFD, w, h);
//filter
double c1=0.1;
double c2=0.1;
double T=1.0;
double r=0.2;
double minH=0.001;
for(int y=0; y<h; y++)
{
for(int x=0; x<w; x++)
{
double uv=Pi*(c1*(x-w/2)+c2*(y-h/2)) ;
complex<double> H ;
if(uv==0.0)
H= complex<double>(T,0.0);
else
H= complex<double>(T/(uv)*sin(uv)*cos(uv),-T/(uv)*sin(uv)*sin(uv));
if(H.real()>=0 && H.real()<=minH)
H= complex<double>(minH,H.imag());
if(H.imag()>=0 && H.imag()<=minH)
H= complex<double>(H.real(),minH);
if(H.real()<0 && H.real()>=-minH)
H= complex<double>(-minH,H.imag());
if(H.imag()<0 && H.imag()>=-minH)
H= complex<double>(H.real(),-minH);
// |H(u,v)|
double norm = abs(H);
// |P(u,v)|
double Pnorm = abs(PFD[y*w+x]);
// H*(u,v)/(|H(u,v)|^2+r|p(u,v)|^2)
complex<double> temp( complex<double>(H.real(),-H.imag()));
temp=temp/(norm*norm+r*Pnorm*Pnorm);
// 求得f(u,v)
FD[y*w + x]*=temp;
}
}
//DisplayFw(FD,w, h,0.6,"|F(u,v)H(u,v)|");
DoIFFT( TD, FD, w,h,"约束最小二乘法滤波器",CPoint(0,0));
// 恢复光标
EndWaitCursor();
// 删除临时变量
delete [] TD;
delete [] FD;
delete [] PTD;
delete [] PFD;
}
void CImageProcessView::OnUpdateFrequencydomainLeastsquaresfilter(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//设定多个畸变点,获得其校正后坐标
//将图像分成多个区域,对应区域满足线性平面
//解方程获得线性参数,对图像进行几何变换,可完成图像畸变、畸变校正
void CImageProcessView::OnSpatialdomainGeometrictransformations()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
//1.获得对应点
//4x4 对称区域
const int N=3;
CPoint pt1[(N+1)*(N+1)];
CPoint pt2[(N+1)*(N+1)];
int h=(pDoc->EndPoint.y-pDoc->StartPoint.y+1)/N;
int w=(pDoc->EndPoint.x-pDoc->StartPoint.x+1)/N;
int k=0;
使图像畸变
//for(int j=pDoc->StartPoint.y;j<pDoc->EndPoint.y;j+=h)
// for(int i=pDoc->StartPoint.x;i<pDoc->EndPoint.x;i+=w)
// {
// pt1[k]=CPoint(i,j);
// k++;
// }
//
//for(int i=0;i<(N+1)*(N+1);i++)
// pt2[i]=pt1[i]+CPoint(2,2);
//
//pt2[N+2]+=CPoint(-40,-10);
//pt2[N+3]+=CPoint(20,40);
//
//pt2[2*N+3]+=CPoint(-25,-10);
//pt2[2*N+4]+=CPoint(15,25);
//
//使畸变图像校正
for(int j=pDoc->StartPoint.y;j<pDoc->EndPoint.y;j+=h)
for(int i=pDoc->StartPoint.x;i<pDoc->EndPoint.x;i+=w)
{
pt2[k]=CPoint(i,j);
k++;
}
for(int i=0;i<(N+1)*(N+1);i++)
pt1[i]=pt2[i]+CPoint(2,2);
pt1[N+2]+=CPoint(-40,-10);
pt1[N+3]+=CPoint(20,40);
pt1[2*N+3]+=CPoint(-25,-10);
pt1[2*N+4]+=CPoint(15,25);
//2.获得对应变换系数(8)
double c[N*N][8];
for(int k=0;k<N*N;k++){
// 构造矩阵
CMatrix mtxA(8,8), mtxB(8,1),mtxC(8,1);
double value[64]={0};
double value1[8]={0};
value[0] =pt1[k+k/3+0].x; value[1]=pt1[k+k/3+0].y; value[2]=pt1[k+k/3+0].x*pt1[k+k/3+0].y; value[3]=1;
value[12]=pt1[k+k/3+0].x; value[13]=pt1[k+k/3+0].y; value[14]=pt1[k+k/3+0].x*pt1[k+k/3+0].y; value[15]=1;
value[16] =pt1[k+k/3+1].x; value[17]=pt1[k+k/3+1].y; value[18]=pt1[k+k/3+1].x*pt1[k+k/3+1].y; value[19]=1;
value[28]=pt1[k+k/3+1].x; value[29]=pt1[k+k/3+1].y; value[30]=pt1[k+k/3+1].x*pt1[k+k/3+1].y; value[31]=1;
value[32] =pt1[k+k/3+1+N].x; value[33]=pt1[k+k/3+1+N].y; value[34]=pt1[k+k/3+1+N].x*pt1[k+k/3+1+N].y; value[35]=1;
value[44]=pt1[k+k/3+1+N].x; value[45]=pt1[k+k/3+1+N].y; value[46]=pt1[k+k/3+1+N].x*pt1[k+k/3+1+N].y; value[47]=1;
value[48] =pt1[k+k/3+2+N].x; value[49]=pt1[k+k/3+2+N].y; value[50]=pt1[k+k/3+2+N].x*pt1[k+k/3+2+N].y; value[51]=1;
value[60]=pt1[k+k/3+2+N].x; value[61]=pt1[k+k/3+2+N].y; value[62]=pt1[k+k/3+2+N].x*pt1[k+k/3+2+N].y; value[63]=1;
value1[0]=pt2[k+k/3+0].x;value1[1]=pt2[k+k/3+0].y;
value1[2]=pt2[k+k/3+1].x;value1[3]=pt2[k+k/3+1].y;
value1[4]=pt2[k+k/3+1+N].x;value1[5]=pt2[k+k/3+1+N].y;
value1[6]=pt2[k+k/3+2+N].x;value1[7]=pt2[k+k/3+2+N].y;
mtxA.SetData(value);
mtxB.SetData(value1);
// 构造线性方程组
CLEquations leqs(mtxA, mtxB);
// 全选主元高斯消去法
CString m_strResult;
if (leqs.GetRootsetGauss(mtxC))
m_strResult = mtxC.ToString(" ");
else
{
m_strResult ="求解失败";
// 显示数据
AfxMessageBox(m_strResult, MB_OK|MB_ICONINFORMATION);
return;
}
memcpy(c[k],mtxC.GetData(),8*sizeof(double));
}
//3.几何校正
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
unsigned char* lpSrc;
unsigned char* lpDst;
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
for (int i = pDoc->StartPoint.y+2; i <pDoc->EndPoint.y-2; i ++){
for (int j =pDoc->StartPoint.x+2; j <pDoc->EndPoint.x-2; j ++){
lpDst = (unsigned char*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j;
//为了方便,不去判断具体区域,忍让边界处错误
int k=min(((i-pDoc->StartPoint.y)/h),N-1)*3+min((j-pDoc->StartPoint.x)/w,N);
double x=c[k][0]*j+c[k][1]*i+c[k][2]*i*j+c[k][3];
double y=c[k][4]*j+c[k][5]*i+c[k][6]*i*j+c[k][7];
int x1=(int)x;
int y1=(int)y;
if(x1>=0 && x1<lWidth-1 && y1>=0 && y1<lHeight-1){//in
lpSrc = (unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - y1) + x1;
int v=(unsigned char)((y1+1-y)*((x1+1-x)*(*lpSrc)+(x-x1)*(*(lpSrc+1)))
+(y-y1)*((x1+1-x)*(*(lpSrc-lLineBytes))+(x-x1)*(*(lpSrc-lLineBytes+1))));//a=x-x1 b=y-y1
if(v<0) v=0;
else if(v>255) v=255;
*lpDst=(BYTE)v;
// *lpDst=*(pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - (int)(y+0.5)) + (int)(x+0.5));//近邻插值
}
}
}
CString str=pDoc->GetTitle();
DisplayNewImg(lpNewDIBBits,lLineBytes,lHeight,str+"--+运用角点几何校正");//
delete [] lpNewDIBBits;
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdateSpatialdomainGeometrictransformations(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnDwtDwt()
{
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CPoint wh=FrequencydomainSelectarea();
int w=wh.x;
int h=wh.y;
const int LEVEL=2;
CString str=pDoc->GetTitle();
DisplayNewImg(pDoc->m_pDib->m_lpImage, lLineBytes,lHeight,str);
m_bDWT=!m_bDWT;
DoDWT(w,h,LEVEL);
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::DoDWT(int w,int h,int LEVEL)
{
CImageProcessDoc* pDoc = GetDocument();
//input data
// 分配内存
double *image = new double [w * h];
unsigned char* lpSrc;
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
// 指向DIB第i行,第j个象素的指针
if(i+pDoc->StartPoint.y<lHeight && pDoc->StartPoint.x+j<lWidth)
{
lpSrc = (unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i-pDoc->StartPoint.y) + pDoc->StartPoint.x+j;
image[j + w * i] = (double)*(lpSrc);//w*h
}else
image[j + w * i] = 0;//out of image:add 0
}
}
int wp=int(log((double) w)/log(2.0));
int hp=int(log((double) h)/log(2.0));
int nDWTCurDepth=0;
int nCurWLevel=wp;
int nCurHLevel=hp;
while( min(nCurWLevel,nCurHLevel)>min(wp,hp)-LEVEL)
{// 进行小波变换
// 计算当前分解的图象的长度和宽度
int CurW = 1<<nCurWLevel, CurH = 1<<nCurHLevel;
// 对行进行一维DWT
for (int i=0; i<CurH; i++)
DWTStep_1D(image+w*i, nCurWLevel, 0, 1,2);
// 对列进行一维DWT
for (int i=0; i<CurW; i++)
DWTStep_1D(image+i, nCurHLevel, 0, w,2);
nDWTCurDepth ++;
nCurWLevel=wp-nDWTCurDepth;
nCurHLevel=hp-nDWTCurDepth;
}
// 然后,将数据拷贝回原CDib中,并进行相应的数据转换
int lfw;
int lfh;
lfw = w>>nDWTCurDepth, lfh = h>>nDWTCurDepth;
for(int i = 0; i < h; i++)
{
// 列
for(int j = 0; j < w; j++)
{
double f=image[i * w + j];
unsigned char tmp;
if (i<lfh && j<lfw)
{//FloatToByte
if (f<=0) tmp=(BYTE)0;
else if (f>=255) tmp=(BYTE)255;
else tmp=(BYTE)(f+0.5);
}
else{
//FloatToChar
char temp;
if (f>=0){
if (f>=127.5)
temp= (char)127;
else temp=(char)(f+0.5);}
else{
if (f<=-128)
temp= (char)-128;
else temp= -(char)(-f+0.5);
}
tmp=(BYTE)(temp ^0x80);//+128
}
if(j<lWidth-pDoc->StartPoint.x && i<lHeight-pDoc->StartPoint.y)
{
lpSrc = pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i-pDoc->StartPoint.y) + j+pDoc->StartPoint.x;
* (lpSrc) = tmp;
}
}
}
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"DWT");
// 删除临时变量
delete [] image;
}
/*************************************************************************
*
* \函数名称:
* DWTStep_1D()
*
* \输入参数:
* double * pDbSrc - 指向源数据的指针
* int nCurLevel - 当前分界的层数
* int nInv - 是否为DWT,1表示为IDWT,0表示DWT
* int nStep - 当前的计算层数
* int nSupp - 小波基的紧支集的长度
*
* \返回值:
* BOOL - 成功则返回TRUE,否则返回FALSE
*
* \说明:
* 该函数用对存放在pDBSrc中的数据进行一层的一维DWT或者IDWT。其中,nInv为表示进行
* DWT或者IDWT的标志。nCurLevel为当前需要进行分界的层数。nStep为已经分界的层数
* 计算后数据仍存放在pDbSrc中
*
*************************************************************************
*/
BOOL CImageProcessView::DWTStep_1D(double* pDbSrc, int nCurLevel,
int nInv, int nStep,int nSupp)
{
// 小波变换函数原型
// Daubechies紧致正交小波基
//不同支撑区间长度下的滤波器系数如下
//only use hCoef[0][]
const double hCoef[10][20] =
{
{ .707106781187, .707106781187},
{ .482962913145, .836516303738, .224143868042, -.129409522551 },//use
{ .332670552950, .806891509311, .459877502118, -.135011020010, -.085441273882, .035226291882 },
{ .230377813309, .714846570553, .630880767930, -.027983769417,
-.187034811719, .030841381836, .032883011667, -.010597401785 },
{ .160102397974, .603829269797, .724308528438, .138428145901, -.242294887066,
-.032244869585, .077571493840, -.006241490213, -.012580751999, .003335725285 },
{ .111540743350, .494623890398, .751133908021, .315250351709, -.226264693965,
-.129766867567, .097501605587, .027522865530, -.031582039318, .000553842201,
.004777257511, -.001077301085 },
{ .077852054085, .396539319482, .729132090846, .469782287405, -.143906003929,
-.224036184994, .071309219267, .080612609151, -.038029936935, -.016574541631,
.012550998556, .000429577973, -.001801640704, .000353713800 },
{ .054415842243, .312871590914, .675630736297, .585354683654, -.015829105256,
-.284015542962, .000472484574, .128747426620, -.017369301002, -.044088253931,
.013981027917, .008746094047, -.004870352993, -.000391740373, .000675449406,
-.000117476784 },
{ .038077947364, .243834674613, .604823123690, .657288078051, .133197385825,
-.293273783279, -.096840783223, .148540749338, .030725681479, -.067632829061,
.000250947115, .022361662124, -.004723204758, -.004281503682, .001847646883,
.000230385764, -.000251963189, .000039347320 },
{ .026670057901, .188176800078, .527201188932, .688459039454, .281172343661,
-.249846424327, -.195946274377, .127369340336, .093057364604, -.071394147166,
-.029457536822, .033212674059, .003606553567, -.010733175483, .001395351747,
.001992405295, -.000685856695, -.000116466855, .000093588670, -.000013264203 }
};
double s = sqrt(2.0);
// 获得小波基的指针
double* h = (double*)hCoef[nSupp-1];
// 确认当前层数有效
ASSERT(nCurLevel>=0);
// 计算当前层数的长度
int CurN = 1<<nCurLevel;
if (nInv) CurN <<= 1;
// 确认所选择的小波基和当前层数的长度有效
if (nSupp<1 || nSupp>10 || CurN<2*nSupp)
return FALSE;
// 分配临时内存用于存放结果
double *ptemp = new double[CurN];
if (!ptemp) return FALSE;
double s1, s2;
int Index1, Index2;
// 判断是进行DWT还是IDWT
if (!nInv)
{ // DWT
Index1=0;
Index2=2*nSupp-1;
// 进行卷积,其中s1为低频部分,s2为高频部分的结果
for (int i=0; i<CurN/2; i++)
{
s1 = s2 = 0;
double t = -1;
for (int j=0; j<2*nSupp; j++, t=-t)
{
s1 += h[j]*pDbSrc[(Index1 & CurN-1) * nStep];
s2 += t*h[j]*pDbSrc[(Index2 & CurN-1) * nStep];
Index1++;
Index2--;
}
// 将结果存放在临时内存中
ptemp[i] = s1/s;
ptemp[i+CurN/2] = s2/s;
Index1 -= 2*nSupp;
Index2 += 2*nSupp;
Index1 += 2;
Index2 += 2;
}
}
// 否则进行IDWT
else
{ // IDWT
Index1 = CurN/2;
Index2 = CurN/2-nSupp+1;
// 进行卷积,其中其中s1为低频部分,s2为高频部分的结果
for (int i=0; i<CurN/2; i++)
{
s1 = s2 = 0;
int Index3 = 0;
for (int j=0; j<nSupp; j++)
{
s1 += h[Index3]*pDbSrc[(Index1 & CurN/2-1) * nStep]
+h[Index3+1]*pDbSrc[((Index2 & CurN/2-1) + CurN/2) * nStep];
s2 += h[Index3+1]*pDbSrc[(Index1 & CurN/2-1) * nStep]
-h[Index3]*pDbSrc[((Index2 & CurN/2-1) + CurN/2) * nStep];
Index3+=2;
Index1--, Index2++;
}
// 将结果存入临时内存
ptemp[2*i] = s1*s;
ptemp[2*i+1] = s2*s;
Index1 += nSupp;
Index2 -= nSupp;
Index1++;
Index2++;
}
}
// 将结果存入源图象中
for (long int i=0; i<CurN; i++)
pDbSrc[i*nStep] = ptemp[i];
// 释放临时内存,并返回
delete[] ptemp;
return TRUE;
}
void CImageProcessView::OnUpdateDwtDwt(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
if(!m_bDWT)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnDwtIdwt()
{
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CString str=pDoc->GetTitle();
DisplayNewImg(pDoc->m_pDib->m_lpImage, lLineBytes,lHeight,str);
m_bDWT=!m_bDWT;
const int LEVEL=2;
int w=pDoc->EndPoint.x-pDoc->StartPoint.x+1;
int h=pDoc->EndPoint.y-pDoc->StartPoint.y+1;
DoIDWT(w,h,LEVEL);
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::DoIDWT(int w,int h,int LEVEL)
{
CImageProcessDoc* pDoc = GetDocument();
//input data
// 分配内存
double *image = new double [w * h];
unsigned char* lpSrc;
int wp=int(log((double) w)/log(2.0));
int hp=int(log((double) h)/log(2.0));
int nDWTCurDepth=LEVEL;
int lfw = 1<<(wp-nDWTCurDepth), lfh = 1<<(hp-nDWTCurDepth);
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
lpSrc = (unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i-pDoc->StartPoint.y) + j+pDoc->StartPoint.x;
if (i>=lfh || j>=lfw)
{
//CharToFloat
image[j + w * i] = (double)*(lpSrc)-128;//高频
}else
image[j + w * i] = (double)*(lpSrc);//低频
}
}
int nCurWLevel=wp-nDWTCurDepth;
int nCurHLevel=hp-nDWTCurDepth;
while(nDWTCurDepth>0)
{// 进行小波反变换
// 计算当前分解的图象的长度和宽度
int CurW = 1<<nCurWLevel, CurH = 1<<nCurHLevel;
CurW <<= 1;
CurH <<= 1;
// 对列进行IDWT
for (int i=0; i<CurW; i++)
DWTStep_1D(image+i, nCurHLevel, 1, w,2);
// 对行进行IDWT
for (int i=0; i<CurH; i++)
DWTStep_1D(image+w*i, nCurWLevel, 1,1,2);
nDWTCurDepth --;
nCurWLevel=wp-nDWTCurDepth;
nCurHLevel=hp-nDWTCurDepth;
}
// 然后,将数据拷贝回原CDib中,并进行相应的数据转换
for(int i = 0; i < h; i++)
{
// 列
for(int j = 0; j < w; j++)
{
double f=image[i * w + j];
unsigned char tmp;
if (f<=0) tmp=(BYTE)0;
else if (f>=255) tmp=(BYTE)255;
else tmp=(BYTE)(f+0.5);
if(j<lWidth-pDoc->StartPoint.x && i<lHeight-pDoc->StartPoint.y)
{
lpSrc = pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i-pDoc->StartPoint.y) + j+pDoc->StartPoint.x;
* (lpSrc) = tmp;
}
}
}
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"IDWT");
// 删除临时变量
delete [] image;
}
void CImageProcessView::OnUpdateDwtIdwt(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
if(m_bDWT)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnEdgeAll()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
int w=pDoc->EndPoint.x-pDoc->StartPoint.x+1;
int h=pDoc->EndPoint.y-pDoc->StartPoint.y+1;
int wp=int(log((double) w)/log(2.0));
int hp=int(log((double) h)/log(2.0));
const int LEVEL=2;
int nDWTCurDepth=LEVEL;
int lfw = 1<<(wp-nDWTCurDepth), lfh = 1<<(hp-nDWTCurDepth);
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
lpSrc = (unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i-pDoc->StartPoint.y) + j+pDoc->StartPoint.x;
if (i<lfh && j<lfw)
*lpSrc = 128;//0
}
}
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
}
void CImageProcessView::OnUpdateEdgeAll(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
if(m_bDWT)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnEdgeH()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
int w=pDoc->EndPoint.x-pDoc->StartPoint.x+1;
int h=pDoc->EndPoint.y-pDoc->StartPoint.y+1;
int wp=int(log((double) w)/log(2.0));
int hp=int(log((double) h)/log(2.0));
const int LEVEL=2;
int nDWTCurDepth=LEVEL;
int lfw = 1<<(wp-nDWTCurDepth), lfh = 1<<(hp-nDWTCurDepth);
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
lpSrc = (unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i-pDoc->StartPoint.y) + j+pDoc->StartPoint.x;
if (i<lfh && j<lfw)
*lpSrc = 64;//0
else if (j<lfw || (j>=lfw && j<lfw*2 && i>lfh*2))
*lpSrc = 128;
}
}
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
}
void CImageProcessView::OnUpdateEdgeH(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
if(m_bDWT)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnEdgeV()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
int w=pDoc->EndPoint.x-pDoc->StartPoint.x+1;
int h=pDoc->EndPoint.y-pDoc->StartPoint.y+1;
int wp=int(log((double) w)/log(2.0));
int hp=int(log((double) h)/log(2.0));
const int LEVEL=2;
int nDWTCurDepth=LEVEL;
int lfw = 1<<(wp-nDWTCurDepth), lfh = 1<<(hp-nDWTCurDepth);
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
lpSrc = (unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i-pDoc->StartPoint.y) + j+pDoc->StartPoint.x;
if (i<lfh && j<lfw)
*lpSrc = 64;//0
else if (i<lfh || (i>=lfh && i<lfh*2 && j>lfw*2))
*lpSrc = 128;
}
}
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
}
void CImageProcessView::OnUpdateEdgeV(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
if(m_bDWT)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnDwtSmooth()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
int w=pDoc->EndPoint.x-pDoc->StartPoint.x+1;
int h=pDoc->EndPoint.y-pDoc->StartPoint.y+1;
int wp=int(log((double) w)/log(2.0));
int hp=int(log((double) h)/log(2.0));
const int LEVEL=2;
int nDWTCurDepth=LEVEL;
int lfw = 1<<(wp-nDWTCurDepth), lfh = 1<<(hp-nDWTCurDepth);
const int Th=20;
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
lpSrc = (unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i-pDoc->StartPoint.y) + j+pDoc->StartPoint.x;
if (!(i<lfh && j<lfw))
if(*lpSrc>128-Th && *lpSrc<128+Th)
*lpSrc = 128;
else if(*lpSrc>128)
*lpSrc-=Th;
else
*lpSrc+=Th;
}
}
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
}
void CImageProcessView::OnUpdateDwtSmooth(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
if(m_bDWT)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnMorphologicalDilation()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
int Obj=TWOVALUE_H;
int Back=TWOVALUE_L;
const int M=3;
const int N=3;
// 3×3的结构元素
int **S;
S = new int * [M];
for (int i = 0; i < M; i++) {
S[i] = new int[N] ;
}
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
S[i][j]=1;
Dilation(S,M,N,Obj,Back);
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"膨胀运算");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
for(int i=0;i<M;i++)
delete []S[i];
delete []S;
}
void CImageProcessView::Dilation(int** S, int M, int N, int Object, int Back)
{
// TODO: 在此添加命令处理程序代码
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
if(*lpSrc==Back){//obj no need process
for (int m = 0; m < M; m++)
{
for (int n = 0; n < N; n++)
{
if (S[m][n] == 0)
continue;
if(i+m-M/2>=0 && i+m-M/2<lHeight && j+n -N/2>=0 && j+n-N/2<lWidth)
if (*(lpSrc - lLineBytes*(m-M/2) +(n-N/2) ) ==Object)//R and ~St != Null
{ *lpDst=(BYTE)Object;
break;
}
}
}
}
}
}
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdateMorphologicalDilation(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bTwoValue);
}
void CImageProcessView::OnMorphologicalErosion()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
// int Obj=TWOVALUE_H;
int Back=TWOVALUE_L;
const int M=3;
const int N=3;
// 3×3的结构元素
int **S;
S = new int * [M];
for (int i = 0; i < M; i++) {
S[i] = new int[N] ;
}
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
S[i][j]=1;
Erosion(S,M,N,Back);
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"腐蚀运算");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
for(int i=0;i<M;i++)
delete []S[i];
delete []S;
}
void CImageProcessView::Erosion(int** S,int M,int N, int Back)
{
// TODO: 在此添加命令处理程序代码
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
if (*lpSrc !=Back){
for (int m = 0; m < M; m++)
{
for (int n = 0; n < N; n++)
{
if (S[m][n] == 0)
continue;
else if(i+m-M/2>=0 && i+m-M/2<lHeight && j+n -N/2>=0 && j+n-N/2<lWidth){
if (*(lpSrc - lLineBytes*(m-M/2) +(n-N/2) ) ==Back)//t St in R
{
*(lpDst)=(BYTE) Back;
break;
}
}
}
}
}
}
}
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdateMorphologicalErosion(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bTwoValue);
}
void CImageProcessView::OnMorphologicalOpen()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
int Obj=TWOVALUE_H;
int Back=TWOVALUE_L;
const int M=3;
const int N=3;
// 3×3的结构元素
int **S;
S = new int * [M];
for (int i = 0; i < M; i++) {
S[i] = new int[N] ;
}
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
S[i][j]=1;
Erosion(S,M,N,Back);
Dilation(S,M,N,Obj,Back);
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"开运算");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
for(int i=0;i<M;i++)
delete []S[i];
delete []S;
}
void CImageProcessView::OnUpdateMorphologicalOpen(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bTwoValue);
}
void CImageProcessView::OnMorphologicalClose()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
int Obj=TWOVALUE_H;
int Back=TWOVALUE_L;
const int M=3;
const int N=3;
// 3×3的结构元素
int **S;
S = new int * [M];
for (int i = 0; i < M; i++) {
S[i] = new int[N] ;
}
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
S[i][j]=1;
Dilation(S,M,N,Obj,Back);
Erosion(S,M,N,Back);
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"闭运算");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
for(int i=0;i<M;i++)
delete []S[i];
delete []S;
}
void CImageProcessView::OnUpdateMorphologicalClose(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bTwoValue);
}
//显示直方图,选择阈值
void CImageProcessView::OnSegmentationFixedthreshold()
{
// TODO: Add your command handler code here
// CImageProcessDoc* pDoc = GetDocument();
int Hist[256]={0};
GetHistgram(Hist,false);
DisplayDlg dlg;
dlg.pData=&Hist[0];
dlg.m_Sizex=256;
dlg.m_LinePos=THRESHOLD;
dlg.m_Title=_T("选择阈值");
dlg.m_Level=1;
if(dlg.DoModal()==IDOK)
THRESHOLD=dlg.m_LinePos;
Fixedthreshold();
}
void CImageProcessView::Fixedthreshold()
{
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpDst;
unsigned char* lpSrc;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) +pDoc->StartPoint.x;
lpDst = lpNewDIBBits + lLineBytes* (lHeight-1-i) +pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
if(*lpSrc>THRESHOLD)
*lpDst=TWOVALUE_H;
else
*lpDst=TWOVALUE_L;
lpSrc++;lpDst++;
}
}
CString str=pDoc->GetTitle();
DisplayNewImg(lpNewDIBBits,lLineBytes,lHeight,str+"--+二值化");//display orignal image
delete [] lpNewDIBBits;
}
void CImageProcessView::OnUpdateSegmentationFixedthreshold(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
if(!m_bTwoValue) bAvail=true;
pCmdUI->Enable(bAvail);
}
//A Erosion B1 (原点为1)&& A~ Erosion B2 (原点为X);(满足 1.不满足0)
//同于结构中所有点相同,结构应该含有1和0(查询速度慢)
void CImageProcessView::OnMorphologicalHitormiss()
{
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);//备份
int Obj=TWOVALUE_H;
int Back=TWOVALUE_L;
const int M=m_ModelHeight;
const int N=m_ModelWidth;
int **S;
S = new int * [M];
for (int i = 0; i < M; i++) {
S[i] = new int[N] ;
}
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
if(m_pModelData[i*m_ModelWidth+j])
S[i][j]=1;
else
S[i][j]=0;
//1 A Erosion B1
Erosion(S,M,N,Back);
unsigned char* lpNewDIBBits1;
lpNewDIBBits1=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits1 == NULL)
{
// 分配内存失败
return ;
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits1,lpSrc, lLineBytes * lHeight);///A Erosion B1
memcpy( lpSrc,lpNewDIBBits, lLineBytes * lHeight);//备份还原
//B2
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
S[i][j]=1-S[i][j];
//A~
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) +pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
*lpSrc=TWOVALUE_H-*lpSrc;
lpSrc++;
}
}
//if use lpNewDIBBits1==true,we can get fast!
//2 A~ Erosion B2
//Erosion(S,M,N,Obj,Back);
//for fast
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits1 + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
if(*lpDst==Obj)//A Erosion B1==Obj
{
bool bBack=false;//
for (int m = 0; m < M; m++)
{
for (int n = 0; n < N; n++)
{
if (S[m][n] == 0)
continue;
else if(i-m+M/2>=0 && i-m+M/2<lHeight && j+n -N/2>=0 && j+n -N/2<lWidth){
if (*(lpSrc - lLineBytes*(m-M/2) +(n-N/2) ) ==Back)//t St in R
{ bBack=true;;
m=M;n=N;//out
}
}
}
}
if(bBack) *(lpDst)= (BYTE)Back;
}
}
}
//display
LPRGBQUAD pDibQuad = (LPRGBQUAD) pDoc->m_pDib->m_lpvColorTable+TWOVALUE_H+1;//
pDibQuad->rgbRed = 255; pDibQuad->rgbGreen =0;pDibQuad->rgbBlue = 0;
pDibQuad = (LPRGBQUAD) pDoc->m_pDib->m_lpvColorTable+TWOVALUE_L+1;//
pDibQuad->rgbRed = 0; pDibQuad->rgbGreen =0;pDibQuad->rgbBlue = 255;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc =lpNewDIBBits + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;//A
lpDst =lpNewDIBBits1 + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;//击中或击不中
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpDst++;lpSrc++;
if(*lpDst == Obj)
{
for (int m = 0; m < m_ModelHeight; m++)
{
for (int n = 0; n <m_ModelWidth; n++)
{
*(lpSrc+ lLineBytes*(m_ModelHeight/2 - m) +(n - m_ModelWidth/2) )+=1; //=m_ModelData[m*m_ModelWidth+n];
}
}
}
}
}
memcpy( pDoc->m_pDib->m_lpImage,lpNewDIBBits, lLineBytes * lHeight);//显示结果
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"击中或击不中运算");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
// 恢复光标
EndWaitCursor();
for(int i=0;i<M;i++)
delete []S[i];
delete []S;
delete [] lpNewDIBBits;
delete [] lpNewDIBBits1;
}
void CImageProcessView::OnUpdateMorphologicalHitormiss(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
BOOL bAvail=false;
if(m_bTwoValue)
if(m_pModelData)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//利用3x3结构B腐蚀
//A-(A腐蚀B)
//在原图上显示边缘
void CImageProcessView::OnApplicationBoundaryextraction()
{
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
return ;
//copy img
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
//int Obj=TWOVALUE_H;
int Back=TWOVALUE_L;
const int M=3;
const int N=3;
// 3×3的结构元素
int **S;
S = new int * [M];
for (int i = 0; i < M; i++) {
S[i] = new int[N] ;
}
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
S[i][j]=1;
//S[0][0]=0;S[0][2]=0;S[2][0]=0;S[2][2]=0;
Erosion(S,M,N,Back);
for(int i=0;i<M;i++)
delete []S[i];
delete []S;
//A-A Erosion B
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{ lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
{
lpSrc++;lpDst++;
*lpSrc=(*lpDst-*lpSrc);
if(*lpSrc) (*lpDst)+=1;//for display
}
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpSrc,lpNewDIBBits, lLineBytes * lHeight);
LPRGBQUAD pDibQuad = (LPRGBQUAD) pDoc->m_pDib->m_lpvColorTable+TWOVALUE_H+1;//
pDibQuad->rgbRed = 255;pDibQuad->rgbGreen =0;pDibQuad->rgbBlue = 0;
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"边缘提取");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdateApplicationBoundaryextraction(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bTwoValue);
}
//将背景提取出来,则可以填充非背景区域,利用4个角点为可能背景点,利用十字结构膨胀,将背景填满
void CImageProcessView::OnApplicationRegionfilling()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
BeginWaitCursor();
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
//set init seed 背景(4 角点)
lpSrc =pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 -pDoc->StartPoint.y-1)+pDoc->StartPoint.x+1;
if(*lpSrc==TWOVALUE_L)
*(lpNewDIBBits + lLineBytes * (lHeight - 1 -pDoc->StartPoint.y-1)+pDoc->StartPoint.x+1)=0x1;
lpSrc =pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 -pDoc->StartPoint.y-1)+pDoc->EndPoint.x-1;
if(*lpSrc==TWOVALUE_L)
*(lpNewDIBBits + lLineBytes * (lHeight - 1 -pDoc->StartPoint.y-1)+pDoc->EndPoint.x-1)=0x1;
lpSrc =pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 -pDoc->EndPoint.y+1)+pDoc->StartPoint.x+1;
if(*lpSrc==TWOVALUE_L)
*(lpNewDIBBits + lLineBytes * (lHeight - 1 -pDoc->EndPoint.y+1)+pDoc->StartPoint.x+1)=0x1;
lpSrc =pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 -pDoc->EndPoint.y+1)+pDoc->EndPoint.x-1;
if(*lpSrc==TWOVALUE_L)
*(lpNewDIBBits + lLineBytes * (lHeight - 1 -pDoc->EndPoint.y+1)+pDoc->EndPoint.x-1)=0x1;
bool bchg=true;
//提取背景
while(bchg){
bchg=false;
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x;
lpSrc =pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
lpDst++;lpSrc++;
if(((*lpSrc)==TWOVALUE_L) && ((*lpDst)==0x1))
{ bchg=true;
*lpSrc|=0x1;//visited
//若边缘为1个像数,可能出错
//for(int m=-1;m<2;m++)
// for(int n=-1;n<2;n++)
// if((*(lpSrc+m*lLineBytes+n))==TWOVALUE_L) (*(lpDst+m*lLineBytes+n))=0x1;
//十字结构
if((*(lpSrc+lLineBytes))==TWOVALUE_L) *(lpDst+lLineBytes)=0x1;
if((*(lpSrc-lLineBytes))==TWOVALUE_L) *(lpDst-lLineBytes)=0x1;
if((*(lpSrc+1))==TWOVALUE_L) *(lpDst+1)=0x1;
if((*(lpSrc-1))==TWOVALUE_L) *(lpDst-1)=0x1;
}
}
}
}
//非背景0置128
//change all black to white
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ j;
if(*lpDst==TWOVALUE_L){
*lpDst=TWOVALUE_H;
}
}
}
//display
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
if(!*lpSrc && *lpDst>=TWOVALUE_H)
(*lpDst)+=1;
}
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpSrc,lpNewDIBBits, lLineBytes * lHeight);
LPRGBQUAD pDibQuad = (LPRGBQUAD) pDoc->m_pDib->m_lpvColorTable+TWOVALUE_H+1;//out
pDibQuad->rgbRed = 255;pDibQuad->rgbGreen =0;pDibQuad->rgbBlue = 0;
EndWaitCursor();
// 释放内存
delete []lpNewDIBBits;
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"区域填充");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
}
void CImageProcessView::OnUpdateApplicationRegionfilling(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bTwoValue);
}
//顺序扫描,找到一未访问的物体点,No++,利用膨胀获取相连部分,全设置为N,且设置为访问过;直到全部访问过
//统计每个区域面积;可以求区域中心、周长、矩等
void CImageProcessView::OnApplicationConnectedcomponents()
{
// TODO: Add your command handler code here
// CImageProcessDoc* pDoc = GetDocument();
int ObjNum=Connectedcomponents();
DisplayObjLabel(ObjNum+1);
}
int CImageProcessView::Connectedcomponents(){
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
return 0;
memset( lpNewDIBBits,0, lLineBytes * lHeight);
int No=0;
bool bProcOver=false;
while(!bProcOver){
bProcOver=true;
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x;
lpSrc =pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
lpDst++;lpSrc++;
if(((*lpSrc)==TWOVALUE_H) && (!*lpDst))
{ No++;
*lpDst=(BYTE)No;//set first pt
bProcOver=false;
break;
}
}
if(!bProcOver)break;
}
if(bProcOver) break;
bool bchg=true;
while(bchg){
bchg=false;
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x;
lpSrc =pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
lpDst++;lpSrc++;
if(((*lpSrc)==TWOVALUE_H) && ((*lpDst)==No))
{ bchg=true;
*lpSrc|=0x1;//visited
//must be 8 point
for(int m=-1;m<2;m++)
for(int n=-1;n<2;n++)
if((*(lpSrc+m*lLineBytes+n))==TWOVALUE_H) (*(lpDst+m*lLineBytes+n))=(BYTE)No;
}
}
}
}
}
memcpy(pDoc->m_pDib->m_lpImage, lpNewDIBBits, lLineBytes * lHeight);
// 释放内存
delete []lpNewDIBBits;
return No;//object number
}
void CImageProcessView::OnUpdateApplicationConnectedcomponents(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bTwoValue);
}
//凸壳:区域内任意两点落在区域内
//该方法不是最小区域
//获取包含区域最小长方形区域,限制在该区域
//4个结构,击中点包含,反复运算直到不改变
//仅进行一个凸壳运算,故先选择区域,可以方便的求取多个凸壳
void CImageProcessView::OnApplicationConvexhull()
{
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
unsigned char* lpNewDIBBits1;
lpNewDIBBits1=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits1 == NULL)
{
// 分配内存失败
return ;
}
BeginWaitCursor();
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
memcpy( lpNewDIBBits1,lpNewDIBBits, lLineBytes * lHeight);
//Get max area
CRect rectArea(512,512,0,0);
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{ lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
{
lpSrc++;
if(*lpSrc & TWOVALUE_H) //
{
if(i<rectArea.top)rectArea.top=i;
else if(i>rectArea.bottom)rectArea.bottom=i;
if(j<rectArea.left)rectArea.left=j;
else if(j>rectArea.right)rectArea.right=j;
}
}
}
pDoc->StartPoint.x=rectArea.left-1;
pDoc->EndPoint.x=rectArea.right+1;
pDoc->StartPoint.y=rectArea.top-1;
pDoc->EndPoint.y=rectArea.bottom+1;
// |
// |o
// |
bool bOver=false;
while(!bOver){
bOver=true;
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
lpDst=lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ j;
if(*lpDst == TWOVALUE_L)
if (*(lpDst-1) ==TWOVALUE_H && *(lpDst-1+ lLineBytes) ==TWOVALUE_H && *(lpDst-1- lLineBytes) ==TWOVALUE_H)
{
*lpDst = TWOVALUE_H;
lpDst=lpNewDIBBits1 + lLineBytes * (lHeight - 1 - i)+ j;;
*lpDst = TWOVALUE_H;
bOver=false;
}
}
}
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
//---
// o
bOver=false;
while(!bOver){
bOver=true;
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
lpDst=lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ j;;
if(*lpDst == TWOVALUE_L)
if (*(lpDst-1+lLineBytes) ==TWOVALUE_H && *(lpDst+ lLineBytes) ==TWOVALUE_H && *(lpDst+1+ lLineBytes) ==TWOVALUE_H)
{
*lpDst = TWOVALUE_H;
lpDst=lpNewDIBBits1 + lLineBytes * (lHeight - 1 - i)+ j;;
*lpDst = TWOVALUE_H;
bOver=false;
}
}
}
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
// |
// o|
// |
bOver=false;
while(!bOver){
bOver=true;
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
for (int j =pDoc->EndPoint.x-1; j >pDoc->StartPoint.x; j --){
lpDst=lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ j;;
if(*lpDst == TWOVALUE_L)
if (*(lpDst+1) ==TWOVALUE_H && *(lpDst+1+ lLineBytes) ==TWOVALUE_H && *(lpDst+1- lLineBytes) ==TWOVALUE_H)
{
*lpDst = TWOVALUE_H;
lpDst=lpNewDIBBits1 + lLineBytes * (lHeight - 1 - i)+ j;;
*lpDst = TWOVALUE_H;
bOver=false;
}
}
}
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
// o
//---
bOver=false;
while(!bOver){
bOver=true;
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
for (int i =pDoc->EndPoint.y-1 ; i >pDoc->StartPoint.y; i --){
lpDst=lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ j;;
if(*lpDst == TWOVALUE_L)
if (*(lpDst-1-lLineBytes) ==TWOVALUE_H && *(lpDst-lLineBytes) ==TWOVALUE_H && *(lpDst+1- lLineBytes) ==TWOVALUE_H)
{
*lpDst = TWOVALUE_H;
lpDst=lpNewDIBBits1 + lLineBytes * (lHeight - 1 - i)+ j;;
*lpDst = TWOVALUE_H;
bOver=false;
}
}
}
}
CString str=pDoc->GetTitle();
DisplayNewImg(lpNewDIBBits1,lLineBytes,lHeight,str+"凸壳");//
EndWaitCursor();
// 释放内存
delete []lpNewDIBBits;
delete []lpNewDIBBits1;
}
void CImageProcessView::OnUpdateApplicationConvexhull(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bTwoValue);
}
//利用8结构进行击中运算,重复直到没有改变
//删除击中点
//不是单像数,利用保持连通性的结构删除多余像数
void CImageProcessView::OnApplicationThin()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
// 更改光标形状
BeginWaitCursor();
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
//击中 0--0 1---1 2--X(0\1)
// 3×3的结构元素
int B[8][9] = {
{ 0, 0, 0,
2, 1, 2,
1, 1, 1},
{ 2, 0, 0,
1, 1, 0,
1, 1, 2},
{ 1, 2, 0,
1, 1, 0,
1, 2, 0},
{ 1, 1, 2,
1, 1, 0,
2, 0, 0},
{ 1, 1, 1,
2, 1, 2,
0, 0, 0},
{ 2, 1, 1,
0, 1, 1,
0, 0, 2},
{ 0, 2, 1,
0, 1, 1,
0, 2, 1},
{ 0, 0, 2,
0, 1, 1,
2, 1, 1},
};
BOOL bOver=false;
while(!bOver){
bOver=true;
for(int si=0;si<8;si++){
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpDst++;lpSrc++;
if(i>0 && i<lHeight-1 && j>0 && j<lWidth-1){
if(*lpSrc == TWOVALUE_H) //
{ bool bchg=true;
for (int m = 0; m < 3; m++)
{
for (int n = 0; n < 3; n++)
{
if (B[si][m *3+ n] == 2)
continue;
else
if (B[si][m *3+ n] == 0){
if (*(lpSrc + lLineBytes*(1 - m) +(n - 1) ) ==TWOVALUE_H)
{
bchg=false;
m=3;n=3;//out
}
}
else
if (B[si][m *3+ n] == 1)
if (*(lpSrc + lLineBytes*(1 - m) +(n - 1) ) ==TWOVALUE_L)
{
bchg=false;
m=3;n=3;//out
}
}
}
if(bchg) {
*lpDst = TWOVALUE_L;
bOver=false;
}
}
}
}
}
//
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy(lpSrc, lpNewDIBBits, lLineBytes * lHeight);
}
}
// 不是单像数,删除多余像数
//m-connectivity
int B4[4][9] = {
{ 0, 1, 2,
1, 1, 0,
2, 0, 0},
{ 2, 1, 0,
0, 1, 1,
0, 0, 2},
{ 0, 0, 2,
0, 1, 1,
2, 1, 0},
{ 2, 0, 0,
1, 1, 0,
0, 1, 2}
};
for(int si=0;si<4;si++){
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst =pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpDst++;
if(i>0 && i<lHeight-1 && j>0 && j<lWidth-1){
if(*lpDst == TWOVALUE_H) //
{ bool bchg=true;
for (int m = 0; m < 3; m++)
{
for (int n = 0; n < 3; n++)
{
if (B4[si][m *3+ n] == 2)
continue;
else
if (B4[si][m *3+ n] == 0){
if (*(lpDst + lLineBytes*(1 - m) +(n - 1) ) ==TWOVALUE_H)
{
bchg=false;
m=3;n=3;//out
}
}
else
if (B4[si][m *3+ n] == 1)
if (*(lpDst + lLineBytes*(1 - m) +(n - 1) ) ==TWOVALUE_L)
{
bchg=false;
m=3;n=3;//out
}
}
}
if(bchg)
*lpDst = TWOVALUE_L;
}
}
}
}
}
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"击中击不中-细化");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
EndWaitCursor();
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdateApplicationThin(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bTwoValue);
}
//细化后图像有毛刺,利用选择的模板进行3次细化,去除小毛刺,同时对端点处影响
//获取端点,在此处进行膨胀,与原图取交集恢复端点处,如毛刺距端点处大于3则消除
void CImageProcessView::OnApplicationPruned()
{
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
unsigned char* lpNewDIBBits1;
lpNewDIBBits1=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits1 == NULL)
{
// 分配内存失败
return ;
}
// 更改光标形状
BeginWaitCursor();
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
memcpy( lpNewDIBBits1,lpSrc, lLineBytes * lHeight);
//细化
//击中 0--0 1---1 2--X(0\1)
// 3×3的结构元素
int B[8][9] = {
{ 2, 0, 0,
1, 1, 0,
2, 0, 0},
{ 2, 1, 2,
0, 1, 0,
0, 0, 0},
{ 0, 0, 2,
0, 1, 1,
0, 0, 2},
{ 0, 0, 0,
0, 1, 0,
2, 1, 2},
{ 1, 0, 0,
0, 1, 0,
0, 0, 0},
{ 0, 0, 1,
0, 1, 0,
0, 0, 0},
{ 0, 0, 0,
0, 1, 0,
0, 0, 1},
{ 0, 0, 0,
0, 1, 0,
1, 0, 0},
};
//去除3点毛刺
int Num=3;
while(Num){
Num--;
for(int si=0;si<8;si++){
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpDst++;lpSrc++;
if(i>0 && i<lHeight-1 && j>0 && j<lWidth-1){
if(*lpSrc == TWOVALUE_H) //
{ bool bchg=true;
for (int m = 0; m < 3; m++)
{
for (int n = 0; n < 3; n++)
{
if (B[si][m *3+ n] == 2)
continue;
else
if (B[si][m *3+ n] == 0){
if (*(lpSrc + lLineBytes*(1 - m) +(n - 1) ) ==TWOVALUE_H)
{
bchg=false;
m=3;n=3;//out
}
}
else
if (B[si][m *3+ n] == 1)
if (*(lpSrc + lLineBytes*(1 - m) +(n - 1) ) ==TWOVALUE_L)
{
bchg=false;
m=3;n=3;//out
}
}
}
if(bchg)
*lpDst = TWOVALUE_L;
}
}
}
}
//
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy(lpSrc, lpNewDIBBits, lLineBytes * lHeight);
}
}
//set 0
memset(pDoc->m_pDib->m_lpImage,0, lLineBytes * lHeight);
//获取端点
//lpNewDIBBits---X1=A细化{B}
//pDoc->m_pDib->m_lpImage--端点X2=X1击中{B}
for(int si=0;si<8;si++){
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = lpNewDIBBits + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst = pDoc->m_pDib->m_lpImage+ lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpDst++;lpSrc++;
if(i>0 && i<lHeight-1 && j>0 && j<lWidth-1){
if(*lpSrc == TWOVALUE_H) //
{ bool bchg=true;
for (int m = 0; m < 3; m++)
{
for (int n = 0; n < 3; n++)
{
if (B[si][m *3+ n] == 2)
continue;
else
if (B[si][m *3+ n] == 0){
if (*(lpSrc + lLineBytes*(1 - m) +(n - 1) ) ==TWOVALUE_H)
{
bchg=false;
m=3;n=3;//out
}
}
else
if (B[si][m *3+ n] == 1)
if (*(lpSrc + lLineBytes*(1 - m) +(n - 1) ) ==TWOVALUE_L)
{
bchg=false;
m=3;n=3;//out
}
}
}
if(bchg)
*lpDst = TWOVALUE_H;
}
}
}
}
}
//膨胀3次
// 3×3的结构元素
int **S;
int M=3;
int N=3;
S = new int * [M];
for (int i = 0; i < M; i++) {
S[i] = new int[N] ;
}
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
S[i][j]=1;
Dilation(S,M,N,TWOVALUE_H,TWOVALUE_L);
Dilation(S,M,N,TWOVALUE_H,TWOVALUE_L);
Dilation(S,M,N,TWOVALUE_H,TWOVALUE_L);
for(int i=0;i<M;i++)
delete []S[i];
delete []S;
//端点延伸3次U X1
unsigned char * lpSrc1;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = lpNewDIBBits1 + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc1 = lpNewDIBBits + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst = pDoc->m_pDib->m_lpImage+ lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpDst++;lpSrc++;
if(*lpDst){
if(!(*lpSrc)) *lpDst=TWOVALUE_L;
}
(*lpSrc1)|=(*lpDst);
}
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy(lpSrc, lpNewDIBBits1, lLineBytes * lHeight);
CString str=pDoc->GetTitle();
DisplayNewImg(lpNewDIBBits,lLineBytes,lHeight,str+"裁剪");//
EndWaitCursor();
// 释放内存
delete []lpNewDIBBits;
delete []lpNewDIBBits1;
}
void CImageProcessView::OnUpdateApplicationPruned(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bTwoValue);
}
void CImageProcessView::OnGrayDilation()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
const int M=3;
const int N=3;
// 3×3的结构元素
int **S;
S = new int * [M];
for (int i = 0; i < M; i++) {
S[i] = new int[N] ;
}
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
S[i][j]=0;
GrayDilation(S,M,N);
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"膨胀运算");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
for(int i=0;i<M;i++)
delete []S[i];
delete []S;
}
void CImageProcessView::OnUpdateGrayDilation(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnGrayErosion()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
const int M=3;
const int N=3;
// 3×3的结构元素
int **S;
S = new int * [M];
for (int i = 0; i < M; i++) {
S[i] = new int[N] ;
}
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
S[i][j]=0;
GrayErosion(S,M,N);
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"腐蚀运算");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
for(int i=0;i<M;i++)
delete []S[i];
delete []S;
}
void CImageProcessView::GrayDilation(int** S, int M, int N)
{
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
膨胀运算
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
int gray=*lpSrc;
for (int m = 0; m < M; m++)
{
for (int n = 0; n < N; n++)
{ if(S[m][n]<0) continue;
if(i-M/2 + m>=0 && i-M/2 +m<lHeight && j+n - N/2>=0 && j+n - N/2<lWidth){
int tmp=*(lpSrc + lLineBytes*(M/2 - m) +(n - N/2))+S[m][n];
if(tmp>gray) gray=tmp;//max
}
}
}
if(gray>255) gray=255;
*lpDst=(BYTE)gray;
}
}
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::GrayErosion(int** S, int M, int N)
{
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
//腐蚀运算,定义域内输入数据减对应模板数据,并求最小值,该最小值便是该点输出
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
int gray=*lpSrc;
for (int m = 0; m < M; m++)
{
for (int n = 0; n < N; n++)
{ if(S[m][n]<0) continue;
if(i-M/2 + m>=0 && i-M/2 +m<lHeight && j+n - N/2>=0 && j+n - N/2<lWidth)
{
int tmp=*(lpSrc + lLineBytes*(M/2 - m) +(n - N/2))-S[m][n];
if(tmp<gray) gray=tmp;//min
}
}
}
*lpDst=(BYTE)gray;
}
}
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdateGrayErosion(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnGrayOpen()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
const int M=3;
const int N=3;
// 3×3的结构元素
int **S;
S = new int * [M];
for (int i = 0; i < M; i++) {
S[i] = new int[N] ;
}
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
S[i][j]=0;
GrayErosion(S,M,N);
GrayDilation(S,M,N);
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"开运算");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
for(int i=0;i<M;i++)
delete []S[i];
delete []S;
}
void CImageProcessView::OnUpdateGrayOpen(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnGrayClose()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
const int M=3;
const int N=3;
// 3×3的结构元素
int **S;
S = new int * [M];
for (int i = 0; i < M; i++) {
S[i] = new int[N] ;
}
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
S[i][j]=0;
GrayDilation(S,M,N);
GrayErosion(S,M,N);
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"闭运算");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
for(int i=0;i<M;i++)
delete []S[i];
delete []S;
}
void CImageProcessView::OnUpdateGrayClose(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnGrayGradient()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
unsigned char* lpNewDIBBits1;
lpNewDIBBits1=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits1 == NULL)
{
return ;
}
const int M=3;
const int N=3;
// 3×3的结构元素
int **S;
S = new int * [M];
for (int i = 0; i < M; i++) {
S[i] = new int[N] ;
}
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
S[i][j]=0;
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits1,lpSrc, lLineBytes * lHeight);
GrayDilation(S,M,N);
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
//load
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy(lpSrc, lpNewDIBBits1, lLineBytes * lHeight);
GrayErosion(S,M,N);
//形态学梯度为膨胀的结果减腐蚀的结果
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
*lpDst=max(*lpDst-*lpSrc,0);
}
}
CString str=pDoc->GetTitle();
DisplayNewImg(lpNewDIBBits, lLineBytes ,lHeight,str+"形态学梯度");
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy(lpSrc, lpNewDIBBits1, lLineBytes * lHeight);
// 释放内存
delete []lpNewDIBBits;
delete []lpNewDIBBits1;
for(int i=0;i<M;i++)
delete []S[i];
delete []S;
}
void CImageProcessView::OnUpdateGrayGradient(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnGrayTophat()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
const int M=3;
const int N=3;
// 3×3的结构元素
int **S;
S = new int * [M];
for (int i = 0; i < M; i++) {
S[i] = new int[N] ;
}
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
S[i][j]=0;
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
GrayErosion(S,M,N);
GrayDilation(S,M,N);
//原图减开运算的结果
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
*lpSrc=max(*lpDst-*lpSrc,0);
}
}
CString str=pDoc->GetTitle();
DisplayNewImg(pDoc->m_pDib->m_lpImage, lLineBytes ,lHeight,str+"Top-hat变换");
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy(lpSrc, lpNewDIBBits, lLineBytes * lHeight);
// 释放内存
delete []lpNewDIBBits;
for(int i=0;i<M;i++)
delete []S[i];
delete []S;
}
void CImageProcessView::OnUpdateGrayTophat(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//获取梯度大小,低2位包含方向信息 0| 、1\、 2--、 3/
//存放于原图,可以调用
void CImageProcessView::OnEdgeSobel()
{
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
BeginWaitCursor();
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
int pixel[8];
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
if(i>0 && i<lHeight-1 && j>0 && j<lWidth-1){
pixel[0] = (int)*(lpSrc+lLineBytes-1);
pixel[1] = (int)*(lpSrc+lLineBytes);
pixel[2] = (int)*(lpSrc+lLineBytes+1);
pixel[3] = (int)*(lpSrc-1);
pixel[4] = (int)*(lpSrc+1);
pixel[5] = (int)*(lpSrc - lLineBytes-1);
pixel[6] = (int)*(lpSrc - lLineBytes);
pixel[7] = (int)*(lpSrc - lLineBytes+1);
// 1 2 1
// 0 0 0
// -1 -2 -1
int tmp1=pixel[0]+2*pixel[1]+pixel[2]-pixel[5]-2*pixel[6]-pixel[7];
// -1 0 1
// -2 0 2
// -1 0 1
int tmp2=pixel[2]+2*pixel[4]+pixel[7]-pixel[0]-2*pixel[3]-pixel[5];
int result =(int)(sqrt(double(tmp1*tmp1+tmp2*tmp2))+0.5);//>>255
if(result>255) result=255;
*lpDst = (unsigned char)result;
//add edge infomation
*lpDst&=0xfc;
if(tmp2==0) tmp2=1;
double tha=atan((double(tmp1))/tmp2);
//if(result>10)
// TRACE("\n %3.2f",tha);
if(abs(tha)<Pi/8)// | 0
*lpDst=*lpDst;
else
if(tha>Pi/8 && tha<Pi*3/8)// \ 1
*lpDst=*lpDst+1;
else
if(tha<-Pi/8 && tha>-Pi*3/8)// / 3
*lpDst=*lpDst+3;
else // - 2
*lpDst=*lpDst+2;
}else *lpDst=0;
}
}
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"--Sobe");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
// 恢复光标
EndWaitCursor();
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdateEdgeSobel(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//显示-127---127(0--128)
//高值反映边缘偏亮处、低值为边缘偏暗处,不显示边缘处(过零点)
//跳跃变换如二值图像无过零点
void CImageProcessView::OnEdgeLaplace()
{
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
BeginWaitCursor();
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
int pixel[8];
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
if(i>0 && i<lHeight-1 && j>0 && j<lWidth-1){
pixel[0] = (int)*(lpSrc+lLineBytes-1);
pixel[1] = (int)*(lpSrc+lLineBytes);
pixel[2] = (int)*(lpSrc+lLineBytes+1);
pixel[3] = (int)*(lpSrc-1);
pixel[4] = (int)*(lpSrc+1);
pixel[5] = (int)*(lpSrc - lLineBytes-1);
pixel[6] = (int)*(lpSrc - lLineBytes);
pixel[7] = (int)*(lpSrc - lLineBytes+1);
// -1 -1 -1
// -1 8 -1
// -1 -1 -1
int Tmp=0;
for(int k=0;k<8;k++)
Tmp+=pixel[k];
Tmp=8*((int)*lpSrc)-Tmp;
Tmp+=128;
//Tmp=abs(Tmp);
if(Tmp>255) Tmp=255;
if(Tmp<0) Tmp=0;
*lpDst=(BYTE)Tmp;
}else *lpDst=128;
}
}
CString str=pDoc->GetTitle();
DisplayNewImg(lpNewDIBBits, lLineBytes ,lHeight,"--Laplace");
// 恢复光标
EndWaitCursor();
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdateEdgeLaplace(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
// LOG
void CImageProcessView::OnEdgeLog()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
BeginWaitCursor();
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
const int M=11;
const int N=11;
float **H;
H = new float * [M];
for (int i = 0; i < M; i++) {
H[i] = new float[N] ;
}
/*
H[2][2]=16;
H[2][1]=H[1][2]=H[2][3]=H[3][2]=-2;
H[0][2]=H[2][0]=H[4][2]=H[2][4]=-1;
H[1][1]=H[3][1]=H[1][3]=H[3][3]=-1;*/
float sigma=.8f;
float fsum=0.0f;
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
{
float ftmp=((i-M/2)*(i-M/2)+(j-N/2)*(j-N/2))/(sigma*sigma);
H[i][j]=(ftmp-2)/(sigma*sigma)*exp(-ftmp/2);
fsum+=H[i][j];
}
for (int i = 0; i < M; i++)
{ // TRACE("\n");
for (int j = 0; j < N; j++)
{
H[i][j]/=fsum;
// TRACE("%3.2f\t",H[i][j]);
}
}
MaskCount(H,M,N,true);
CString str=pDoc->GetTitle();
DisplayNewImg(pDoc->m_pDib->m_lpImage, lLineBytes ,lHeight,str+"--LOG");
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpSrc,lpNewDIBBits, lLineBytes * lHeight);
DisplayNewImg(pDoc->m_pDib->m_lpImage, lLineBytes ,lHeight,str);
//判断过零点
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
if(i>0 && i<lHeight-1 && j>0 && j<lWidth-1){
int v=*lpDst+*(lpDst-1)+*(lpDst+lLineBytes)+*(lpDst-1+lLineBytes)-4*128;
int min=v;
int max=v;
v=*lpDst+*(lpDst+1)+*(lpDst+lLineBytes)+*(lpDst+1+lLineBytes)-4*128;
if(v>max)max=v;
else if(v<min) min=v;
v=*lpDst+*(lpDst-1)+*(lpDst-lLineBytes)+*(lpDst-1-lLineBytes)-4*128;
if(v>max)max=v;
else if(v<min) min=v;
v=*lpDst+*(lpDst+1)+*(lpDst-lLineBytes)+*(lpDst+1-lLineBytes)-4*128;
if(v>max)max=v;
else if(v<min) min=v;
if(max>=0 && min<=0)
*lpSrc=0x80;
else
*lpSrc=0;
}
else *lpSrc=0;
}
}
pDoc->SetTitle(str+"--LOG过零点");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
// 恢复光标
EndWaitCursor();
// 释放内存
delete []lpNewDIBBits;
for(int i=0;i<M;i++)
delete []H[i];
delete []H;
}
void CImageProcessView::OnUpdateEdgeLog(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::MaskCount(float** H,int M,int N,bool bEdge)
{
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = lpNewDIBBits + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
if(i>=N/2 && i<lHeight-N/2 && j>=M/2 && j<lWidth-M/2){
float Tmp=0.0f;
for(int m=0;m<M;m++)
for(int n=0;n<N;n++)
Tmp+=*(lpSrc+lLineBytes*(N/2-n)+m-M/2)*H[m][n] ;
if(bEdge) Tmp+=128;
if(Tmp>255) Tmp=255;
if(Tmp<0) Tmp=0;
*lpDst=(unsigned char)Tmp;
}else *lpDst=0;
}
}
// 释放内存
delete []lpNewDIBBits;
}
//获取直线参数(最大值),删除该值附近值,再取最大值为下一条直线
//显示直线为图像点为边缘且满足方向的约束,若无满足点查看邻域(1,-1)是否满足,可去掉一些断点,
//对于角度变化求可能的距离,故速度较快,不考虑方向对角度的限制,提高速度有限
//针对一般图像OnEdgeLog();
//二值Sobel边缘-细化后运行
//图像较大时,由于原点(0,0) 误差较大,改为(cx/2,cy/2)
void CImageProcessView::OnHoughLines()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
//1 save image
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
for (int i =0; i <lHeight; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) -1;
lpDst = lpNewDIBBits + lLineBytes* (lHeight-1-i) -1;
for (int j =0; j <lWidth; j ++){
lpSrc++;lpDst++;
*lpDst=*lpSrc;
if(*lpDst>=220) *lpDst=220;// for display line
}
}
//2 Get edge
if(!m_bTwoValue)
OnEdgeLog();
else
OnEdgeSobel();
//3 Hough transform
//极半径检测分辨率和角度检测分辨率
int radiusResolution=2;
int angleResolution=1;
//线与原点的距离最大
int houghWidth=(int)(sqrt((double)(lWidth*lWidth+lHeight*lHeight)));//+/-
houghWidth /= radiusResolution;
//线的角度在[-90,90]之间,所以申请的累加数组高度为181/angleResolution
int houghHeight=181/angleResolution;
//申请累加数组缓冲区
int *houghBuf=new int[houghWidth*houghHeight];
//init
//清理变换空间累加数组
for(int i=0;i<houghHeight;i++){
for(int j=0;j<houghWidth;j++){
*(houghBuf+i*houghWidth+j)=0;
}
}
const double Deg_Rad=3.1415926/180;
//遍历图像数据
for (int i =max(pDoc->StartPoint.y,1); i <=pDoc->EndPoint.y; i ++){//start: 1
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + max(pDoc->StartPoint.x,1)-1;
// 针对每行图像每列进行操作
for (int j =max(pDoc->StartPoint.x,1); j <=pDoc->EndPoint.x; j ++){
// 指向源DIB第i行,第j个象素的指针
lpSrc++;
//如果是edge,则在变换域的对应各点上加1
if(*lpSrc>=TWOVALUE_H)
//if(i+j==500 && j>=200 && j<=300 )
{
//出现一个目标点
//a代表角度的循环变量,在变换空间累加数组的垂直方向上
for(int a=0;a<houghHeight;a++){
//按照给定变换角度的分辨率,求取角度
double tempA=Deg_Rad*(a-houghHeight/2)*angleResolution;
//double tempA=Deg_Rad*(a)*angleResolution;
//可以建立表,查表;提高速度
//根据当前遍历的角度及x,y值求取对应极半径
double tempR=(i*cos(tempA)+j*sin(tempA))/radiusResolution;//r=xcosa+ysina
//double tempR=((i-houghHeight/2)*cos(tempA)+(houghWidth/2-j)*sin(tempA))/radiusResolution;//r=xcosa+ysina
//与冈萨雷斯书一致,与习惯不同
int r;
if(tempR>0)
r=(int)(tempR+0.5);
else
r=(int)(tempR-0.5);
if(r>=-houghWidth/2 && r<houghWidth/2)
//累加数组累加
*(houghBuf+a*houghWidth+r+houghWidth/2)+=1;//[r][a]
}
}
}
}
//4.save for display Hough Result
int line=houghWidth/4*4;
unsigned char *pHoughImg=new unsigned char[line*houghHeight];
memset(pHoughImg,0,line*houghHeight);
for(int r=0;r<line;r++){
for(int a=0;a<houghHeight;a++){
if(*(houghBuf+a*houghWidth+r)>255)
*(pHoughImg+(houghHeight-a-1)*line+r)=255;
else
*(pHoughImg+(houghHeight-a-1)*line+r)=(BYTE)(*(houghBuf+a*houghWidth+r));
}
}
//display center
for(int i=-5;i<=5;i++)
*(pHoughImg+(houghHeight/2)*line+houghWidth/2+i)=255;
for(int i=-5;i<=5;i++)
*(pHoughImg+(houghHeight/2+i)*line+houghWidth/2)=255;
DisplayNewImg(pHoughImg, line ,houghHeight,"HoughImg:a:(-90,90) r:(-rMax/2,rMax/2)");
//5 累加数组的极大值
const int N_MaxVal=60;
vector< LineInfo> L_Info;
for(int a=5;a<houghHeight;a++){//-90 r == 90 -r
for(int r=0;r<houghWidth;r++){
if(*(houghBuf+a*houghWidth+r)>N_MaxVal){
bool btrue=true;
//判断极值
for(int m=-2;m<=2;m++)
{
for(int n=-2;n<=2;n++)//
{
if(m==0 && n==0)
continue;
if(a+n>=0 && a+n<houghHeight && r+m>=0 && r+m<houghWidth) {
if(*(houghBuf+(a+n)*houghWidth+r+m)>*(houghBuf+a*houghWidth+r))
{
btrue=false;
break;
}
else
if(*(houghBuf+(a+n)*houghWidth+r+m)==*(houghBuf+a*houghWidth+r))
*(houghBuf+(a+n)*houghWidth+r+m)=*(houghBuf+(a+n)*houghWidth+r+m)-1;
}
}
if(!btrue)
break;
}
if(btrue){
LineInfo line;
line.pt=CPoint((a-houghHeight/2)*angleResolution,(r-houghWidth/2)*radiusResolution);
//line.pt=CPoint((a)*angleResolution,(r-houghWidth/2)*radiusResolution);
line.num=*(houghBuf+a*houghWidth+r);
L_Info.push_back(line);
}
}
}
}
//sort
TRACE("\n Edge Infomation:\n");
if(L_Info.size()){
for(int i=0;i<(int)L_Info.size()-1;i++)
{
for(int j=i+1;j<(int)L_Info.size();j++)
if(L_Info[i].num<L_Info[j].num)
{
LineInfo line;
line=L_Info[i];
L_Info[i]=L_Info[j];
L_Info[j]=line;
}
}
for(int i=0;i<(int)L_Info.size() && i<100;i++)
{
CString str;
str.Format("%d: (R: %d theta: %d MaxNum: %d)\n",
i+1,L_Info[i].pt.y, L_Info[i].pt.x,L_Info[i].num);
TRACE("%s\n",str);
}
const int displayN=20;
int no=0;
for(int i=0;i<(int)L_Info.size() && no<displayN;i++)
{
no++;
double angle=L_Info[i].pt.x;
double radius=L_Info[i].pt.y;
//angle的单位是度,此处转换为弧度进行计算
double alfa=angle*Deg_Rad;
if(angle<-45 || angle>45){
for(int x= pDoc->StartPoint.y+1;x<pDoc->EndPoint.y-2;x++){//|
int y=(int)(radius/sin(alfa)-x/tan(alfa)+0.5);
if(y>pDoc->StartPoint.x && y<pDoc->EndPoint.x){
lpSrc=pDoc->m_pDib->m_lpImage+lLineBytes* (lHeight-1-x) +y;
if(*lpSrc>=TWOVALUE_H || *(lpSrc+1)>=TWOVALUE_H || *(lpSrc-1)>=TWOVALUE_H)
*(lpNewDIBBits+lLineBytes* (lHeight-1-x) +y)=220+(BYTE)no;//
}
}
}
else{
for( int y= pDoc->StartPoint.x+1;y<pDoc->EndPoint.x-2;y++){
int x=(int)(radius/cos(alfa)-y*tan(alfa)+0.5);
if(x>pDoc->StartPoint.y && x<pDoc->EndPoint.y){
lpSrc=pDoc->m_pDib->m_lpImage+lLineBytes* (lHeight-1-x) +y;
if(*lpSrc>=TWOVALUE_H || *(lpSrc+lLineBytes)>=TWOVALUE_H || *(lpSrc-lLineBytes)>=TWOVALUE_H)
*(lpNewDIBBits+lLineBytes* (lHeight-1-x) +y)=220+(BYTE)no;
}
}
}
}
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpSrc,lpNewDIBBits, lLineBytes * lHeight);
lpSrc=(unsigned char*)pDoc->m_pDib->m_lpvColorTable;
for (int i=221;i<=255;i++)//
{
*(lpSrc+i*4+1)=((i-220)*20)%256;
*(lpSrc+i*4)=(BYTE)max(255-(i-220)*20,0);
*(lpSrc+i*4+2)=255;//(i-220)*20%255;
}
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"--Hough Lines");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
// 释放内存
delete []lpNewDIBBits;
delete []houghBuf;
delete []pHoughImg;
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdateHoughLines(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//适应于多峰图像
void CImageProcessView::OnSegmentationRegiongrowing()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
//copy img
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
return ;
memcpy( lpNewDIBBits,pDoc->m_pDib->m_lpImage, lLineBytes * lHeight);
unsigned char* lpSrc;
stack <CPoint> ptStack;
//1.获取种子点图像,取亮点(255)
//set 0
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = lpNewDIBBits + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;
if(*lpSrc>254) {
ptStack.push(CPoint(j,i)); //255 种子
*lpSrc=TWOVALUE_H;
}else
*lpSrc=0;
}
}
//2.显示种子图像
DisplayNewImg(lpNewDIBBits,lLineBytes,lHeight,"种子");//display orignal image
unsigned char* lpDst;
const int DIFF=65;
//3.邻域生长
//栈出列,3x3邻域点未处理(0),若与种子点灰度差小则标记(TWOVALUE_H)、进栈;否则设访问过(0x1)
while(!ptStack.empty()){
CPoint Point;
Point=ptStack.top();
ptStack.pop();
//set area
for(int m=1;m>-2;m--)
for(int n=1;n>-2;n--) {
if(m!=0 || n!=0){
int x=Point.x+m;
int y=Point.y+n;
if(y>=pDoc->StartPoint.y && y<=pDoc->EndPoint.y && x>=pDoc->StartPoint.x && x<=pDoc->EndPoint.x){
lpDst =lpNewDIBBits + lLineBytes*(lHeight-1-y) + x;
if(!(*lpDst)){//no visit
lpSrc = pDoc->m_pDib->m_lpImage+ lLineBytes*(lHeight-1-y) + x;
if(*lpSrc>255-DIFF){//
//limit in
ptStack.push(CPoint(x,y));
*lpDst=TWOVALUE_H;
}
}
(*lpDst)|= 0x1;//visted
}
}
}
}
//4.显示结果
CString str=pDoc->GetTitle();
DisplayNewImg(lpNewDIBBits,lLineBytes,lHeight,str+"区域生长");//display orignal image
delete [] lpNewDIBBits;
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdateSegmentationRegiongrowing(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnSegmentationWatershed()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
unsigned char* pMarker;
pMarker=new unsigned char [lLineBytes*lHeight];
if (pMarker == NULL)
{
return ;
}
unsigned char* pOrgIMg;
pOrgIMg=new unsigned char [lLineBytes*lHeight];
if (pOrgIMg == NULL)
{
return ;
}
//save
memcpy( pOrgIMg,pDoc->m_pDib->m_lpImage, lLineBytes * lHeight);
//获取目标亮度阈值(取大一些,保证每个目标都有值即可,无需一个目标一值)
int Hist[256]={0};
GetHistgram(Hist,false);
int GrayTh=0;
int tol=0;
int size=(pDoc->EndPoint.y-pDoc->StartPoint.y+1)*(pDoc->EndPoint.x-pDoc->StartPoint.x+1);
for(GrayTh=0;GrayTh<256;GrayTh++){
tol+=Hist[GrayTh];
if(tol>size*8/10) break;
}
//1)get edge
OnEdgeSobel();
//Filter
GaussFilter(5,5,1.414);
unsigned char* lpSrc;
unsigned char* lpDst;
//设置边界梯度为最大,防止物体在边界上(梯度=0)与背景混合
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
if(i==pDoc->StartPoint.y || i==pDoc->EndPoint.y || j==pDoc->StartPoint.x || j==pDoc->EndPoint.x){
lpDst = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + j;
*lpDst=255;//edge
}
}
}
DisplayNewImg(pDoc->m_pDib->m_lpImage, lLineBytes ,lHeight,"梯度Image");
//初始化标记图置0,0代表未作标记的点(等待生长的点)
memset(pMarker, 0, lLineBytes*lHeight);
//2) set all lable is 0xff
//目标为亮,背景为暗,取目标内部区域为Marker(0xff),保证每个目标都有Marker点
//目标的Marker点:梯度小且亮度大
int GradientTh=40;
TRACE("\nGradientTh=%d,GrayTh=%d\n",GradientTh,GrayTh);
const int initLabel=0xff;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + j;
lpDst = pOrgIMg + lLineBytes* (lHeight-1-i) + j;
if((*lpSrc<GradientTh) && (*lpDst >GrayTh))//目标内部
{int min=*lpSrc;
for(int m=-1;m<2;m++)
for(int n=-1;n<2;n++)
if((*(lpSrc+m*lLineBytes+n))<min)
min=*(lpSrc+m*lLineBytes+n);
if(min<(*lpSrc-2) || min<5)
*(pMarker+ lLineBytes*(lHeight-1-i) + j)=initLabel;
}
}
}
//设置边缘处判断为背景的点为:1
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
if(i==pDoc->StartPoint.y+1 || i==pDoc->EndPoint.y-1 || j==pDoc->StartPoint.x+1 || j==pDoc->EndPoint.x-1){
lpDst = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + j;
lpSrc =pOrgIMg + lLineBytes * (lHeight - 1 - i)+ j;
if(*lpDst<GradientTh/2 && *lpSrc<GrayTh)
*(pMarker+ lLineBytes*(lHeight-1-i) + j)=1;//back
}
}
}
//3 利用连通性标定
//2、3...objectCount物体,消除了过小的目标(可能的噪声点)
int objectCount=1;
bool bProcOver=false;
while(!bProcOver){
bProcOver=true;
int No=0;
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
lpSrc =pMarker + lLineBytes *(lHeight-1-i)+ j;
if(*lpSrc==initLabel)
{ objectCount++;
*lpSrc=(BYTE)objectCount;//set first pt
No++;
bProcOver=false;
break;
}
}
if(!bProcOver)break;
}
if(bProcOver) break;
bool bchg=true;
while(bchg){
bchg=false;
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
lpSrc =pMarker + lLineBytes * (lHeight-1-i)+ j;
if(*lpSrc==objectCount){
for(int m=-1;m<2;m++)
for(int n=-1;n<2;n++)
{ if((*(lpSrc+m*lLineBytes+n))==initLabel){
*(lpSrc+m*lLineBytes+n)=(BYTE)objectCount;
No++;
bchg=true;
}
}
}
}
}
}
if(No<10){//面积过小,标注取消
//delete all seed
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc =pMarker + lLineBytes *(lHeight-1-i)+ j;
if(*lpSrc==objectCount) *lpSrc=0;
}
}
objectCount--;
if(objectCount<0) objectCount=0;
}
}
DisplayNewImg(pMarker, lLineBytes ,lHeight,"Marker Image");
Watershed(pMarker,objectCount);
DisplayNewImg(pOrgIMg, lLineBytes ,lHeight,"Origin Image");
memcpy( pDoc->m_pDib->m_lpImage,pMarker, lLineBytes * lHeight);
pDoc->SetTitle("Watershed");
//如果粘连、或者一个目标多区域描述,可以进一步处理
//将其二值化(门限>0),利用腐蚀、标注、条件膨胀可解决该问题,见物体分离
DisplayObjLabel(objectCount);
EndWaitCursor();
delete []pMarker;
delete []pOrgIMg;
}
//利用各个目标点与背景点(objectCount>0)对其邻域进行处理(相当于膨胀),
//其邻域梯度小(不大于当前值)就并入,否则待以后处理(梯度递增、相当于水位上升)
//利用队列确定梯度小的邻域先处理,每个目标同步处理,梯度小的未处理点(objectCount==0)并入最近的目标
//pMarkImg中所有点处理完为结果,1--表示背景,物体标识为2--objectCount+1
//可以不处理完,阈值上升到(例如128)一定时停止,这时其中还有位处理点(梯度较大),判断为背景
int CImageProcessView::Watershed(unsigned char* pMarkImg,int objectCount)
{
CImageProcessDoc* pDoc = GetDocument();
unsigned char * lpSrc;
unsigned char * lpDst;
if(!objectCount){
MessageBox("无区域种子!","Message");
return 0;
}
//int direct[8][2]={{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};
//水域生长
//每个种子同步生长,在交融处停止;标志区全部被标志
for(int grad=2;grad<128;grad++){//256; 可以调整,大了浪费时间但没有问题
for(int obj=1;obj<=objectCount;obj++){
bool bchg=true;
while(bchg){
bchg=false;
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
lpDst =pMarkImg + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x;
lpSrc =pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
lpDst++;lpSrc++;
if((*lpDst)==obj)
{
for(int m=-1;m<2;m++)
for(int n=-1;n<2;n++)
if(*(lpDst+m*lLineBytes+n)==0)
if((*(lpSrc+m*lLineBytes+n))<=grad){
(*(lpDst+m*lLineBytes+n))=(BYTE)obj;
bchg=true;
}
}
}
}
}
}
}
//obj-- ,0--back,
//未处理点置为背景
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
{
lpSrc =pMarkImg + lLineBytes * (lHeight-1-i)+ j;
if(*lpSrc)
*lpSrc=*lpSrc-1;
}
}
return 0;
}
void CImageProcessView::DisplayObjLabel(int objectCount)
{
//display color
CImageProcessDoc* pDoc = GetDocument();
int dstep=250/objectCount;
unsigned char* lpSrc=(unsigned char*)pDoc->m_pDib->m_lpvColorTable;
for (int i=1;i<=objectCount;i++)//0 --back
{
*(lpSrc+i*4+1)=(BYTE)(i*dstep);
*(lpSrc+i*4)=(BYTE)(255-i*dstep);
*(lpSrc+i*4+2)=(BYTE)((i*20)%256);
}
//get character
long int *pArea;
pArea=new long int [objectCount+1];
for(int i=0;i<=objectCount;i++)
pArea[i]=0;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
{
if(*lpSrc>objectCount) continue;//前面可以不做完,有255
pArea[*lpSrc]++;
lpSrc++;
}
}
long int min=1000;
long int max=0;
long int total=0;
CString str;
str="\n\tNo\t\tArea";
for(int i=1;i<objectCount;i++)//1 --back
{
if(pArea[i]>max)
max=pArea[i];
if(pArea[i]<min)
min=pArea[i];
total+=pArea[i];
CString str1;
str1.Format("\n\t%3d:\t\t%d",i,pArea[i]);
str+=str1;
}
//int aver=total/(objectCount-1);
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
MessageBox(str);
delete []pArea;
}
void CImageProcessView::OnUpdateSegmentationWatershed(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnApplicationThinbycondition()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
// 更改光标形状
BeginWaitCursor();
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
// 3×3相邻区域像素值
unsigned char S[3][3];
bool bOver=false;
while (!bOver)
{
bOver = true;
for(int kk=0;kk<2;kk++){//do step1/step2
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpDst++;lpSrc++;
// 如果源图像中当前点为Backgroung,则跳过
if (*lpSrc==TWOVALUE_L)
continue;
if(i<1 || i>=lHeight-1 && j<1 && j>=lWidth-1)
continue;
// 获得当前点相邻的3×3区域内像素值,白色用1代表,黑色用0代表
for (int m = 0; m < 3; m++)
{
for (int n = 0; n < 3; n++)
{
if (*(lpSrc + (1-m)* lLineBytes + n-1 ) >= TWOVALUE_H)
S[m][n] = 1;
else
S[m][n] = 0;
}
}
// 判断条件一是否成立:
int Num = S[0][0] + S[0][1] + S[0][2] + S[1][0]
+ S[1][2] + S[2][0] + S[2][1] + S[2][2];
if (Num < 2 || Num >6)
{
continue;
}
// 判断条件二是否成立:
Num = 0;
if (S[0][1] == 0 && S[0][2] == 1)
Num++;
if (S[0][2] == 0 && S[1][2] == 1)
Num++;
if (S[1][2] == 0 && S[2][2] == 1)
Num++;
if (S[2][2] == 0 && S[2][1] == 1)
Num++;
if (S[2][1] == 0 && S[2][0] == 1)
Num++;
if (S[2][0] == 0 && S[1][0] == 1)
Num++;
if (S[1][0] == 0 && S[0][0] == 1)
Num++;
if (S[0][0] == 0 && S[0][1] == 1)
Num++;
if (Num != 1)
{
continue;
}
if(kk==0){
// 判断条件三是否成立;
if (S[0][1] * S[1][2] * S[2][1] != 0)
continue;
// 判断条件四是否成立:
if (S[1][2] * S[2][1] * S[1][0] != 0)
continue;
}
else
{ // 判断条件三是否成立;
if (S[0][1] * S[1][2] * S[1][0] != 0)
continue;
// 判断条件四是否成立:
if (S[0][1] * S[2][1] * S[1][0] != 0)
continue;
}
// 如果条件均满足则标注该点
*lpDst = 0;
bOver= false;
}
}
//删除所有标注点
if(!bOver){
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy(lpSrc, lpNewDIBBits, lLineBytes * lHeight);
}
}
}
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"条件-细化");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
EndWaitCursor();
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdateApplicationThinbycondition(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bTwoValue);
}
//获取模板,可调用图像或在图中选择区域
//计算相关系数并显示(-1,1)为(0,255)
//可以方便的利用系数门限确定是否匹配,未做
void CImageProcessView::OnObjectrecognitionCorrelationmatch()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memset( lpNewDIBBits,0, lLineBytes * lHeight);
int tol=0;
for (int m = 0; m <m_ModelHeight; m++)
for (int n =0; n <m_ModelWidth; n++)
tol+=m_pModelData[m*m_ModelWidth+n];
int size=m_ModelHeight*m_ModelWidth;
int ModelMean=tol/size;
int ModelSigm2=0;
for (int m = 0; m <m_ModelHeight; m++)
for (int n =0; n <m_ModelWidth; n++)
ModelSigm2+=((m_pModelData[m*m_ModelWidth+n]-ModelMean)*(m_pModelData[m*m_ModelWidth+n]-ModelMean));
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
if(i-m_ModelHeight/2<0 || i+m_ModelHeight/2>lHeight-1 || j-m_ModelWidth/2<0 || j+m_ModelWidth/2>lWidth-1)
continue;
tol=0;
for (int m = -m_ModelHeight/2; m <=m_ModelHeight/2; m++)
for (int n = -m_ModelWidth/2; n <=m_ModelWidth/2; n++)
tol+=*(lpSrc-m*lLineBytes+n);
int ImgMean=tol/size;
int ImgSigm2=0;
int ImgModel=0;
for (int m = -m_ModelHeight/2; m <=m_ModelHeight/2; m++){
for (int n = -m_ModelWidth/2; n <=m_ModelWidth/2; n++){
ImgSigm2+=((*(lpSrc-m*lLineBytes+n)-ImgMean)*(*(lpSrc-m*lLineBytes+n)-ImgMean));
ImgModel+=((*(lpSrc-m*lLineBytes+n)-ImgMean)*(m_pModelData[(m+m_ModelWidth/2)*
m_ModelWidth+n+m_ModelWidth/2]-ModelMean));
}
}
double r;
r=((double)ImgModel)/sqrt((double)ImgSigm2*ModelSigm2);
*lpDst=(BYTE)min((int)(128+r*128),255);
}
}
//display
DisplayNewImg(lpNewDIBBits,lLineBytes,lHeight,"相关系数(-1,1)-(0,255)");//display orignal image
// 恢复光标
EndWaitCursor();
delete [] lpNewDIBBits;
}
void CImageProcessView::OnUpdateObjectrecognitionCorrelationmatch(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
if(m_pModelData)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnMorphologicalDistancetransform()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
unsigned char* lpSrc;
int* lpDst;
int* pDist;
pDist=new int [lLineBytes*lHeight];
if (pDist == NULL)
{
return ;
}
Distance(pDist);
//display
int MaxDist=0;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =pDist + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
if(*lpDst) {
//*lpDst/=3;
if(*lpDst>MaxDist) MaxDist=*lpDst;
if(*lpDst>255) *lpSrc=255;
else *lpSrc=(BYTE)*lpDst;
}
}
}
lpSrc=(unsigned char*)pDoc->m_pDib->m_lpvColorTable;
for (int i=1;i<=min(MaxDist,255);i++)
{
*(lpSrc+i*4+1)=(i/2%10)*25;*(lpSrc+i*4)=(10-i/2%10)*25;*(lpSrc+i*4+2)=(i/2%6)*50;
}
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"距离");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
EndWaitCursor();
// 释放内存
delete [] pDist;
}
void CImageProcessView::OnUpdateMorphologicalDistancetransform(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bTwoValue);
}
//设置背景距离为0 物体为大值
//顺序扫描,利用邻域值修正(+3,+4 近似欧几里得距离)取最小值改变当前距离值
//再次反向扫描,修改距离
//其值为3倍像数点值
void CImageProcessView::Distance(int * pDist){
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
int* lpDst;
//init 0,max
const int max=10000;//
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =pDist + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
if(*lpSrc) *lpDst=max;
else *lpDst=0;
}
}
const int d1=3;//Euclidean
const int d2=4;
//do left--right top--down
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst =pDist + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpDst++;
if(*lpDst){
int Min=*lpDst;
//d2 d1 d2
//d1 0
if(i>0) Min=min(Min,*(lpDst+lLineBytes)+d1);
if(j>0) Min=min(Min,*(lpDst-1)+d1);
if(i>0 && j>0) Min=min(Min,*(lpDst+lLineBytes-1)+d2);
if(i>0 && j<lWidth-1)Min=min(Min,*(lpDst+lLineBytes+1)+d2);
//set label
*(lpDst)=Min;
}
}
}
//do right--left down--top
for (int i =pDoc->EndPoint.y; i >=pDoc->StartPoint.y; i --){
for (int j =pDoc->EndPoint.x; j>=pDoc->StartPoint.x; j --){
lpDst =pDist + lLineBytes * (lHeight - 1 - i)+ j;
if(*lpDst){
int Min=*lpDst;
// 0 d1
//d2 d1 d2
if(i<lHeight-1) Min=min(Min,*(lpDst-lLineBytes)+d1);
if(j<lWidth-1) Min=min(Min,*(lpDst+1)+d1);
if(i<lHeight-1 && j>0) Min=min(Min,*(lpDst-lLineBytes-1)+d2);
if(i<lHeight-1 && j<lWidth-1)Min=min(Min,*(lpDst-lLineBytes+1)+d2);
//set label
*(lpDst)=Min;
}
}
}
}
void CImageProcessView::OnApplicationSeparateobject()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
// int Obj=TWOVALUE_H;
int Back=TWOVALUE_L;
const int M=31;
const int N=31;
const int r=15;
int **S;
S = new int * [M];
for (int i = 0; i < M; i++) {
S[i] = new int[N] ;
}
for (int i = 0; i < M; i++){
for (int j = 0; j < N; j++)
if((i-M/2)*(i-M/2)+(j-N/2)*(j-N/2)<r*r)
S[i][j]=1;
else S[i][j]=0;
}
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
memcpy( lpNewDIBBits,pDoc->m_pDib->m_lpImage, lLineBytes * lHeight);
//1)腐蚀
Erosion(S,M,N,Back);
DisplayNewImg( pDoc->m_pDib->m_lpImage,lLineBytes,lHeight,"种子图像");
//2) 标记
int ObjNum=Connectedcomponents();
//3)条件膨胀
int obj=-1;
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpDst1;
unsigned char* lpNewDIBBits1;
lpNewDIBBits1=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits1 == NULL)
return ;
memcpy( lpNewDIBBits1,pDoc->m_pDib->m_lpImage, lLineBytes * lHeight);
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = lpNewDIBBits + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
lpDst1 =lpNewDIBBits1 + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;lpDst1++;
if ((*(lpSrc) !=Back) && (*(lpDst) ==Back)){//原图像有值
bool bObj=false;
for (int m = 0; m < M; m++){
for (int n = 0; n < N; n++){
if (S[m][n] == 0)
continue;
if(i+m-M/2>=0 && i+m-M/2<lHeight && j+n -N/2>=0 && j+n-N/2<lWidth)//图像内
if (*(lpDst1 - lLineBytes*(m-M/2) +(n-N/2) ) !=Back)//有非背景点
{ bObj=true;
obj=*(lpDst1 + lLineBytes*(M/2 - m) +(n - N/2));//取当前标记值
m=M;n=N;//out
}
}
}
if(bObj) *lpDst=(BYTE)obj;//设置该目标点为判断的标记值,若多个标记相连,取首个,不同于水域分割,同时生长,也可多次小范围膨胀
}
}
}
//4 显示结果
DisplayObjLabel(ObjNum+1);
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
DisplayNewImg( lpNewDIBBits,lLineBytes,lHeight,"原图像");
// 恢复光标
EndWaitCursor();
delete [] lpNewDIBBits;
delete [] lpNewDIBBits1;
for(int i=0;i<M;i++)
delete []S[i];
delete []S;
}
void CImageProcessView::OnUpdateApplicationSeparateobject(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bTwoValue);
}
void CImageProcessView::OnWatershedprocessGetseed()
{
// TODO: Add your command handler code here
if(m_pModelData)//have image
{
CImageProcessDoc* pDoc = GetDocument();
unsigned char *lpSrc;
unsigned char *lpDst;
unsigned char *lpDst1;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
return ;
memcpy( lpNewDIBBits,m_pModelData, lLineBytes * lHeight);
memset( m_pModelData,0, lLineBytes * lHeight);
const int GradientTh=30;
const int GrayTh=100;
int max=0;
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + j;
lpDst = m_pModelData + lLineBytes* (lHeight-1-i) + j;
lpDst1 = lpNewDIBBits + lLineBytes*i + j;//area, not bmp
if(*lpDst1>max) max=*lpSrc;
if((*lpSrc<GradientTh) && (*lpDst1 <GrayTh)){//目标内部
int min=255;
for(int m=-1;m<2;m++)
for(int n=-1;n<2;n++)
if(min>*(lpSrc+m*lLineBytes+n))
min=*(lpSrc+m*lLineBytes+n);
if(min==*lpSrc)
*lpDst=TWOVALUE_H;
}
}
}
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
lpDst = m_pModelData + lLineBytes* (lHeight-1-i) + j;
lpDst1 = lpNewDIBBits + lLineBytes*i + j;//area, not bmp
if(*lpDst1==max)
*lpDst=TWOVALUE_H;
}
}
DisplayNewImg(m_pModelData,lLineBytes,lHeight,"Marked Point");//
delete [] lpNewDIBBits;
}
else{//select point by hand
m_bWatershedProcGetSeed=true;
m_pModelData=new unsigned char [lWidth*lHeight];
memset(m_pModelData,0,lWidth*lHeight);
}
}
void CImageProcessView::OnUpdateWatershedprocessGetseed(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnWatershedprocessLabelmarked()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
if(m_bWatershedProcGetSeed){
DisplayNewImg( pDoc->m_pDib->m_lpImage,lLineBytes,lHeight,"原图像");
memcpy( pDoc->m_pDib->m_lpImage,m_pModelData , lLineBytes * lHeight);
unsigned char* lpSrc;
unsigned char* lpDst;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = m_pModelData + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst = pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
if ((*(lpSrc) == TWOVALUE_H)){
*(lpDst-1)=TWOVALUE_H;*(lpDst+1)=TWOVALUE_H;
*(lpDst+lLineBytes)=TWOVALUE_H;*(lpDst-lLineBytes)=TWOVALUE_H;
*(lpDst+lLineBytes-1)=TWOVALUE_H;*(lpDst+lLineBytes+1)=TWOVALUE_H;
*(lpDst-lLineBytes-1)=TWOVALUE_H;*(lpDst-lLineBytes+1)=TWOVALUE_H;
}
}
}
}
int ObjNum=Connectedcomponents();
memcpy( m_pModelData ,pDoc->m_pDib->m_lpImage, lLineBytes * lHeight);
if(ObjNum)
DisplayObjLabel(ObjNum+1);
}
void CImageProcessView::OnUpdateWatershedprocessLabelmarked(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_pModelData!=NULL);
}
// Edge img
void CImageProcessView::OnWatershedprocessGetareas()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
BeginWaitCursor();
int objectCount=0;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = m_pModelData + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;
if ((*lpSrc)>objectCount)
objectCount=*(lpSrc);
}
}
//set boarder 255
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;
if (i == pDoc->StartPoint.y || i==pDoc->EndPoint.y || j ==pDoc->StartPoint.x || j ==pDoc->EndPoint.x)
*(lpSrc)=255;
}
}
Watershed(m_pModelData,objectCount);
memcpy( pDoc->m_pDib->m_lpImage,m_pModelData, lLineBytes * lHeight);
pDoc->SetTitle("Watershed");
DisplayObjLabel(objectCount);
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdateWatershedprocessGetareas(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_pModelData!=NULL);
}
void CImageProcessView::OnSegmentationOstu()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
//直方图数组
int lHistogram[256]={0};
GetHistgram(lHistogram,true);
int iThreshold;
//用于计算区域灰度平均值的中间变量
double m1,m2,w1,w2;
double maxD=0.0;
int size=(pDoc->EndPoint.x-pDoc->StartPoint.x+1)*(pDoc->EndPoint.y-pDoc->StartPoint.y+1);
for(iThreshold = 1; iThreshold< 255;iThreshold ++)
{
m1 =0.0;m2=0.0;
w1 =0.0;w2=0.0;
//求两个区域的灰度平均值m and number w
for (int i =0;i <=iThreshold;i++)
{
m1 += lHistogram[i]*i;//
w1 += lHistogram[i];//total num
}
for (int i = iThreshold+1;i < 256;i++)
{
m2 += lHistogram[i]*i;
}
m1/=w1;
m2/=(size-w1);
w1/=size;
w2=1-w1;
double dev_B=w1*w2*(m2-m1)*(m2-m1);
if(dev_B>maxD){
maxD=dev_B;
THRESHOLD=iThreshold;
}
}
Fixedthreshold();
//display Hist
CString str;
str.Format("Treshold(%d)",THRESHOLD);
DisplayDlg dlg;
dlg.pData=&lHistogram[0];
dlg.m_Sizex=256;
dlg.m_Title=str;
dlg.m_Level=1;//draw number
dlg.m_LinePos=THRESHOLD;
dlg.DoModal();
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdateSegmentationOstu(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnSegmentationEntropy()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
//直方图数组
int lHistogram[256]={0};
GetHistgram(lHistogram,true);
int size=(pDoc->EndPoint.x-pDoc->StartPoint.x+1)*(pDoc->EndPoint.y-pDoc->StartPoint.y+1);
int iThreshold;
double maxH=0.0;
for(iThreshold = 1; iThreshold< 255;iThreshold ++)
{
double Pk =0.0;
for (int i =0;i <=iThreshold;i++)
{
Pk+= lHistogram[i];
}
Pk/=size;
if(Pk<0.01 || Pk>0.99) continue;
double H1=0.0;
for (int i =0;i <=iThreshold;i++)
{
double dtmp=((double)lHistogram[i])/size;
if(dtmp>0.0001)
H1+= dtmp*log(dtmp);
}
double H2=0.0;
for (int i = iThreshold+1;i < 256;i++)
{
double dtmp=((double)lHistogram[i])/size;
if(dtmp>0.0001)
H2+= dtmp*log(dtmp);
}
double H=log(Pk)+log(1-Pk)-H1/Pk-H2/(1-Pk);
if(H>maxH){
maxH=H;
THRESHOLD=iThreshold;
}
}
Fixedthreshold();
//display Hist
CString str;
str.Format("Treshold(%d)",THRESHOLD);
DisplayDlg dlg;
dlg.pData=&lHistogram[0];
dlg.m_Sizex=256;
dlg.m_Title=str;
dlg.m_Level=1;//draw number
dlg.m_LinePos=THRESHOLD;
dlg.DoModal();
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdateSegmentationEntropy(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//假设存在2个正态分布,估计其均值、方差
//估计其背景、目标的比例
//依据最小误判概率,解2次方差
void CImageProcessView::OnSegmentationMaxlikelihood()
{
// TODO: Add your command handler code here
// CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
//直方图数组
int lHistogram[256]={0};
GetHistgram(lHistogram,true);
//get meanBack,meanObj
int meanBack,meanObj;
int ABack,AObj;
//get max
ABack=0;
meanBack=-1;
meanObj=-1;
for (int i = 0; i < 256;i++)
{ if(ABack<lHistogram[i]) {
ABack=(int)lHistogram[i];//max
meanBack=i;
}
}
int minH=0;
while(lHistogram[minH]<ABack/20)
minH++;
int maxH=255;
while(lHistogram[maxH]<ABack/20)
maxH--;
//get second max
AObj=0;
int pos=meanBack-(maxH-minH)/3;
int min=lHistogram[meanBack];
if(pos<0) pos=0;
if(meanBack>10){
for (int i =pos ; i>=0 ;i--){
if(min>lHistogram[i])
min=lHistogram[i];
else
{
pos=i;break;
}
if(min<10) {
pos=i;break;
}
}
for (int i = pos; i >=0 ;i--){
if(AObj<lHistogram[i]) {
AObj=(int)lHistogram[i];//max
meanObj=i;
}
}
}
min=lHistogram[meanBack];
pos=meanBack+(maxH-minH)/3;
if(pos>255) pos=255;
if(meanBack<250){
for (int i = pos; i<256 ;i++){
if(min>lHistogram[i])
min=lHistogram[i];
else
{
pos=i;break;
}
if(min<10) {
pos=i;break;
}
}
for (int i = pos; i <256 ;i++){
if(AObj<lHistogram[i]) {
AObj=(int)lHistogram[i];//max
meanObj=i;
}
}
}
if(meanObj<meanBack){
//swap
int tmp=meanBack;
meanBack=meanObj;
meanObj=tmp;
int dtmp=ABack;
ABack=AObj;
AObj=dtmp;
}
TRACE("\nmeanBack=%d,(%d),meanObj=%d,(%d) posStep=%d\n\n",meanBack,ABack,meanObj,AObj,(maxH-minH)/3);
//get segm
double segmBack;
pos=meanBack;
bool bfind=false;
if(meanBack>10){
while(pos>0 && !bfind){
pos--;
double dtmp=((double)lHistogram[pos])/ABack;
if(dtmp<exp(-0.5))
bfind=true;
}
}
else{
while(pos<255 && !bfind){
pos++;
double dtmp=((double)lHistogram[pos])/ABack;
if(dtmp<exp(-0.5))
bfind=true;
}
}
segmBack=abs(pos-meanBack);
if(segmBack<3.0)segmBack=3.0;//不连续直方图
else if(segmBack>meanObj-meanBack)
segmBack=(meanObj-meanBack)/3;
double segmObj;
pos=meanObj;
bfind=false;
if(meanObj>255-10){
while(pos>0 && !bfind){
pos--;
double dtmp=((double)lHistogram[pos])/AObj;
if(dtmp<exp(-0.5))
bfind=true;
}
}
else
{while(pos<255 && !bfind){
pos++;
double dtmp=((double)lHistogram[pos])/AObj;
if(dtmp<exp(-0.5))
bfind=true;
}
}
segmObj=abs(pos-meanObj);
if(segmObj<3.0)segmObj=3.0;//不连续直方图
else if(segmObj>meanObj-meanBack)
segmObj=(meanObj-meanBack)/3;
TRACE("\nmeanBack=%d,segmBack=%3.1f,meanObj=%d,segmObj=%3.1f",meanBack,segmBack,meanObj,segmObj);
//get Th--比例
double Th=AObj*segmObj/(AObj*segmObj+ABack*segmBack);
//get iThreshold
double A,B,C;
A=segmObj*segmObj-segmBack*segmBack;
B=2.0*(-meanBack*segmObj*segmObj+meanObj*segmBack*segmBack);
C=meanBack*meanBack*segmObj*segmObj-meanObj*meanObj*segmBack*segmBack
-2.0*segmObj*segmObj*segmBack*segmBack*log(segmObj/segmBack*(1.0-Th)/Th);
if(A>0.01 || A<-0.01){ //A!=0
double t1=(-B+sqrt(B*B-4*A*C))/(2.0*A);
double t2=(-B-sqrt(B*B-4*A*C))/(2.0*A);
if(t1>meanBack && t1<meanObj) THRESHOLD=(int)(t1+0.5);
if(t2>meanBack && t2<meanObj) THRESHOLD=(int)(t2+0.5);
}else if(B>0.01 || B<-0.01)
THRESHOLD=(int)max((-C/B+0.5),0.0);
else
THRESHOLD=0;//err
Fixedthreshold();
//display Hist
CString str;
str.Format("Treshold(%d)",THRESHOLD);
DisplayDlg dlg;
dlg.pData=&lHistogram[0];
dlg.m_Sizex=256;
dlg.m_Title=str;
dlg.m_Level=1;//draw number
dlg.m_LinePos=THRESHOLD;
dlg.DoModal();
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdateSegmentationMaxlikelihood(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//目标为黑,适合扫描文字提取,可克服明亮程度的不同
//利用邻域的最大最小值获取阈值
void CImageProcessView::OnSegmentationLocalthresholding()
{
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
unsigned char* lpSrc;
unsigned char* lpDst;
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
const int M=5;
const int N=5;
int minrange=255/5;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;
lpDst++;
if(i>=M/2 && i<lHeight-M/2 && j>=N/2 && j<lWidth-N/2){
int min=255;
int max=0;
for(int m=-M/2;m<=M/2;m++)
for(int n=-N/2;n<=N/2;n++)
{
if(*(lpSrc+m*lLineBytes+n)>max)
max=*(lpSrc+m*lLineBytes+n);
if(*(lpSrc+m*lLineBytes+n)<min)
min=*(lpSrc+m*lLineBytes+n);
int range=max-min;
int T;
if(range>minrange)
T=(min+max)/2;
else
T=max-min/2;//all white
if(*lpSrc>T)
*(lpDst)=255;
else
*(lpDst)=0;
}
}
else
*(lpDst)=255;//back
}
}
DisplayNewImg(lpNewDIBBits,lLineBytes,lHeight,"自适应局部阈值");//
// 释放内存
delete []lpNewDIBBits;
EndWaitCursor();
}
void CImageProcessView::OnUpdateSegmentationLocalthresholding(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnApplicationParallelthin()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
// 更改光标形状
BeginWaitCursor();
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
BOOL bOver=false;
while(!bOver){
bOver=true;
//North:
//x 0 x
//x (1) x
//x 1 x
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
lpDst++;lpSrc++;
bool A0,A1,A2,A3,A4,A5,A6,A7,A8;
A0 = *lpSrc>0;
A1 = *(lpSrc+1)>0;
A2 = *(lpSrc+lLineBytes+1)>0;
A3 = *(lpSrc+lLineBytes)>0;
A4 = *(lpSrc+lLineBytes-1)>0;
A5 = *(lpSrc-1)>0;
A6 = *(lpSrc - lLineBytes-1)>0;
A7 = *(lpSrc - lLineBytes)>0;
A8 = *(lpSrc - lLineBytes+1)>0;
if(A0 && !A3 && A7){
int sigm=A1+A2+A3+A4+A5+A6+A7+A8;
int chi=(A1!=A3)+(A3!=A5)+(A5!=A7)+(A7!=A1)
+2*((A1 && A2 && !A3)+(!A3 && A4 && !A5)
+(!A5 && A6 && !A7)+(!A7 && A8 && !A1));
if((chi==2) && (sigm!=1)){
*lpDst = TWOVALUE_L;
bOver=false;
}
}
}
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy(lpSrc, lpNewDIBBits, lLineBytes * lHeight);
//South:
//x 1 x
//x (1) x
//x 0 x
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
lpDst++;lpSrc++;
bool A0,A1,A2,A3,A4,A5,A6,A7,A8;
A0 = *lpSrc>0;
A1 = *(lpSrc+1)>0;
A2 = *(lpSrc+lLineBytes+1)>0;
A3 = *(lpSrc+lLineBytes)>0;
A4 = *(lpSrc+lLineBytes-1)>0;
A5 = *(lpSrc-1)>0;
A6 = *(lpSrc - lLineBytes-1)>0;
A7 = *(lpSrc - lLineBytes)>0;
A8 = *(lpSrc - lLineBytes+1)>0;
if(A0 && !A7 && A3){
int sigm=A1+A2+A3+A4+A5+A6+A7+A8;
int chi=(A1!=A3)+(A3!=A5)+(A5!=A7)+(A7!=A1)
+2*((A1 && A2 && !A3)+(!A3 && A4 && !A5)
+(!A5 && A6 && !A7)+(!A7 && A8 && !A1));
if((chi==2) && (sigm!=1)){
*lpDst = TWOVALUE_L;
bOver=false;
}
}
}
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy(lpSrc, lpNewDIBBits, lLineBytes * lHeight);
//East:
//x x x
//0 (1) 1
//x x x
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
lpDst++;lpSrc++;
bool A0,A1,A2,A3,A4,A5,A6,A7,A8;
A0 = *lpSrc>0;
A1 = *(lpSrc+1)>0;
A2 = *(lpSrc+lLineBytes+1)>0;
A3 = *(lpSrc+lLineBytes)>0;
A4 = *(lpSrc+lLineBytes-1)>0;
A5 = *(lpSrc-1)>0;
A6 = *(lpSrc - lLineBytes-1)>0;
A7 = *(lpSrc - lLineBytes)>0;
A8 = *(lpSrc - lLineBytes+1)>0;
if(A0 && !A5 && A1){
int sigm=A1+A2+A3+A4+A5+A6+A7+A8;
int chi=(A1!=A3)+(A3!=A5)+(A5!=A7)+(A7!=A1)
+2*((A1 && A2 && !A3)+(!A3 && A4 && !A5)
+(!A5 && A6 && !A7)+(!A7 && A8 && !A1));
if((chi==2) && (sigm!=1)){
*lpDst = TWOVALUE_L;
bOver=false;
}
}
}
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy(lpSrc, lpNewDIBBits, lLineBytes * lHeight);
//West:
//x x x
//1 (1) 0
//x x x
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++){
lpDst++;lpSrc++;
bool A0,A1,A2,A3,A4,A5,A6,A7,A8;
A0 = *lpSrc>0;
A1 = *(lpSrc+1)>0;
A2 = *(lpSrc+lLineBytes+1)>0;
A3 = *(lpSrc+lLineBytes)>0;
A4 = *(lpSrc+lLineBytes-1)>0;
A5 = *(lpSrc-1)>0;
A6 = *(lpSrc - lLineBytes-1)>0;
A7 = *(lpSrc - lLineBytes)>0;
A8 = *(lpSrc - lLineBytes+1)>0;
if(A0 && !A1 && A5){
int sigm=A1+A2+A3+A4+A5+A6+A7+A8;
int chi=(A1!=A3)+(A3!=A5)+(A5!=A7)+(A7!=A1)
+2*((A1 && A2 && !A3)+(!A3 && A4 && !A5)
+(!A5 && A6 && !A7)+(!A7 && A8 && !A1));
if((chi==2) && (sigm!=1)){
*lpDst = TWOVALUE_L;
bOver=false;
}
}
}
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy(lpSrc, lpNewDIBBits, lLineBytes * lHeight);
}
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"细化");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
EndWaitCursor();
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdateApplicationParallelthin(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bTwoValue);
}
//1. select sub_image(2x2) ,it can improve accuray
// not process ; ==select area by hand
//2 select the origin at the center of area
//3 let rho>10
//4 Sobel
//5 count x0,y0 set list and count times
//6 sort by num
//7 union by pt (near as 1)
//8 display positions (liness)
//delete last position (around )--not process
//9 use center and point(x0,y0) can get line function
// not process!
//10 get near line (function) point ,then improve accuray by 最小二乘法拟合
void CImageProcessView::OnHoughFontofnormal()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
BeginWaitCursor();
//err! must be 全局变量
/*struct Info{
CPoint pt;
int num;
};*/
CList<LineInfo,LineInfo&> myList;
LineInfo info;
int pixel[8];
CPoint center=CPoint((pDoc->EndPoint.x-pDoc->StartPoint.x+1)/2+pDoc->StartPoint.x,(pDoc->EndPoint.y-pDoc->StartPoint.y+1)/2+pDoc->StartPoint.y);
const int TH=280;//need be changed::gantrycrane
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;
if(i>0 && i<lHeight-1 && j>0 && j<lWidth-1){
pixel[0] = (int)*(lpSrc+lLineBytes-1);
pixel[1] = (int)*(lpSrc+lLineBytes);
pixel[2] = (int)*(lpSrc+lLineBytes+1);
pixel[3] = (int)*(lpSrc-1);
pixel[4] = (int)*(lpSrc+1);
pixel[5] = (int)*(lpSrc - lLineBytes-1);
pixel[6] = (int)*(lpSrc - lLineBytes);
pixel[7] = (int)*(lpSrc - lLineBytes+1);
// 1 2 1
// 0 0 0
// -1 -2 -1
int gy=pixel[0]+2*pixel[1]+pixel[2]-pixel[5]-2*pixel[6]-pixel[7];
// -1 0 1
// -2 0 2
// -1 0 1
int gx=pixel[2]+2*pixel[4]+pixel[7]-pixel[0]-2*pixel[3]-pixel[5];
int result =(int)(sqrt(double(gx*gx+gy*gy)));
//edge
if(result>TH){
double v=((double)((j-center.x)*gx+(center.y-i)*gy))/(gx*gx+gy*gy);
int x0=(int)(v*gx);
int y0=(int)(v*gy);
bool bfind=false;
POSITION pos=myList.GetHeadPosition();
while(pos!=NULL)
{
POSITION tmp_pos=pos;
info=myList.GetNext(pos);
if(info.pt==CPoint(x0,y0))
{
bfind=true;
pos=tmp_pos;
break;
}
}
if(!bfind){
info.pt=CPoint(x0,y0);
info.num=1;
myList.AddTail(info);
}
else{
info.num++;
myList.SetAt(pos,info);//++
}
}
}
}
}
//watch data
//sort
for(POSITION pos1=myList.GetHeadPosition();pos1!=NULL;myList.GetNext(pos1))
for(POSITION pos2=myList.GetHeadPosition();pos2!=NULL;myList.GetNext(pos2)){
LineInfo info1=myList.GetAt(pos1);
LineInfo info2=myList.GetAt(pos2);
if(info1.num>info2.num){
LineInfo tmp=info1;
myList.SetAt(pos1,info2);//++
myList.SetAt(pos2,tmp);//++
}
}
POSITION pos = myList.GetHeadPosition();
TRACE("\nBefore Union:\nData(%d):\n",myList.GetCount());
while(pos!=NULL){
info=myList.GetNext(pos);
TRACE("\t(%3d,%3d)=%3d",info.pt.x,info.pt.y,info.num);
if(info.num<30) break;
}
TRACE("\n\n");
//union
for(POSITION pos1=myList.GetHeadPosition();pos1!=NULL;myList.GetNext(pos1))
for(POSITION pos2=myList.GetHeadPosition();pos2!=NULL;myList.GetNext(pos2)){
LineInfo info1=myList.GetAt(pos1);
LineInfo info2=myList.GetAt(pos2);
if(info1.pt!= info2.pt){
if(abs(info1.pt.x-info2.pt.x)<3 && abs(info1.pt.y-info2.pt.y)<3){ //near pt
info1.num+=info2.num;
myList.SetAt(pos1,info1);//
POSITION tmp=pos2;
myList.GetPrev(pos2);
myList.RemoveAt(tmp);//
}
}
}
pos = myList.GetHeadPosition();
TRACE("\nAfter Union:\nData(%d):\n",myList.GetCount());
while(pos!=NULL){
info=myList.GetNext(pos);
TRACE("\t(%3d,%3d)=%3d",info.pt.x,info.pt.y,info.num);
if(info.num<50) break;
}
TRACE("\n\n");
//find pt
pos = myList.GetHeadPosition();
CPoint pt;
while(pos!=NULL){
info=myList.GetNext(pos);//not be sorted now
if(info.num>50){//line length>50
pt=info.pt;
pt.x+=center.x;
pt.y=(center.y-pt.y);
//display x0,y0
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-pt.y) + pt.x;
*(lpSrc-2)=255;*(lpSrc-1)=255;*(lpSrc)=255;*(lpSrc+1)=255;*(lpSrc+2)=255;
*(lpSrc-2*lLineBytes)=255;*(lpSrc-lLineBytes)=255;*(lpSrc+lLineBytes)=255;*(lpSrc+2*lLineBytes)=255;
}
}
//display Center
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-center.y) + center.x;
*(lpSrc-1)=255;*(lpSrc)=255;*(lpSrc+1)=255;
*(lpSrc-lLineBytes-1)=255;*(lpSrc-lLineBytes)=255;*(lpSrc-lLineBytes+1)=255;
*(lpSrc+lLineBytes-1)=255;*(lpSrc+lLineBytes)=255;*(lpSrc+lLineBytes+1)=255;
LPRGBQUAD pDibQuad = (LPRGBQUAD) pDoc->m_pDib->m_lpvColorTable+255;
pDibQuad->rgbRed = 255; pDibQuad->rgbGreen =0;pDibQuad->rgbBlue = 0;
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"The Foot of Nomal Method");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
EndWaitCursor();
}
void CImageProcessView::OnUpdateHoughFontofnormal(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//1.选择一个圆处理
//可以进行二值化,标定再处理,获取多个圆---未完成
//2提取边缘Sobel
//3获取每行起始、终止边缘的中值
//4获取每列起始、终止边缘的中值
//5 取峰值获得圆心
//6 对于边缘点计算半径均值
//7 作图形显示圆心、圆
void CImageProcessView::OnCircledetectionChordbisectionalg()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
// 更改光标形状
BeginWaitCursor();
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
//soble
OnEdgeSobel();
const int TH=250;//coins if no use OnEdgeSobel();:400
int *ptx;
ptx=new int [lWidth];
memset(ptx,0,lWidth*sizeof(int));
//获取行中心点
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
bool bfind=false;
int pt1=0;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x && !bfind; j ++){
lpSrc++;
if(*lpSrc>TH){
pt1=j;
bfind=true;
}
}
if(bfind){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->EndPoint.x+1;
bfind=false;
int pt2=0;
for (int j =pDoc->EndPoint.x; j >=pDoc->StartPoint.x && !bfind; j --){
lpSrc--;
if(*lpSrc>TH){
pt2=j;
bfind=true;
}
}
ptx[(pt2+pt1)/2]++;
if((pt2+pt1%2)) ptx[(pt2+pt1)/2+1]++;//后面取最大值,将其赋值,保证峰值点
}
}
int *pty;
pty=new int [lHeight];
memset(pty,0,lHeight*sizeof(int));
//获取列中心点
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
bool bfind=false;
int pt1=0;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y && !bfind; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) +j;
if(*lpSrc>TH){
pt1=i;
bfind=true;
}
}
if(bfind){
bfind=false;
int pt2=0;
for (int i =pDoc->EndPoint.y; i >=pDoc->StartPoint.y && !bfind; i --){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) +j;
if(*lpSrc>TH){
pt2=i;
bfind=true;
}
}
pty[(pt2+pt1)/2]++;
if((pt2+pt1%2)) pty[(pt2+pt1)/2+1]++;//后面取最大值,将其赋值,保证峰值点
}
}
//中心点:最大值
CPoint center(CPoint(0,0));
int max1=0;
for(int i=0;i<lWidth;i++)
if(ptx[i]>max1){
max1=ptx[i];
center.x=i;
}
int max2=0;
for(int i=0;i<lHeight;i++)
if(pty[i]>max2){
max2=pty[i];
center.y=i;
}
delete []ptx;
delete []pty;
TRACE("\n\nCenter(%d,%d) max(%d,%d)\n\n",center.x,center.y,max1,max2);
//get radius
int num=0;
double addRadius=0;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x ; j ++){
lpSrc++;
if(*lpSrc>TH){
double r=sqrt(double((j-center.x)*(j-center.x)+(i-center.y)*(i-center.y)));
num++;
addRadius+=r;
}
}
}
double Radius=0;
if(num)
Radius=addRadius/num;
TRACE("\n\nRadiu(%3.1f),edge num=%d\n",Radius,num);
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy(lpSrc, lpNewDIBBits, lLineBytes * lHeight);//original image
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"Circle Detection");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
CString msg;
msg.Format("圆心坐标(%d,%d)半径(%3.1f)\n",center.x,center.y,Radius);
MessageBox(msg,"Message");
//在显示图形前,等待屏幕刷新完成
//display
CDC *pdc=GetDC();
CPen Redpen;
Redpen.CreatePen(PS_DOT, 1, RGB(255,0,0));
pdc->SelectObject(Redpen);
int radius=(int)(Radius+1.5);//普遍小,补偿?
Arc(pdc->m_hDC,
center.x-radius,
center.y-radius,
center.x+radius,
center.y+radius,
center.x+radius,
center.y,
center.x+radius,
center.y
);
Rectangle(pdc->m_hDC,center.x-1,center.y-1,center.x+1,center.y+1);
DeleteObject(Redpen);
EndWaitCursor();
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdateCircledetectionChordbisectionalg(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//1.选择一个圆处理
//物体为亮,否则圆心计算公式需要调整
//可以处理半个圆、
//多个圆----未完成
//2 Sobel
//3 估计半径
// 半径递增,取中心点,取最大数下为估计半径。误差+/-1 pixel
//半径不必整数,可初调后精调,边缘的大小可对中心数加权,提高精度—未完成
//4 中心点精确估计0.1pixel(书上介绍?)
//边缘的大小对中心数加权,提高精度
//梯度计算重复多次,可利用存储gx、gy降低计算量
//5 显示圆、圆心
void CImageProcessView::OnCircledetectionAcurr()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
BeginWaitCursor();
//估计半径
int pixel[8];
const int Rmin=20;
const int Rmax=35;
CList<LineInfo,LineInfo&> myList;
LineInfo info;
const int TH=400;//coins :need be changed
int Max=0;//num
int rMax=0;//半径
CPoint center;
for(int R=Rmin;R<=Rmax;R++){
myList.RemoveAll();
//get List---info(x0,y0,num) circle center \point num
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;
if(i>0 && i<lHeight-1 && j>0 && j<lWidth-1){
pixel[0] = (int)*(lpSrc+lLineBytes-1);
pixel[1] = (int)*(lpSrc+lLineBytes);
pixel[2] = (int)*(lpSrc+lLineBytes+1);
pixel[3] = (int)*(lpSrc-1);
pixel[4] = (int)*(lpSrc+1);
pixel[5] = (int)*(lpSrc - lLineBytes-1);
pixel[6] = (int)*(lpSrc - lLineBytes);
pixel[7] = (int)*(lpSrc - lLineBytes+1);
// 1 2 1
// 0 0 0
// -1 -2 -1
int gy=pixel[0]+2*pixel[1]+pixel[2]-pixel[5]-2*pixel[6]-pixel[7];
// -1 0 1
// -2 0 2
// -1 0 1
int gx=pixel[2]+2*pixel[4]+pixel[7]-pixel[0]-2*pixel[3]-pixel[5];
double g =sqrt(double(gx*gx+gy*gy));
//edge
if(g>TH){
double v=R/g;
int x0=j+(int)(v*gx+0.5);//于书不同!
int y0=i-(int)(v*gy+0.5);
bool bfind=false;
POSITION pos=myList.GetHeadPosition();
while(pos!=NULL)
{
POSITION tmp_pos=pos;
info=myList.GetNext(pos);
if(info.pt==CPoint(x0,y0))
{
bfind=true;
pos=tmp_pos;
break;
}
}
if(!bfind){
info.pt=CPoint(x0,y0);
info.num=1;
myList.AddTail(info);
}
else{
info.num++;
myList.SetAt(pos,info);//++
}
}
}
}
}
//sort
for(POSITION pos1=myList.GetHeadPosition();pos1!=NULL;myList.GetNext(pos1))
for(POSITION pos2=myList.GetHeadPosition();pos2!=NULL;myList.GetNext(pos2)){
LineInfo info1=myList.GetAt(pos1);
LineInfo info2=myList.GetAt(pos2);
if(info1.num>info2.num){
LineInfo tmp=info1;
myList.SetAt(pos1,info2);//++
myList.SetAt(pos2,tmp);//++
}
}
//union
for(POSITION pos1=myList.GetHeadPosition();pos1!=NULL;myList.GetNext(pos1))
for(POSITION pos2=myList.GetHeadPosition();pos2!=NULL;myList.GetNext(pos2)){
LineInfo info1=myList.GetAt(pos1);
LineInfo info2=myList.GetAt(pos2);
if(info1.pt!= info2.pt){
if(abs(info1.pt.x-info2.pt.x)<3 && abs(info1.pt.y-info2.pt.y)<3){ //near pt
info1.num+=info2.num;
myList.SetAt(pos1,info1);//
POSITION tmp=pos2;
myList.GetPrev(pos2);
myList.RemoveAt(tmp);//
}
}
}
//
//POSITION pos = myList.GetHeadPosition();
//TRACE("\nAfter Union:\nR=%dData(%d):\n",R,myList.GetCount());
//while(pos!=NULL){
// info=myList.GetNext(pos);
// TRACE("\t(%3d,%3d)=%3d",info.pt.x,info.pt.y,info.num);
// if(info.num<30) break;
//}
//TRACE("\n\n");
info=myList.GetHead();
if(Max<info.num){
Max=info.num;
rMax=R;
center=info.pt;
}
}
TRACE("\n圆心坐标(%3d,%3d)\t 半径(%3d) 数目(%d)\n",center.x,center.y,rMax,Max);
//中心点精确估计
int R=rMax;
double num=0;
double totX=0;
double totY=0;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;
if(i>0 && i<lHeight-1 && j>0 && j<lWidth-1){
pixel[0] = (int)*(lpSrc+lLineBytes-1);
pixel[1] = (int)*(lpSrc+lLineBytes);
pixel[2] = (int)*(lpSrc+lLineBytes+1);
pixel[3] = (int)*(lpSrc-1);
pixel[4] = (int)*(lpSrc+1);
pixel[5] = (int)*(lpSrc - lLineBytes-1);
pixel[6] = (int)*(lpSrc - lLineBytes);
pixel[7] = (int)*(lpSrc - lLineBytes+1);
// 1 2 1
// 0 0 0
// -1 -2 -1
int gy=pixel[0]+2*pixel[1]+pixel[2]-pixel[5]-2*pixel[6]-pixel[7];
// -1 0 1
// -2 0 2
// -1 0 1
int gx=pixel[2]+2*pixel[4]+pixel[7]-pixel[0]-2*pixel[3]-pixel[5];
double g =sqrt(double(gx*gx+gy*gy));
//edge
if(g>TH){
double v=R/g;
double x0=j+v*gx;
double y0=i-v*gy;
double s=sqrt((x0-j)*(x0-j)+(y0-i)*(y0-i));
if(abs(s-R)<5){
//num++;
double w=g/TH;
num+=w;//边缘峰值加权
totX+=(j-(R/s)*(j-x0))*w;
totY+=(i-(R/s)*(i-y0))*w;
}
}
}
}
}
if(num>1.0){
TRACE("\n中心点精确估计后\n圆心坐标(%3.1f,%3.1f)\t 半径(%3d) 数目(%3.1f)\n",totX/num,totY/num,rMax,num);
}
//display
// MessageBox(msg,"Message");
//在显示图形前,等待屏幕刷新完成
//display
CDC *pdc=GetDC();
CPen Redpen;
Redpen.CreatePen(PS_DOT, 1, RGB(255,0,0));
pdc->SelectObject(Redpen);
int radius=R;
center.x=(int)(totX/num+0.5);
center.y=(int)(totY/num+0.5);
Arc(pdc->m_hDC,
center.x-radius,
center.y-radius,
center.x+radius,
center.y+radius,
center.x+radius,
center.y,
center.x+radius,
center.y
);
Rectangle(pdc->m_hDC,center.x-1,center.y-1,center.x+1,center.y+1);
DeleteObject(Redpen);
EndWaitCursor();
}
void CImageProcessView::OnUpdateCircledetectionAcurr(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnHistgramGrayBar()
{
// TODO: Add your command handler code here
// CImageProcessDoc* pDoc = GetDocument();
int Hist[256]={0};
GetHistgram(Hist,false);
pDlg=new DisplayDlg();//
pDlg->Create(IDD_DISPLAY_DIALOG,this);
//pDlg->pData=&Hist[0];//动态时,数据传不过去
pDlg->pData=new int [256];
memcpy(pDlg->pData,Hist,256*sizeof(int));
pDlg->m_Sizex=256;
pDlg->m_LinePos=100;
pDlg->m_Title=_T("灰度直方图");
pDlg->m_Level=1;
pDlg->bBar=true;
pDlg->ShowWindow(SW_SHOW);
}
void CImageProcessView::OnUpdateHistgramGrayBar(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnHistgramRgbbar()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
int m_nHistRGB[256*3]={0};
unsigned char *lpSrc;
// 计算各个灰度值的计数,即得到直方图
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes*(lHeight-1-i) + j*3;//down -up
// 计数加1
m_nHistRGB[*(lpSrc+2)]++;//R
m_nHistRGB[256+*(lpSrc+1)]++;//G
m_nHistRGB[256*2+*(lpSrc)]++;//B
}
pDlg=new DisplayDlg();//
pDlg->Create(IDD_DISPLAY_DIALOG,this);
pDlg->pData=new int [256*3];
memcpy(pDlg->pData, m_nHistRGB,256*3*sizeof(int));
pDlg->m_Sizex=256;
pDlg->m_Title="彩色RGB直方图";
pDlg->m_Level=3;//draw number
pDlg->m_LinePos=0;
pDlg->bBar=true;
pDlg->ShowWindow(SW_SHOW);
}
void CImageProcessView::OnUpdateHistgramRgbbar(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==24)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnHistgramHsibar()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
int m_nHistHSI[256*3]={0};
unsigned char *lpSrc;
// 计算各个灰度值的计数,即得到直方图
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes*(lHeight-1-i) + j*3;//down -up
RGB Rgb;
HSI Hsi;
Rgb.b=*lpSrc;Rgb.g=*(lpSrc+1);Rgb.r=*(lpSrc+2);
RgbtoHsi(&Rgb, &Hsi);
unsigned int H,S,I;
H=(unsigned int) (Hsi.Hue/360.0*255.0);
S=(unsigned int) (Hsi.Saturation*255.0);
I=(unsigned int) (Hsi.Intensity*255.0);
// 计数加1
m_nHistHSI[H]++;//H
m_nHistHSI[256+S]++;//S
m_nHistHSI[256*2+I]++;//I
}
pDlg=new DisplayDlg();//
pDlg->Create(IDD_DISPLAY_DIALOG,this);
pDlg->pData=new int [256*3];
memcpy(pDlg->pData, m_nHistHSI,256*3*sizeof(int));
pDlg->m_Sizex=256;
pDlg->m_Title="彩色HSI直方图";
pDlg->m_Level=3;//draw number
pDlg->m_LinePos=0;
pDlg->bBar=true;
pDlg->ShowWindow(SW_SHOW);
}
void CImageProcessView::OnUpdateHistgramHsibar(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==24)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnObjectrecognitionPlesseycornerdetector()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
// 更改光标形状
BeginWaitCursor();
//1 filter
GaussFilter(7,7,1.0);//-3*1.0--3*1.0
//2 difference
double* Dx;
double* Dy;
Dx=new double [lLineBytes*lHeight];
Dy=new double [lLineBytes*lHeight];
_ASSERT(Dx != NULL);//false
_ASSERT(Dy != NULL);//false
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
unsigned char *lpSrc = pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
double* pDx = Dx + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
double* pDy = Dy + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;pDx++;pDy++;
if(*lpSrc==255)
*lpSrc=254;//for display out
if(i>1 && i<lHeight-2 && j>1 && j<lWidth-2){
*pDx=*(lpSrc-1)-*(lpSrc+1);
*pDy=*(lpSrc+lLineBytes)-*(lpSrc-lLineBytes);
}
else
{
*pDx=*pDy=0;
}
}
}
//3 Dx2=Dx*Dx Dy2 Dxy
double* Dxy;
Dxy=new double [lLineBytes*lHeight];
_ASSERT(Dxy != NULL);//false
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
double* pDx = Dx + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
double* pDy = Dy + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
double* pDxy = Dxy + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
pDxy++;pDx++;pDy++;
*pDxy=(*pDx)*(*pDy);
*pDx=(*pDx)*(*pDx);
*pDy=(*pDy)*(*pDy);
}
}
//4 filter
GaussFilter(Dx,25,25,4.0);
GaussFilter(Dy,25,25,4.0);
GaussFilter(Dxy,25,25,4.0);
for test
//for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
// unsigned char *lpSrc = pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
// double* pDx = Dx + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
// double* pDy = Dy + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
// double* pDxy = Dxy + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
// for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
// lpSrc++;pDx++;pDy++;pDxy++;
// *lpSrc=min(255,max(0,(*pDxy)/5+128));
//
// }
//}
kappa = 0.04 ... 0.06, at most 0.25 .
const double kappa = 0.04;
const double CxyTh = 250000;
double maxCxy=0;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
unsigned char *lpSrc = pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
double* pDx = Dx + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
double* pDy = Dy + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
double* pDxy = Dxy + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;pDx++;pDy++;pDxy++;
double A=*pDx;
double B=*pDy;
double C=*pDxy;
double Cxy=(A*B-C*C)-kappa*(A+B)*(A+B);
if(Cxy>maxCxy)
maxCxy=Cxy;
if(Cxy>CxyTh)
*lpSrc=255;
}
}
TRACE("\nmaxCxy=%6.1f\n",maxCxy);
//display
unsigned char* lpSrc=(unsigned char*)pDoc->m_pDib->m_lpvColorTable;
*(lpSrc+255*4+1)=0;*(lpSrc+255*4)=0;*(lpSrc+255*4+2)=255;
//
// 释放内存
delete []Dx;
delete []Dy;
delete []Dxy;
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"角点检测");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
EndWaitCursor();
}
void CImageProcessView::OnUpdateObjectrecognitionPlesseycornerdetector(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnEdgeCanny()
{
// TODO: 在此添加命令处理程序代码
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpImg;
// 指向转置图像对应象素的指针
unsigned char* lpMag;
unsigned char* lpEdge;
// 指向转置图像的指针
unsigned char* lpNewDIBBits;
unsigned char* lpNewDIBBits1;
// 暂时分配内存,以保存新图像
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
// 判断是否内存分配失败
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
// 暂时分配内存,以保存新图像
lpNewDIBBits1=new unsigned char [lLineBytes*lHeight];
// 判断是否内存分配失败
if (lpNewDIBBits1 == NULL)
{
// 分配内存失败
return ;
}
BeginWaitCursor();
// 针对图像每行进行操作
lpImg=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpImg, lLineBytes * lHeight);
//1 Gaussian Filter
const int M=7;
GaussFilter(M,M,1.5);//edge number down
//2 Sobel to get Mag
// 针对图像每行进行操作
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{ lpImg =(unsigned char *)pDoc->m_pDib->m_lpImage+ lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpMag =lpNewDIBBits1 + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
// 针对每行图像每列进行操作
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
{
// 指向源DIB第i行,第j个象素的指针
lpImg++;//
lpMag++;//
if(i<1 || i>=lHeight-1 || j<1 || j >=lWidth-1)
{
*lpMag=0;
continue;
}
int valx,valy;
valy=*(lpImg+lLineBytes-1)+*(lpImg+lLineBytes)*2+*(lpImg+lLineBytes+1)
-*(lpImg-lLineBytes-1)-*(lpImg-lLineBytes)*2-*(lpImg-lLineBytes+1);
valx=*(lpImg+lLineBytes-1)+*(lpImg-1)*2+*(lpImg-lLineBytes-1)
-*(lpImg+lLineBytes+1)-*(lpImg+1)*2-*(lpImg-lLineBytes+1);
int val=(int)(0.5+sqrt(double(valx*valx+valy*valy)));
*lpMag=(unsigned char)min(val,255);
}
}
//3 应用non-maximum 抑制
const int DOOR=8;
// 针对图像每行进行操作
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{ lpMag =lpNewDIBBits1 + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpImg =(unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
lpEdge =lpNewDIBBits+ lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
// 针对每行图像每列进行操作
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
{
// 指向源DIB第i行,第j个象素的指针
lpImg++;//
lpMag++;//
lpEdge++;//
int g,g1,g2,g3,g4;
if(i<1 || i>lHeight-2 || j<1 || j >lWidth-2)
*lpEdge = 0 ;
else{
g=*(lpMag);
if(g>DOOR){
int gx,gy;
gy=*(lpImg-lLineBytes);
gy-=*(lpImg+lLineBytes);
gx=*(lpImg+1);
gx-=*(lpImg-1);
double weight;
// 如果方向导数y分量比x分量大,说明导数的方向更加“趋向”于y分量。
if (abs(gy) > abs(gx))
{
// 计算插值的比例
weight = fabs((float) gx)/fabs((float) gy);
g2 = *(lpMag+lLineBytes) ;
g4 = *(lpMag-lLineBytes);
// 如果x,y两个方向的方向导数的符号相同
// C是当前象素,与g1-g4的位置关系为:
// g1 g2
// C
// g4 g3
if (gx*gy > 0)
{
g1 = *(lpMag+lLineBytes-1) ;
g3 = *(lpMag-lLineBytes+1) ;
}
// 如果x,y两个方向的方向导数的符号相反
// C是当前象素,与g1-g4的位置关系为:
// g2 g1
// C
// g3 g4
else
{
g1 = *(lpMag+lLineBytes+1) ;
g3 = *(lpMag-lLineBytes-1) ;
}
}
// 如果方向导数x分量比y分量大,说明导数的方向更加“趋向”于x分量
// 这个判断语句包含了x分量和y分量相等的情况
else
{
// 计算插值的比例
weight = fabs((float) gy)/fabs((float) gx);
g2 = *(lpMag+1) ;
g4 = *(lpMag-1) ;
// 如果x,y两个方向的方向导数的符号相同
// C是当前象素,与g1-g4的位置关系为:
// g3
// g4 C g2
// g1
if (gx*gy > 0)
{
g1 = *(lpMag-lLineBytes+1) ;
g3 = *(lpMag+lLineBytes-1) ;
}
// 如果x,y两个方向的方向导数的符号相反
// C是当前象素,与g1-g4的位置关系为:
// g1
// g4 C g2
// g3
else
{
g1 = *(lpMag+lLineBytes+1) ;
g3 = *(lpMag-lLineBytes-1) ;
}
}
// 下面利用g1-g4对梯度进行插值
{
double dTmp1 = weight*g1 + (1-weight)*g2 ;
double dTmp2 = weight*g3 + (1-weight)*g4 ;
// 当前象素的梯度是局部的最大值
// 该点可能是个边界点
if(g>=dTmp1 && g>=dTmp2)
{
*lpEdge =TWOVALUE_H ;
}else *lpEdge = 0 ;
}
}else *lpEdge = 0 ;
}
}
}
DisplayNewImg(lpNewDIBBits,lLineBytes,lHeight,"non-maximum Edge");
//4应用Hysteresis,找到所有的边界
// 估计需要的低阈值,高阈值
int ThdHigh,ThdLow;
int nHist[256];//
const double dRatioHigh =0.61;//总边缘数的比例
const double dRatioLow =0.3;//
// 该数组的大小和梯度值的范围有关,如果采用本程序的算法,那么梯度的范围不会超过pow(2,10)
// 初始化
for(int k=0; k<256; k++)
{
nHist[k] = 0;
}
// 统计直方图,然后利用直方图计算阈值
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{ lpMag =lpNewDIBBits1 + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpEdge =lpNewDIBBits+ lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
// 针对每行图像每列进行操作
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
{
// 指向源DIB第i行,第j个象素的指针
lpEdge++;//
lpMag++;//
// 只是统计那些可能是边界点,并且还没有处理过的象素
if(*lpEdge==TWOVALUE_H)
{
nHist[*lpMag]++;
}
}
}
int nEdgeNb = nHist[0] ;
int nMaxMag = 0 ;
// 统计经过“非最大值抑止(non-maximum suppression)”后有多少象素
for(int k=1; k<256; k++)
{
if(nHist[k] != 0)
{
// 最大梯度值
nMaxMag = k;
}
// 梯度为0的点是不可能为边界点的
// 经过non-maximum suppression后有多少象素
nEdgeNb += nHist[k];
}
// 梯度比高阈值*pnThdHigh小的象素点总数目
int nHighCount = (int)(dRatioHigh * nEdgeNb +0.5);
int nLowCount = (int)(dRatioLow * nEdgeNb +0.5);
int k = 1;
nEdgeNb = nHist[1];
// 计算低阈值
while( (k<(nMaxMag-1)) && (nEdgeNb < nLowCount) )
{
k++;
nEdgeNb += nHist[k];
}
// 设置低阈值
ThdLow = k ;
// 计算高阈值
while( (k<(nMaxMag-1)) && (nEdgeNb < nHighCount) )
{
k++;
nEdgeNb += nHist[k];
}
// 设置高阈值
ThdHigh = k ;
TRACE("\nThdLow =%d,ThdHigh=%d\n",ThdLow ,ThdHigh);
// 这个循环用来寻找大于nThdHigh的点,这些点被用来当作边界点,然后用
// TraceEdge函数来跟踪该点对应的边界(大于ThdLow)
for (int i = pDoc->StartPoint.y+1; i <pDoc->EndPoint.y; i ++)
{ lpMag =lpNewDIBBits1 + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x;
lpEdge =lpNewDIBBits+ lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x;
// 针对每行图像每列进行操作
for (int j =pDoc->StartPoint.x+1; j <pDoc->EndPoint.x; j ++)
{
// 指向源DIB第i行,第j个象素的指针
lpEdge++;//
lpMag++;//
// 只是统计那些可能是边界点,并且还没有处理过的象素
if(*lpEdge==TWOVALUE_H)
{
if(*lpMag >= ThdHigh)
{
// 设置该点为边界点
*lpEdge = 255;
TraceEdge(i, j, ThdLow, lpNewDIBBits, lpNewDIBBits1);
}
}
}
}
//经过试验,无需反向再做一遍,
// 那些还没有被设置为边界点的象素已经不可能成为边界点
int Num=0;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{ lpEdge =lpNewDIBBits+ lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
{
lpEdge++;//
if(*lpEdge!= 255)
{
// 设置为非边界点
*lpEdge = 0 ;
}else
Num++;
}
}
TRACE("\n Total Edge Num=%d\n",Num);
lpImg=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpImg, lpNewDIBBits,lLineBytes * lHeight);
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"Canny 边缘检测");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
// 恢复光标
EndWaitCursor();
// 释放内存
delete []lpNewDIBBits;
delete []lpNewDIBBits1;
}
void CImageProcessView::OnUpdateEdgeCanny(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::TraceEdge(int y, int x,int LowThd, unsigned char* pUnchEdge, unsigned char* pnMag)
{
// 对8邻域象素进行查询
int xNb[8] = {1, 1, 0,-1,-1,-1, 0, 1} ;
int yNb[8] = {0, 1, 1, 1,0 ,-1,-1,-1} ;
int yy ;
int xx ;
int k ;
int nWidth=lLineBytes;
for(k=0; k<8; k++)
{
yy =y + yNb[k] ;
xx = x + xNb[k] ;
// 如果该象素为可能的边界点,又没有处理过
// 并且梯度大于阈值
if(*(pUnchEdge+(lHeight-1-yy)*lLineBytes+xx) == 128 && *(pnMag+(lHeight-1-yy)*nWidth+xx)>=LowThd)
{
// 把该点设置成为边界点
*(pUnchEdge+(lHeight-1-yy)*lLineBytes+xx) = 255 ;
// 以该点为中心进行跟踪
TraceEdge(yy, xx, LowThd, pUnchEdge, pnMag);
}
}
}
void CImageProcessView::OnSegmentationOptimal()
{
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
//直方图数组
int lHistogram[256]={0};
GetHistgram(lHistogram,true);
int iThreshold=*pDoc->m_pDib->m_lpImage;
int iOldThreshold=-1;
int size=(pDoc->EndPoint.x-pDoc->StartPoint.x+1)*(pDoc->EndPoint.y-pDoc->StartPoint.y+1);
for (int i =0;i <=255;i++)
if( lHistogram[i]>size/10)
{
iThreshold=i;
break;
}
//用于计算区域灰度平均值的中间变量
int m1,m2,w1,w2;
while(iThreshold !=iOldThreshold )
{ iOldThreshold=iThreshold;
m1 =0;m2=0;
w1 =0;w2=0;
//求两个区域的灰度平均值m and number w
for (int i =0;i <=iOldThreshold;i++)
{
m1 += lHistogram[i]*i;//
w1 += lHistogram[i];//total num
}
for (int i = iOldThreshold+1;i < 256;i++)
{
m2 += lHistogram[i]*i;
}
m1/=w1;
m2/=(size-w1);
iThreshold=(m1+m2)/2;
}
THRESHOLD=iThreshold;
Fixedthreshold();
//display Hist
CString str;
str.Format("Treshold(%d)",THRESHOLD);
DisplayDlg dlg;
dlg.pData=&lHistogram[0];
dlg.m_Sizex=256;
dlg.m_Title=str;
dlg.m_Level=1;//draw number
dlg.m_LinePos=THRESHOLD;
dlg.DoModal();
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdateSegmentationOptimal(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnEdgeNon()
{
CImageProcessDoc* pDoc = GetDocument();
// 指向转置图像对应象素的指针
unsigned char* lpSrc;
unsigned char* lpDst;
// 指向转置图像的指针
unsigned char* lpNewDIBBits;
// 暂时分配内存,以保存新图像
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
// 指向转置图像的指针
// 判断是否内存分配失败
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
OnEdgeSobel();
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{ lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
{
lpSrc++;lpDst++;
if(i>0 && i<lHeight-1 && j>0 && j<lWidth-1){
if((*lpSrc & 0x3) == 2) //------
{
if(*lpSrc<*(lpSrc+lLineBytes) || *lpSrc<*(lpSrc-lLineBytes))
*lpDst=0;
}else if((*lpSrc & 0x3) == 0) // |
{
if(*lpSrc<*(lpSrc+1) || *lpSrc<*(lpSrc-1))
*lpDst=0;
}
else if((*lpSrc & 0x3) == 1) // |
{if(*lpSrc<*(lpSrc+lLineBytes+1) || *lpSrc<*(lpSrc-lLineBytes-1))
*lpDst=0;
}
else {if(*lpSrc<*(lpSrc-lLineBytes+1) || *lpSrc<*(lpSrc+lLineBytes-1))
*lpDst=0;
}
}else *lpDst=0;
}
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy(lpSrc, lpNewDIBBits, lLineBytes * lHeight);
CString str=pDoc->GetTitle();
str+="--Non_Maximum Suppression";
pDoc->SetTitle(str);
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdateEdgeNon(CCmdUI *pCmdUI)
{
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
//process after edgeed
void CImageProcessView::OnEdgeHysteresis()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
const int HighTh=80;
const int LowTh=10;
bool bOver=false;
while(!bOver){
bOver=true;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
{
lpSrc++;
if(*lpSrc>LowTh && *lpSrc<HighTh){
for(int m=-1;m<2;m++)
for(int n=-1;n<2;n++)
{
if(m+i>0 && m+i<lHeight && n+j>0 && n+j<lWidth){
if(*(lpSrc-m*lLineBytes+n)>=HighTh && ((*(lpSrc-m*lLineBytes+n) & 0x3) == (*(lpSrc) & 0x3))){
*lpSrc=HighTh;
bOver=false;
}
}
}
}
}
}
}
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++)
{
lpSrc++;
if(*lpSrc<HighTh)
*lpSrc=0;
}
}
CString str=pDoc->GetTitle();
str+="--Hysteresis to filter";
pDoc->SetTitle(str);
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
}
void CImageProcessView::OnUpdateEdgeHysteresis(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnHoughCircle()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
CPoint StartPoint=pDoc->StartPoint;
CPoint EndPoint=pDoc->EndPoint;
BeginWaitCursor();
const int aMax=512;//center x(0-aMax)
const int bMax=512;//center y(0-bMax)
const int rMin=25;//radium //
const int rMax=80;//radium
int dx=max(EndPoint.y-StartPoint.y,EndPoint.y-StartPoint.y)/min(aMax,bMax)+1;
int (*pArray)[bMax][rMax-rMin]=new int [aMax][bMax][rMax-rMin];
//init
for(int k=0;k<aMax;k++)
for(int m=0;m<bMax;m++)
for(int r=0;r<rMax-rMin;r++)
pArray[k][m][r]=0;
const double pi=3.14159;
unsigned char* lpSrc;
//get pArray
for (int i = StartPoint.y; i <=EndPoint.y; i ++)
{ lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + StartPoint.x-1;
for (int j =StartPoint.x; j <=EndPoint.x; j ++)
{
lpSrc++;
if(*lpSrc)
{
for(int theta=0;theta<360;theta+=2)
for(int r=rMin;r<rMax;r++)
{
int a=j-StartPoint.x-int(cos((float)theta*pi/180)*r+0.5);
int b=i-StartPoint.y-int(sin((float)theta*pi/180)*r+0.5);
if(a>=0 && a/dx<aMax && b>=0 && b/dx<bMax){
pArray[a/dx][b/dx][r-rMin]++;
}
}
}
}
}
int N_value=200;
int N_MaxVal=100;
vector <bool> Err;//重合点数少判为err
int kk=0;//times
while(N_value>N_MaxVal && kk<30)
{kk++;
//查找计数器数组中的最大值
int Max=0;
int A=-1,B=-1,R=-1;
for(int r=0;r<rMax-rMin;r++)
{
for(int a=0;a<aMax;a++)
for(int b=0;b<bMax;b++)
{
if(pArray[a][b][r]>Max)
{
Max=pArray[a][b][r];
A=a;
B=b;
R=r+rMin;
}
}
}
A=A*dx;//chg
B=B*dx;
CString str;
str.Format("\n%d: (a: %d b: %d r: %d ) Max:%d\n",kk,A+StartPoint.x,B+StartPoint.y,R,Max);
TRACE(str);
//将最大值点附近清零
for(int r=-R/2;r<R/2;r++)
{ for(int a=A-R/2;a<=A+R/2;a++)
for(int b=B-R/2;b<=B+R/2;b++)
{
if(a>=0 && a<aMax*dx)
if(b>=0 && b<bMax*dx)
if(r+R>=rMin && r+R<rMax)
{
pArray[a/dx][b/dx][r+R-rMin]=0;
}
}
}
N_value=Max;
N_MaxVal=20+R/2;
if(dx>1) N_MaxVal+=(dx-1)*R;//if dx>1 have more point
A+=StartPoint.x;
B+=+StartPoint.y;
if(N_value>N_MaxVal){
int num=0;
int allnum=0;
//Draw a circle (A,B,R) to get poin or point--circle
int x=0;
int y=R;
int p=1-R;
while(x<y){
x++;
if(p<0)
p+=2*x+1;
else
{
y--;
p+=2*(x-y)+1;
}
for(int i=-1;i<2;i+=2)//-1,1
for(int j=-1;j<2;j+=2)//-1,1
{
if(A+i*x>=StartPoint.x && A+i*x<=EndPoint.x && B+j*y>=StartPoint.y && B+j*y<=EndPoint.y)
{
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-B-j*y) +A+i*x;
if(*lpSrc==TWOVALUE_H) num++;
*lpSrc=(unsigned char)(min(200+kk,255));allnum++;
}
if(A+i*y>=StartPoint.x && A+i*y<=EndPoint.x && B+j*x>=StartPoint.y && B+j*x<=EndPoint.y)
{
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-B-j*x) +A+i*y;
if(*lpSrc==TWOVALUE_H) num++;
*lpSrc=(unsigned char)(min(200+kk,255));allnum++;
}
}
}
if(num>allnum/5 && num>N_value/3)
Err.push_back(true);
else
Err.push_back(false);
}
}
// 复制图像
//lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
//memcpy( lpSrc,lpNewDIBBits, lLineBytes * lHeight);
LPRGBQUAD pDibQuad = (LPRGBQUAD) pDoc->m_pDib->m_lpvColorTable+200;
for(int i=0;i<min(kk,255);i++){
// 更新DIB调色板红色分量
pDibQuad->rgbRed = 255;
// 更新DIB调色板绿色分量
pDibQuad->rgbGreen =i*10%256;
// 更新DIB调色板蓝色分量
pDibQuad->rgbBlue = 0;
pDibQuad ++;
}
//display err find in blue
if(Err.size()>0){
for(int i=0;i<(int)Err.size();i++)
{
if(!Err[i]){
pDibQuad = (LPRGBQUAD) pDoc->m_pDib->m_lpvColorTable+200+i+1;
pDibQuad->rgbRed =0;pDibQuad->rgbGreen =0;pDibQuad->rgbBlue = 255;
}
}
}
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
// 恢复光标
EndWaitCursor();
delete []pArray;
}
void CImageProcessView::OnUpdateHoughCircle(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnSegmentationDynamic()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
CPoint StartPoint=pDoc->StartPoint;
CPoint EndPoint=pDoc->EndPoint;
BeginWaitCursor();
unsigned char* lpSrc;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
const int M=25;
const int N=25;
const int Gdiff=10;
//if select small area display data
int Data[256*3]={0};
bool bDisplay=false;//draw line?
if((EndPoint.x-StartPoint.x)<256)
bDisplay=true;
int minMean=255;
int maxMean=0;
int maxDiff=0;
unsigned char* lpDst;
for (int i = StartPoint.y; i <=EndPoint.y; i ++) {
for (int j = StartPoint.x; j <= EndPoint.x; j ++){
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + j;
lpDst=lpNewDIBBits + lLineBytes* (lHeight-1-i) + j;
*lpSrc=TWOVALUE_H;
int mean=*lpDst;
if(i>=N/2 && i<lHeight-N/2 && j>=M/2 && j<lWidth-M/2){
int add=0;
int num=0;
for(int m=-M/2;m<=M/2;m++)
for(int n=-N/2;n<=N/2;n++)
{ if(*(lpDst+lLineBytes* n + m)>(*lpDst+5))
{
add+=*(lpDst+lLineBytes* n + m);
num++;
}
}
if(num>N*M/3)
mean=add/num;
if(mean-(*lpDst)>Gdiff)
{
*lpSrc=TWOVALUE_L;
if(mean-(*lpDst)>maxDiff) maxDiff=mean-(*lpDst);
if(mean>maxMean) maxMean=mean;
if(mean<minMean) minMean=mean;
}
}
if(bDisplay){
if(i==(EndPoint.y/2+StartPoint.y/2)){
Data[min(j- StartPoint.x,199)]=mean-*lpDst;//max(mean-*lpDst,0);
Data[256+min(j- StartPoint.x,199)]=*lpDst;
Data[512+min(j- StartPoint.x,199)]=mean;
}
}
}
}
if(bDisplay){
CString str;
str.Format("minMean=%d maxMean=%d maxDiff=%d",minMean,maxMean,maxDiff);
DisplayDlg dlg;
dlg.pData=&Data[0];
dlg.m_Sizex=256;
dlg.m_Title=str;
dlg.m_Level=3;//draw number
dlg.m_LinePos=0;
dlg.DoModal();
}
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
DisplayNewImg(lpNewDIBBits, lLineBytes ,lHeight,"Origin Image");
EndWaitCursor();
delete [] lpNewDIBBits;
}
void CImageProcessView::OnUpdateSegmentationDynamic(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnSpatialdomainZoombilinearinterpolation()
{
// TODO: Add your command handler code here
BeginWaitCursor();
ZoomDblLinear(1.8,1.8);//zoom out
ZoomDblLinear(.8,.8);//zoom in
EndWaitCursor();
}
void CImageProcessView::OnUpdateSpatialdomainZoombilinearinterpolation(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::ZoomDblLinear(double fx, double fy)
{
CImageProcessDoc* pDoc = GetDocument();
CPoint StartPoint=pDoc->StartPoint;
CPoint EndPoint=pDoc->EndPoint;
unsigned char* lpSrc;
// 指向转置图像对应象素的指针
unsigned char* lpDst;
//if scaled down get smooth first; else : aliasing effects
if(fx<1.0 || fy<1.0)
GaussFilter(5,5,0);
int w,h,l;
h=(int)(fy*(EndPoint.y-StartPoint.y+1));
w=(int)(fx*(EndPoint.x-StartPoint.x+1));
l=(w+3)/4*4;
unsigned char *lpNewDIBBits=new unsigned char [h * l];
// 判断是否内存分配失败
if (lpNewDIBBits == NULL)
{
// 分配内存失败
return ;
}
//out image
for(int i = 0; i < h; i++)
{
// 列
for(int j = 0; j <w ; j++)
{
// 指向DIB第i行,第j个象素的指针
lpDst = (unsigned char*)lpNewDIBBits + l * (h - 1 - i) + j;
double x=j/fx;
double y=i/fy;
int x1=(int)x;
int y1=(int)y;
if(x1+StartPoint.x>=0 && x1+StartPoint.x<lWidth-1 && y1+StartPoint.y>=0 && y1+StartPoint.y<lHeight-1){//in
lpSrc = (unsigned char*)pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - y1-StartPoint.y) + x1+StartPoint.x;
int v=(unsigned char)((y1+1-y)*((x1+1-x)*(*lpSrc)+(x-x1)*(*(lpSrc+1)))
+(y-y1)*((x1+1-x)*(*(lpSrc-lLineBytes))+(x-x1)*(*(lpSrc-lLineBytes+1))));//a=x-x1 b=y-y1
if(v<0) v=0;
else if(v>255) v=255;
*lpDst=(BYTE)v;
}else
*lpDst=*(pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - (int)(y+0.5)-StartPoint.y) + (int)(x+0.5)+StartPoint.x);//近邻插值
}
}
CString str;
str.Format("Scaling by (%3.2f %3.2f)",fx,fy);
DisplayNewImg(lpNewDIBBits, l ,h,str);
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
// 释放内存
delete []lpNewDIBBits;
return ;
}
void CImageProcessView::OnUpdateApplicationContourtrace(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bTwoValue);
}
//obj:black
//1)能获取多个边界及参数
//2)获取周长
//3)存储边界点
//4)计算面积
//5)显示边界图形
//可以在标记后再进行跟踪,无需考虑处理的区域了,每个标号仅有一个起始点
void CImageProcessView::OnApplicationContourtrace()
{
TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
unsigned char* lpSrc;
//1 置处理边沿为背景
for (int j = pDoc->StartPoint.y;j <= pDoc->EndPoint.y ;j++)
{
for(int i = pDoc->StartPoint.x;i <= pDoc->EndPoint.x ;i++)
{
if(i == pDoc->StartPoint.x || i == pDoc->EndPoint.x || j == pDoc->StartPoint.y || j == pDoc->EndPoint.y)
{
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-j) + i;
*lpSrc=TWOVALUE_H;
}
}
}
BOOL bFindStartPoint;
CPoint StartPoint;
int SearchNo=0;
const int MaxAreaNum=20;
CRect Area[MaxAreaNum];
while(SearchNo<MaxAreaNum){
//初始化处理区域大小(为后面比较最大最小值)
Area[SearchNo].left=lWidth;
Area[SearchNo].top=lHeight;
Area[SearchNo].right=0;
Area[SearchNo].bottom=0;
//获取起始点 StartPoint
bFindStartPoint = false;
for (int j = pDoc->StartPoint.y;j <= pDoc->EndPoint.y && !bFindStartPoint;j++)
{
for(int i = pDoc->StartPoint.x;i <= pDoc->EndPoint.x && !bFindStartPoint;i++)
{
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-j) + i;
if(*lpSrc == 0)//obj
{
bFindStartPoint = true;
StartPoint.y = j;
StartPoint.x = i;
//确定该点不在已经处理的区域内
int k_tmp=0;
while(k_tmp<SearchNo){
if(StartPoint.x<=Area[k_tmp].right && StartPoint.x>=Area[k_tmp].left
&& StartPoint.y<=Area[k_tmp].bottom && StartPoint.y>=Area[k_tmp].top)
bFindStartPoint = false;
k_tmp++;
}
}
}
}
if(!bFindStartPoint) break;//无新未处理的区域,退出循环
//八个方向和起始扫描方向
int Direction[8][2]={{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1},{0,1},{1,1}};//
//由于起始点是在左上方,故起始扫描沿左下方向
int BeginDirect = 5;//
//跟踪边界
CPoint CurrentPoint;
//从初始点开始扫描
CurrentPoint.y = StartPoint.y;
CurrentPoint.x = StartPoint.x;
//起始点
//memorey area
if(CurrentPoint.x<Area[SearchNo].left)Area[SearchNo].left=CurrentPoint.x;
if(CurrentPoint.x>Area[SearchNo].right)Area[SearchNo].right=CurrentPoint.x;
if(CurrentPoint.y<Area[SearchNo].top)Area[SearchNo].top=CurrentPoint.y;
if(CurrentPoint.y>Area[SearchNo].bottom)Area[SearchNo].bottom=CurrentPoint.y;
vector<CPoint> edgePt;
edgePt.push_back(CurrentPoint);
double perimeter=0.0;
while(1)
{
//沿扫描方向查看一个像素
lpSrc = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1- CurrentPoint.y - Direction[BeginDirect][1])
+ (CurrentPoint.x + Direction[BeginDirect][0]);
if(*lpSrc == 0)//obj
{
CurrentPoint.y = CurrentPoint.y + Direction[BeginDirect][1];
CurrentPoint.x = CurrentPoint.x + Direction[BeginDirect][0];
//获取周长
if(BeginDirect%2) perimeter+=1.414;
else perimeter+=1;
//存储边界点
edgePt.push_back(CurrentPoint);
if(CurrentPoint.y == StartPoint.y && CurrentPoint.x == StartPoint.x)
break;//out while (闭合)
//memorey area
if(CurrentPoint.x<Area[SearchNo].left)Area[SearchNo].left=CurrentPoint.x;
if(CurrentPoint.x>Area[SearchNo].right)Area[SearchNo].right=CurrentPoint.x;
if(CurrentPoint.y<Area[SearchNo].top)Area[SearchNo].top=CurrentPoint.y;
if(CurrentPoint.y>Area[SearchNo].bottom)Area[SearchNo].bottom=CurrentPoint.y;
//扫描的方向顺时针旋转两格
BeginDirect--;
if(BeginDirect == -1)
BeginDirect = 7;
BeginDirect--;
if(BeginDirect == -1)
BeginDirect = 7;
}
else
{
//扫描方向逆时针旋转一格
BeginDirect++;
if(BeginDirect == 8)
BeginDirect = 0;
}
}
SearchNo++;
//计算面积
int S=0;
for(int i=0;i<(int)edgePt.size()-1;i++)
S+=(edgePt[i].x*edgePt[i+1].y-edgePt[i+1].x*edgePt[i].y) ;
S/=2;
if(S<0) S=-S;
TRACE("\nNo=%d,面积=%d,周长=%3.1f,圆形度=%3.1f\n",SearchNo,S,perimeter,perimeter*perimeter/S);//
CDC *pdc = GetDC();
//显示边界图形
for(int i=0;i<(int)edgePt.size();i++)
pdc->SetPixel(edgePt[i],RGB(255,0,0)) ;//
ReleaseDC(pdc);
}
CString str;
str.Format("\nContour Number is %d\n",SearchNo);
TRACE(str);
//MessageBox(str,"Message ",MB_OK);
EndWaitCursor();
}
void CImageProcessView::OnEdgeTrace()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CPoint StartPoint=pDoc->StartPoint;
CPoint EndPoint=pDoc->EndPoint;
unsigned char* lpSrc;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
//1 get start Point=maxGrad point
CPoint stPt;
unsigned char* lpDst;
double maxGrad=0;
double last_angle=0;
for (int i = StartPoint.y; i <=EndPoint.y; i ++) {
for (int j = StartPoint.x; j <= EndPoint.x; j ++){
lpDst=lpNewDIBBits + lLineBytes* (lHeight-1-i) + j;
*lpDst=min(*lpDst,254);
if(i>=1 && i<lHeight-1 && j>=1 && j<lWidth-1){
CPoint pt=CPoint(j,i);
double grad=0.0;
double angle=0.0;
Gradient(pt,&grad,&angle);
if(grad>maxGrad){
maxGrad=grad;
last_angle=angle;
stPt=pt;
}
}
}
}
if(maxGrad<10)
{
delete[]lpNewDIBBits;
return;
}
//根据边缘方向调整 0: |o (6)
int Direction[8][2]={{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};//
const double DiffTh=maxGrad/2;
CPoint pt=stPt;
int no=0;
while(1){
lpDst=lpNewDIBBits + lLineBytes* (lHeight-1-pt.y) + pt.x;
*lpDst=255;
CPoint nextpt;
//下一点位置获取
int dir=int((last_angle+22.5)/45);
if((last_angle+22.5)>=360)
dir=0;
//边缘
double grad1=0.0;
double angle1=0.0;
CPoint nextpt1=CPoint(pt.x+Direction[dir][0],pt.y+Direction[dir][1]);
Gradient(nextpt1,&grad1,&angle1);
double grad2=0.0;
double angle2=0.0;
dir++;
if(dir>8) dir=0;
CPoint nextpt2=CPoint(pt.x+Direction[dir][0],pt.y+Direction[dir][1]);
Gradient(nextpt2,&grad2,&angle2);
double grad=0.0;
double angle=0.0;
if(grad2>grad1){
grad=grad2;
angle=angle2;
nextpt=nextpt2;
}else
{
grad=grad1;
angle=angle1;
nextpt=nextpt1;
}
double diff=abs(last_angle-angle);
if(diff>315) diff=0;
if(grad>DiffTh && diff<45){
last_angle=angle;
pt=nextpt;
}
else{
//修正角度
//可能不需要,
//find max grad near pt
double maxGrad=0;
double tmpangle=last_angle;
for(int m=-1;m<2;m++)
for(int n=-1;n<2;n++){
CPoint tmpPt=pt;
tmpPt.x+=m;tmpPt.y+=n;
lpDst=lpNewDIBBits + lLineBytes* (lHeight-1-tmpPt.y) + tmpPt.x;
if(*lpDst<255){
double grad=0.0;
double angle=0.0;
Gradient(tmpPt,&grad,&angle);
if(abs(angle-last_angle)<15)//5 err!
grad*=1.2;
if(grad>maxGrad ){
maxGrad=grad;
nextpt=tmpPt;
tmpangle=angle;
}
}
}
pt=nextpt;
last_angle=tmpangle;
}
no++;
// out of while
if(no>10){
if(abs(pt.x-stPt.x)<2 && abs(pt.y-stPt.y)<2){
lpDst=lpNewDIBBits + lLineBytes* (lHeight-1-pt.y) + pt.x;
//set 255
*lpDst=255;
break;
}
}
if(no>10000) break;//防止死循环
}
memcpy( pDoc->m_pDib->m_lpImage,lpNewDIBBits, lLineBytes * lHeight);
//display
lpSrc=(unsigned char*)pDoc->m_pDib->m_lpvColorTable;
*(lpSrc+255*4+1)=0;*(lpSrc+255*4)=0;*(lpSrc+255*4+2)=255;
pDoc->SetTitle("Edge Trace Image");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
EndWaitCursor();
delete [] lpNewDIBBits;
}
void CImageProcessView::OnUpdateEdgeTrace(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
//if(m_bTwoValue) bAvail=false;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
//微调(+、- 1)处理窗口大小
CImageProcessDoc* pDoc = GetDocument();
switch(nChar){
case VK_LEFT:
if(pDoc->StartPoint.x--<=0)
pDoc->StartPoint.x=0;
break;
case VK_RIGHT:
if(pDoc->EndPoint.x++>=lWidth-1)
pDoc->EndPoint.x=lWidth-1;
break;
case VK_UP:
if(pDoc->StartPoint.y--<=0)
pDoc->StartPoint.y=0;
break;
case VK_DOWN:
if(pDoc->EndPoint.y++>=lHeight-1)
pDoc->EndPoint.y=lHeight-1;
break;
}
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CImageProcessView::OnSmoothTrun()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
//copy img
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
return ;
memcpy( lpNewDIBBits,pDoc->m_pDib->m_lpImage, lLineBytes * lHeight);
const int M=13;//odd
const int N=15;//odd
TrunMedianFilter(M,N);
CString str=pDoc->GetTitle();
DisplayNewImg(pDoc->m_pDib->m_lpImage,lLineBytes,lHeight,str+"--++截断中值滤波");//display orignal image
//get img back
pDoc->SetTitle(str);
memcpy( pDoc->m_pDib->m_lpImage,lpNewDIBBits, lLineBytes * lHeight);
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
delete [] lpNewDIBBits;
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::OnUpdateSmoothTrun(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
if(m_bTwoValue) bAvail=false;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::TrunMedianFilter(int M,int N)
{
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
unsigned char* lpSrc;
unsigned char* lpDst;
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
//unsigned char *v=new unsigned char[M*N];//[N*M];//line N Column M not rect (int err)
vector<unsigned char> v(M*N,0);
const int Th=(M*N)/2;//Mid Pos
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;
lpDst++;
if(i>=M/2 && i<lHeight-M/2 && j>=N/2 && j<lWidth-N/2){
//Get M*N data to v[]
int vSize=0;
int aver=0;
for(int m=-M/2;m<=M/2;m++)
for(int n=-N/2;n<=N/2;n++)
{ v[vSize]=*(lpSrc+lLineBytes*m+n);
aver+=v[vSize];
vSize++;
}
aver/=vSize;
//sort v[]
for(int m=0;m<M*N-1;m++)
for(int n=m+1;n<M*N;n++)
{
if(v[m]>v[n]){
//swap
BYTE tmp=v[m];
v[m]=v[n];
v[n]=tmp;
}
}
//截断
int lower=v[0];
int upper=v[vSize-1];
if(aver>v[Th])
upper=2*v[Th]-lower;
else
lower=2*v[Th]-upper;
int pos1=0;
int pos2=vSize-1;
while(lower>v[pos1])
pos1++;
while(upper<v[pos2])
pos2--;
//取中值
*(lpDst)=(unsigned char)v[(pos1+pos2)/2];
}
}
}
// 释放内存
delete []lpNewDIBBits;
//delete []v;
}
void CImageProcessView::OnSmoothAnisotropicdiffusion()
{
// TODO: Add your command handler code here
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
//copy img
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
return ;
memcpy( lpNewDIBBits,pDoc->m_pDib->m_lpImage, lLineBytes * lHeight);
AnisotropicDiffusion();
CString str=pDoc->GetTitle();
DisplayNewImg(pDoc->m_pDib->m_lpImage,lLineBytes,lHeight,str+"--++各向异性扩散滤波");//display orignal image
//get img back
pDoc->SetTitle(str);
memcpy( pDoc->m_pDib->m_lpImage,lpNewDIBBits, lLineBytes * lHeight);
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
delete [] lpNewDIBBits;
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::AnisotropicDiffusion(){
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
if (lpNewDIBBits == NULL)
{
return ;
}
unsigned char* lpSrc;
unsigned char* lpDst;
const int k=5;
const float lamda=0.25f;
for(int t=0;t<20;t++)//迭代
{
lpSrc=(unsigned char *)pDoc->m_pDib->m_lpImage;
memcpy( lpNewDIBBits,lpSrc, lLineBytes * lHeight);
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;
lpDst++;
if(i>=1 && i<lHeight-1 && j>=1 && j<lWidth-1){
//获取变化
float dN=(float)(*(lpSrc+lLineBytes)-*(lpSrc));
float dS=(float)(*(lpSrc-lLineBytes)-*(lpSrc));
float dE=(float)(*(lpSrc-1)-*(lpSrc));
float dW=(float)(*(lpSrc+1)-*(lpSrc));
/*int v=*(lpSrc)+(int)(lamda*(dN/(1+dN*dN/k/k)+dS/(1+dS*dS/k/k)+
dE/(1+dE*dE/k/k)+dW/(1+dW*dW/k/k)));*/
int v=*(lpSrc)+(int)(lamda*(dN*exp(-dN*dN/k/k)+dS*exp(-dS*dS/k/k)+
dE*exp(-dE*dE/k/k)+dW*exp(-dW*dW/k/k)));
if(v>255) v=255;
else if(v<0) v=0;
*lpDst=(BYTE)v;
}
}
}
}
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::OnUpdateSmoothAnisotropicdiffusion(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
if(m_bTwoValue) bAvail=false;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnGrayReconstruction()
{
// TODO: Add your command handler code here
BeginWaitCursor();
CImageProcessDoc* pDoc = GetDocument();
CDemoTimer exeTimer;
exeTimer.Reset();
//1 2x20 Se
//se = strel('disk', 20)
const int M=39;
const int N=39;
动态定义三维数组:
//int *** p3 ;//[ hight][ row][ col]
//p3 = new int**[hight ] ;
int **S;
S = new int * [M];//S[M][N]
for (int i = 0; i < M; i++) {
S[i] = new int[N] ;
}
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
{
if((i-M/2)*(i-M/2)+(j-N/2)*(j-N/2)<=20*20)
S[i][j]=0;
else
S[i][j]=-1;
}
//掩膜图像 原图:(lpNewDIBBits)
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
_ASSERT(lpNewDIBBits != NULL);//false
memcpy( lpNewDIBBits,pDoc->m_pDib->m_lpImage, lLineBytes * lHeight);
//GrayErosion(S,M,N);//7s 578 ms
GrayFastOperate(false);
TRACE("\nUsed Time is %.3f ms\n",exeTimer.GetTime(false)*1000);
标记图像 腐蚀 :pDoc->m_pDib->m_lpImage
ReConstruction(pDoc->m_pDib->m_lpImage,lpNewDIBBits);
TRACE("\nUsed Time is %.3f ms\n",exeTimer.GetTime(false)*1000);
memcpy( lpNewDIBBits,pDoc->m_pDib->m_lpImage, lLineBytes * lHeight);
//掩膜图像:(lpNewDIBBits)
//
//GrayDilation(S,M,N);
GrayFastOperate(true);
//标记图像 膨胀运算pDoc->m_pDib->m_lpImage
unsigned char* lpSrc;
unsigned char* lpDst;
// 掩膜图像\标记图像 取反
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
*(lpSrc)=255-(*lpSrc);
*(lpDst)=255-(*lpDst);
}
}
//重构
ReConstruction(pDoc->m_pDib->m_lpImage,lpNewDIBBits);
// 重构图像 取反
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpDst++;
*(lpDst)=255-(*lpDst);
}
}
TRACE("\nUsed Time is %.3f ms\n",exeTimer.GetTime(false)*1000);
CString str=pDoc->GetTitle();
pDoc->SetTitle(str+"重构");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
for(int i=0;i<M;i++)
delete []S[i];
delete []S;
// 释放内存
delete []lpNewDIBBits;
// 恢复光标
EndWaitCursor();
}
void CImageProcessView::GrayFastOperate(bool bDilate){
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
_ASSERT(lpNewDIBBits != NULL);//false
memcpy( lpNewDIBBits,pDoc->m_pDib->m_lpImage, lLineBytes * lHeight);
//结构分解:
//seq = getsequence(se)
unsigned char* lpSrc;
unsigned char* lpDst;
//1)
int M=15;
int N=15;
//腐蚀运算,定义域内输入数据减对应模板数据,并求最小值,该最小值便是该点输出
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
int gray=*lpSrc;
//for (int m = 0; m < M; m++)
int m=M/2;
{
for (int n = 0; n < N; n++)
{ // if(S[m][n]<0) continue;
if(i-M/2 + m>=0 && i-M/2 +m<lHeight && j+n - N/2>=0 && j+n - N/2<lWidth)
{
int tmp=*(lpSrc + lLineBytes*(M/2 - m) +(n - N/2));//-S[m][n];
if(bDilate)
{if(tmp>gray) gray=tmp;}//max
else
{ if(tmp<gray) gray=tmp;}//min
}
}
}
*lpDst=(BYTE)gray;
}
}
//2)
M=11;N=11;
//腐蚀运算,定义域内输入数据减对应模板数据,并求最小值,该最小值便是该点输出
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = lpNewDIBBits + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =(unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
int gray=*lpSrc;
for (int m = 0; m < M; m++)
{
//for (int n = 0; n < N; n++)
int n=m;
{ // if(S[m][n]<0) continue;
if(i-M/2 + m>=0 && i-M/2 +m<lHeight && j+n - N/2>=0 && j+n - N/2<lWidth)
{
int tmp=*(lpSrc + lLineBytes*(M/2 - m) +(n - N/2));//-S[m][n];
if(bDilate)
{if(tmp>gray) gray=tmp;}//max
else
{ if(tmp<gray) gray=tmp;}//min
}
}
}
*lpDst=(BYTE)gray;
}
}
//3
M=15;
N=15;
//腐蚀运算,定义域内输入数据减对应模板数据,并求最小值,该最小值便是该点输出
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
int gray=*lpSrc;
for (int m = 0; m < M; m++)
{
//for (int n = 0; n < N; n++)
int n=m/2;
{ //if(S[m][n]<0) continue;
if(i-M/2 + m>=0 && i-M/2 +m<lHeight && j+n - N/2>=0 && j+n - N/2<lWidth)
{
int tmp=*(lpSrc + lLineBytes*(M/2 - m) +(n - N/2));//-S[m][n];
if(bDilate)
{if(tmp>gray) gray=tmp;}//max
else
{ if(tmp<gray) gray=tmp;}//min
}
}
}
*lpDst=(BYTE)gray;
}
}
//4)
M=11;N=11;
//腐蚀运算,定义域内输入数据减对应模板数据,并求最小值,该最小值便是该点输出
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = lpNewDIBBits + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =(unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
int gray=*lpSrc;
for (int m = 0; m < M; m++)
{
//for (int n = 0; n < N; n++)
int n=N-1-m;
{ // if(S[m][n]<0) continue;
if(i-M/2 + m>=0 && i-M/2 +m<lHeight && j+n - N/2>=0 && j+n - N/2<lWidth)
{
int tmp=*(lpSrc + lLineBytes*(M/2 - m) +(n - N/2));//-S[m][n];
if(bDilate)
{if(tmp>gray) gray=tmp;}//max
else
{ if(tmp<gray) gray=tmp;}//min
}
}
}
*lpDst=(BYTE)gray;
}
}
//5
M=5;
N=5;
//腐蚀运算,定义域内输入数据减对应模板数据,并求最小值,该最小值便是该点输出
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
int gray=*lpSrc;
for (int m = 0; m < M; m++)
{
//for (int n = 0; n < N; n++)
int n=m/2;
{ //if(S[m][n]<0) continue;
if(i-M/2 + m>=0 && i-M/2 +m<lHeight && j+n - N/2>=0 && j+n - N/2<lWidth)
{
int tmp=*(lpSrc + lLineBytes*(M/2 - m) +(n - N/2));//-S[m][n];
if(bDilate)
{if(tmp>gray) gray=tmp;}//max
else
{ if(tmp<gray) gray=tmp;}//min
}
}
}
*lpDst=(BYTE)gray;
}
}
//6
M=5;
N=5;
//腐蚀运算,定义域内输入数据减对应模板数据,并求最小值,该最小值便是该点输出
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++){
lpDst = (unsigned char *)pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
int gray=*lpSrc;
//for (int m = 0; m < M; m++)
int m=M/2;
{
for (int n = 0; n < N; n++)
{ // if(S[m][n]<0) continue;
if(i-M/2 + m>=0 && i-M/2 +m<lHeight && j+n - N/2>=0 && j+n - N/2<lWidth)
{
int tmp=*(lpSrc + lLineBytes*(M/2 - m) +(n - N/2));//-S[m][n];
if(bDilate)
{if(tmp>gray) gray=tmp;}//max
else
{ if(tmp<gray) gray=tmp;}//min
}
}
}
*lpDst=(BYTE)gray;
}
}
// 释放内存
delete []lpNewDIBBits;
}
void CImageProcessView::ReConstruction(unsigned char* lpLevel,unsigned char* lpMasked){
//
CImageProcessDoc* pDoc = GetDocument();
unsigned char* lpSrc;
unsigned char* lpDst;
unsigned char* lpMask;
unsigned char* lpNewDIBBits;
lpNewDIBBits=new unsigned char [lLineBytes*lHeight];
_ASSERT(lpNewDIBBits != NULL);//false
unsigned char* lpNewDIBBits1;
lpNewDIBBits1=new unsigned char [lLineBytes*lHeight];
_ASSERT(lpNewDIBBits1 != NULL);//false
memcpy(lpNewDIBBits, lpLevel, lLineBytes * lHeight);
memcpy(lpNewDIBBits1, lpLevel, lLineBytes * lHeight);
bool bChg=true;
int num=0;
while(bChg)
{
num++;
bChg=false;
//memcpy( lpLevel,lpNewDIBBits, lLineBytes * lHeight);
水平膨胀运算
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{
lpSrc = lpLevel + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x;
lpDst =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x+1; j <=pDoc->EndPoint.x-1; j ++){
lpSrc++;lpDst++;
*lpDst=max(*lpSrc,max(*(lpSrc+1),*(lpSrc-1))); ;
}
}
垂直膨胀运算
for (int i = pDoc->StartPoint.y+1; i <=pDoc->EndPoint.y-1; i ++)
{
lpDst = lpNewDIBBits1 + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
lpSrc =lpNewDIBBits + lLineBytes * (lHeight - 1 - i)+ pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;lpDst++;
*lpDst=max(*lpSrc,max(*(lpSrc+lLineBytes),*(lpSrc-lLineBytes)));
}
}
//比较运算
for (int i = pDoc->StartPoint.y+1; i <=pDoc->EndPoint.y-1; i ++)
{
lpSrc = lpLevel + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x;
lpMask= lpMasked+ lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x;
lpDst =lpNewDIBBits1 + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x+1; j <=pDoc->EndPoint.x-1; j ++){
lpDst++;lpMask++;lpSrc++;
if(*lpDst>*lpMask)
*lpDst=*lpMask;
if((*lpDst)!=(*lpSrc)){
bChg=true;
*lpSrc=*lpDst;
}
}
}
}
TRACE("\nnum=%d\n",num);
memcpy( pDoc->m_pDib->m_lpImage,lpLevel, lLineBytes * lHeight);
// 释放内存
delete []lpNewDIBBits;
delete []lpNewDIBBits1;
}
void CImageProcessView::OnEdgeRelaxation()
{
// TODO: 在此添加命令处理程序代码
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
CPoint* pEdgeInfo;//i | j // i - j
pEdgeInfo=new CPoint [lLineBytes*lHeight];
_ASSERT(pEdgeInfo != NULL);//false
CPoint* pEdgeInfo1;
//i | j
// i
// -
// j
pEdgeInfo1=new CPoint [lLineBytes*lHeight];
_ASSERT(pEdgeInfo1 != NULL);//false
//1 init c(e)=0---100
int eMax=200;
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{
unsigned char* lpSrc = pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
CPoint * pEdge =pEdgeInfo + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;pEdge++;
if(i==pDoc->EndPoint.y || j==pDoc->EndPoint.x)
*pEdge=CPoint(0,0);
else
{
(*pEdge)=CPoint(abs(*lpSrc-*(lpSrc+1)),abs(*lpSrc-*(lpSrc-lLineBytes)));
if((*pEdge).x>eMax)
eMax=(*pEdge).x;
if((*pEdge).y>eMax)
eMax=(*pEdge).y;
}
}
}
//
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{
CPoint * pEdge =pEdgeInfo + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
pEdge++;
(*pEdge).x=min(90,(*pEdge).x*200/eMax);
(*pEdge).y=min(90,(*pEdge).y*200/eMax);
if((*pEdge).x<10)// && (*pEdge).x>5)//q=10 not type err!
(*pEdge).x=0;
if((*pEdge).y<10)// && (*pEdge).y>5)
(*pEdge).y=0;
}
}
//2迭代num
const int num=100;
int no=0;
const int q=10;
const int delt=20;
int type[4];
bool bOver=false;
while(no<num && !bOver){
no++;
bOver=true;
memcpy(pEdgeInfo1,pEdgeInfo,lLineBytes*lHeight*sizeof(CPoint));
for (int i = pDoc->StartPoint.y+1; i <=pDoc->EndPoint.y-1; i ++)
{
CPoint * pEdge1 =pEdgeInfo1 + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x;
CPoint * pEdge =pEdgeInfo + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x;
for (int j =pDoc->StartPoint.x+1; j <=pDoc->EndPoint.x-1; j ++){
pEdge1++;pEdge++;
int a=(*(pEdge1-1)).x;
int b=(*(pEdge1-1)).y;
int c=(*(pEdge1-lLineBytes-1)).x;
//sort
if(a<b)
Swap(&a,&b);
if(a<c)
Swap(&a,&c);
if(b<c)
Swap(&b,&c);
int m=max(q,a);
int Snode=0;
type[0]=(m-a)*(m-b)*(m-c);
type[1]=a*(m-b)*(m-c);
type[2]=a*b*(m-c);
type[3]=a*b*c;
int maxT=type[0];
for(int k=1;k<4;k++){
if(maxT<type[k]){
Snode=k;
maxT=type[k];
}
}
int d=(*(pEdge1)).x;
int g=(*(pEdge1+1)).y;
int f=(*(pEdge1-lLineBytes)).x;
//sort
if(d<g)
Swap(&d,&g);
if(d<f)
Swap(&d,&f);
if(g<f)
Swap(&g,&f);
m=max(q,d);
type[0]=(m-d)*(m-g)*(m-f);
type[1]=d*(m-g)*(m-f);
type[2]=d*g*(m-f);
type[3]=d*g*f;
int Enode=0;
maxT=type[0];
for(int k=1;k<4;k++){
if(maxT<type[k]){
Enode=k;
maxT=type[k];
}
}
if((Snode==0 && Enode!=1) || (Snode!=1 && Enode==0))//-
{
(*pEdge).y=max((*pEdge).y-delt,0);bOver=false;
}
if((Snode==1 && Enode==1))//+
{
(*pEdge).y=min((*pEdge).y+delt,100);bOver=false;
}else
if((Snode==1 && Enode!=0) || (Snode!=0 && Enode==1))//+
{
(*pEdge).y=min((*pEdge).y+delt/2,100);bOver=false;
}
a=(*(pEdge1+lLineBytes)).x;
b=(*(pEdge1+lLineBytes)).y;
c=(*(pEdge1+lLineBytes+1)).y;
//sort
if(a<b)
Swap(&a,&b);
if(a<c)
Swap(&a,&c);
if(b<c)
Swap(&b,&c);
m=max(q,a);
type[0]=(m-a)*(m-b)*(m-c);
type[1]=a*(m-b)*(m-c);
type[2]=a*b*(m-c);
type[3]=a*b*c;
Snode=0;
maxT=type[0];
for(int k=1;k<4;k++){
if(maxT<type[k]){
Snode=k;
maxT=type[k];
}
}
d=(*(pEdge1)).y;
g=(*(pEdge1+1)).y;
f=(*(pEdge1-lLineBytes)).x;
//sort
if(d<g)
Swap(&d,&g);
if(d<f)
Swap(&d,&f);
if(g<f)
Swap(&g,&f);
m=max(q,d);
type[0]=(m-d)*(m-g)*(m-f);
type[1]=d*(m-g)*(m-f);
type[2]=d*g*(m-f);
type[3]=d*g*f;
Enode=0;
maxT=type[0];
for(int k=1;k<4;k++){
if(maxT<type[k]){
Enode=k;
maxT=type[k];
}
}
if((Snode==0 && Enode!=1) || (Snode!=1 && Enode==0))//-
{
(*pEdge).x=max((*pEdge).x-delt,0);bOver=false;
}
if((Snode==1 && Enode==1))//+
{
(*pEdge).x=min((*pEdge).x+delt,100);bOver=false;
}else
if((Snode==1 && Enode!=0) || (Snode!=0 && Enode==1))//+
{
(*pEdge).x=min((*pEdge).x+delt/2,100);bOver=false;
}
}
}
}
TRACE("\n\n run: %d\n\n",no);
//3输出结果
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y-1; i ++)
{
unsigned char* lpSrc = pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
CPoint * pEdge =pEdgeInfo + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x-1; j ++){
lpSrc++;pEdge++;
*lpSrc=0;//max((*pEdge).x,(*pEdge).y);
if((*pEdge).x>80){
*lpSrc=255;
}
}
}
DisplayNewImg(pDoc->m_pDib->m_lpImage,lLineBytes,lHeight,"垂直边缘松弛");
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y-1; i ++)
{
unsigned char* lpSrc = pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
CPoint * pEdge =pEdgeInfo + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x-1; j ++){
lpSrc++;pEdge++;
*lpSrc=0;//max((*pEdge).x,(*pEdge).y);
if((*pEdge).y>80){
*lpSrc=255;
}
}
}
DisplayNewImg(pDoc->m_pDib->m_lpImage,lLineBytes,lHeight,"水平边缘松弛");
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y-1; i ++)
{
unsigned char* lpSrc = pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
CPoint * pEdge =pEdgeInfo + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x-1; j ++){
lpSrc++;pEdge++;
*lpSrc=0;//max((*pEdge).x,(*pEdge).y);
if((*pEdge).x>80 && (*pEdge).y<80){
*lpSrc=255;
}
if((*pEdge).x<80 && (*pEdge).y>80){
*lpSrc=255;
}
}
}
pDoc->SetTitle("边缘松弛");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
// 恢复光标
EndWaitCursor();
delete[]pEdgeInfo;
delete[]pEdgeInfo1;
}
void CImageProcessView::OnUpdateEdgeRelaxation(CCmdUI *pCmdUI)
{
// TODO: 在此添加命令更新用户界面处理程序代码
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::Swap(int* a, int* b){
int tmp=*a;
*a=*b;
*b=tmp;
}
void CImageProcessView::OnSegmentationBoundarytrace()
{
// TODO: 在此添加命令处理程序代码
CImageProcessDoc* pDoc = GetDocument();
BeginWaitCursor();
int* pCost;//i | j // i - j
pCost=new int [lLineBytes*lHeight];
_ASSERT(pCost != NULL);//false
memset(pCost,0,lLineBytes*lHeight*sizeof(int));
//get cost
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{
unsigned char* lpSrc = pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pDoc->StartPoint.x-1;
int* pC =pCost + lLineBytes*i + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;pC++;
*lpSrc=min(*lpSrc,254);//for diaply
if(i == pDoc->StartPoint.y){
*pC=*lpSrc;
}else
{
if(j == pDoc->StartPoint.x)
*pC=*lpSrc+min(*(pC-lLineBytes),*(pC-lLineBytes+1));
else
if(j == pDoc->EndPoint.x)
*pC=*lpSrc+min(*(pC-lLineBytes),*(pC-lLineBytes-1));
else
*pC=*lpSrc+min(*(pC-lLineBytes),min(*(pC-lLineBytes-1),*(pC-lLineBytes+1)));
}
}
}
//get min path
vector<int> path;
int pos=pDoc->StartPoint.x+1;
int min=*(pCost + lLineBytes*pDoc->EndPoint.y + pDoc->StartPoint.x+1);
for (int j =pDoc->StartPoint.x+1; j <=pDoc->EndPoint.x-1; j ++){
int* pC =pCost + lLineBytes*pDoc->EndPoint.y + j;
if(*pC<min){
min=*pC;
pos=j;
}
// TRACE("\t%d",*pC);
}
path.push_back(pos);
for (int i =pDoc->EndPoint.y-1 ; i >=pDoc->StartPoint.y; i --){
int* pC =pCost + lLineBytes*i + pos;
if(*(pC-1)<min(*(pC),*(pC+1)))
pos--;
if(*(pC+1)<min(*(pC),*(pC-1)))
pos++;
path.push_back(pos);
}
//display
unsigned char* lpSrc;
for (int i =pDoc->EndPoint.y ; i >=pDoc->StartPoint.y; i --){
int pos=path[pDoc->EndPoint.y-i];
lpSrc = pDoc->m_pDib->m_lpImage + lLineBytes* (lHeight-1-i) + pos;
*lpSrc=255;
}
lpSrc=(unsigned char*)pDoc->m_pDib->m_lpvColorTable;
*(lpSrc+255*4+1)=0;*(lpSrc+255*4)=0;*(lpSrc+255*4+2)=255;
pDoc->SetTitle("边界跟踪(最小路径)");
InvalidateRect(CRect(pDoc->StartPoint.x,pDoc->StartPoint.y,pDoc->EndPoint.x,pDoc->EndPoint.y),true);
// 恢复光标
EndWaitCursor();
delete[]pCost;
}
void CImageProcessView::OnUpdateSegmentationBoundarytrace(CCmdUI *pCmdUI)
{
// TODO: 在此添加命令更新用户界面处理程序代码
CImageProcessDoc* pDoc = GetDocument();
BOOL bAvail=false;
if(pDoc->m_pDib->m_lpBMIH!=NULL)
if(pDoc->m_pDib->m_lpBMIH->biBitCount==8)
bAvail=true;
pCmdUI->Enable(bAvail);
}
void CImageProcessView::OnFileOpenavi()
{
TODO: 在此添加命令处理程序代码
TCHAR szFilters[]= _T("AVI Files (*.avi)|*.avi|");
// Create an Open dialog; the default file name extension is ".my".
CFileDialog fileDlg(TRUE, _T("avi"), _T("*.avi"),
OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilters);
// Display the file dialog. When user clicks OK, fileDlg.DoModal()
// returns IDOK.
if(fileDlg.DoModal() == IDOK)
{
if(fileDlg.GetFileExt()=="avi")
{
m_AviName=fileDlg.GetPathName();
if(!LoadAvi())
SetTimer(TIMER_AVI,60,NULL);
}
}
}
int CImageProcessView::LoadAvi(void)
{
CImageProcessDoc* pDoc = GetDocument();
//load avi
AVIFileInit();
PAVIFILE avi;
if(AVIFileOpen(&avi,m_AviName,OF_READ,NULL)!=AVIERR_OK)
return 1;
AVIFILEINFO avi_info;
AVIFileInfo(avi, &avi_info, sizeof(AVIFILEINFO));
if(avi_info.dwSuggestedBufferSize<avi_info.dwHeight*avi_info.dwWidth)
{
MessageBox("Avi 视频压缩,需要先解压!退出");
return 1;
}
if(AVIFileGetStream(avi, &m_pAviStream, streamtypeVIDEO ,0 /*first stream*/)!=AVIERR_OK)
return 1;
int iFirstFrame;
iFirstFrame=AVIStreamStart(m_pAviStream);
if (iFirstFrame==-1)
{
//Error getteing the frame inside the stream
if (m_pAviStream!=NULL)
AVIStreamRelease(m_pAviStream);
AVIFileExit();
return 1;
}
m_AviNumFrames=AVIStreamLength(m_pAviStream);//512
if (m_AviNumFrames==-1)
{
//Error getteing the number of frames inside the stream
if (m_pAviStream!=NULL)
AVIStreamRelease(m_pAviStream);
AVIFileExit();
return 1;
}
lHeight=avi_info.dwHeight;
lWidth=avi_info.dwWidth;
pDoc->StartPoint=CPoint(0,0);
pDoc->EndPoint=CPoint(lWidth-1,lHeight-1);
lLineBytes=(lWidth+3)/4*4;
if( pDoc->m_pDib)
delete pDoc->m_pDib;
pDoc->m_pDib =new CDib(CSize(lLineBytes,lHeight) ,8);
memset(pDoc->m_pDib->m_lpImage,0,lLineBytes*lHeight);
unsigned char* lpSrc=(unsigned char*)pDoc->m_pDib->m_lpvColorTable;
for(int i=0;i<256;i++){
*lpSrc=(unsigned char)i;lpSrc++;
*lpSrc=(unsigned char)i;lpSrc++;
*lpSrc=(unsigned char)i;lpSrc++;
*lpSrc=0;lpSrc++;
}
m_AviIndex=0;
pDoc->SetTitle(m_AviName);
return 0;
}
void CImageProcessView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if(nIDEvent==TIMER_AVI)
{
if(!GetAviNext())
KillTimer(TIMER_AVI);
Invalidate();
}
CScrollView::OnTimer(nIDEvent);
}
int CImageProcessView::GetAviNext(void)
{
CImageProcessDoc* pDoc = GetDocument();
m_pAviFrame=AVIStreamGetFrameOpen(m_pAviStream, NULL );
AVIStreamGetFrame(m_pAviFrame, m_AviIndex); //
BITMAPINFOHEADER bitmapH; // buffer containing the BITMAPINFOHEADER
long int len=40;
AVIStreamReadFormat(m_pAviStream,m_AviIndex,&bitmapH,&len);
int lineBytes=bitmapH.biWidth*2;//16bit
int height=bitmapH.biHeight;
if(bitmapH.biBitCount==24)
lineBytes=bitmapH.biWidth*3;//24bit
if(m_AviIndex==0)
{
if(m_AviBuff)
delete [] m_AviBuff;//may be 2 times open
m_AviBuff=new unsigned char [lineBytes*height];
}
AVIStreamRead(m_pAviStream,m_AviIndex,1, m_AviBuff,lineBytes*height,NULL,NULL);
AVIStreamGetFrameClose(m_pAviFrame);
m_AviIndex++;
CString str;
str.Format("Play Avi...%d/%d)",m_AviIndex,m_AviNumFrames);
((CMainFrame*)AfxGetMainWnd())->m_wndStatusBar.SetPaneText(0,str);
//获取数据图像
for (int i = pDoc->StartPoint.y; i <=pDoc->EndPoint.y; i ++)
{
unsigned char* lpSrc = pDoc->m_pDib->m_lpImage + lLineBytes* i + pDoc->StartPoint.x-1;
for (int j =pDoc->StartPoint.x; j <=pDoc->EndPoint.x; j ++){
lpSrc++;
if(bitmapH.biBitCount==24)
{
*lpSrc=*(m_AviBuff+i*lineBytes+j*3);
}
if(bitmapH.biBitCount==16)
{
*lpSrc=*(m_AviBuff+i*lineBytes+j*2)&0xf8;
//*lpSrc=*(m_AviBuff+i*lineBytes+j*2+1)&0xf8;
}
if(bitmapH.biBitCount==8)
{
*lpSrc=*(m_AviBuff+i*lineBytes+j);
}
}
}
//close the stream after finishing the task
if(m_AviIndex>=m_AviNumFrames)
{
if (m_pAviStream!=NULL)
AVIStreamRelease(m_pAviStream);
AVIFileExit();
if(m_AviBuff)
delete [] m_AviBuff;
m_AviBuff=NULL;
return 0;
}
else
return 1;
}
void CImageProcessView::OnFileBmp2avi()
{
// TODO: 在此添加命令处理程序代码
//CString strBmpDir="d:\\imageprocess\\bmpset";
//CString szAviName="d:\\imageprocess\\bmpset.avi";
CString strBmpDir="d:\\imageprocess\\jpgset";
CString szAviName="d:\\imageprocess\\jpgset.avi";
CFileFind finder;
strBmpDir += _T("\\*.*");
AVIFileInit();
AVISTREAMINFO strhdr;
PAVIFILE pfile=NULL;
PAVISTREAM ps=NULL;
int nFrames =0;
HRESULT hr;
BOOL bFind = finder.FindFile(strBmpDir);
CImage LoadImg;
while(bFind)
{
bFind = finder.FindNextFile();
if(!finder.IsDots() && !finder.IsDirectory())
{
CString pathName = finder.GetFilePath();
if(!LoadImg.IsNull())
LoadImg.Destroy();
LoadImg.Load(pathName);
if(!LoadImg.IsNull())
{
BYTE *tmp_buf = NULL;
if(nFrames ==0 )
{
AVIFileOpen(&pfile,szAviName,OF_WRITE | OF_CREATE,NULL);
memset(&strhdr, 0, sizeof(strhdr));
strhdr.fccType = streamtypeVIDEO;// stream type
strhdr.fccHandler = 0;
strhdr.dwScale = 1;
strhdr.dwRate = 15; // 15 fps
strhdr.dwSuggestedBufferSize = LoadImg.GetWidth()*LoadImg.GetHeight()*3;//bmpInfoHdr.biSizeImage ;
SetRect(&strhdr.rcFrame, 0, 0, LoadImg.GetWidth(),LoadImg.GetHeight());
// And create the stream;
hr = AVIFileCreateStream(pfile,&ps,&strhdr);
// hr = AVIStreamSetFormat(ps,nFrames,&bmpInfoHdr,sizeof(bmpInfoHdr));
}
tmp_buf = new BYTE[ LoadImg.GetWidth()*LoadImg.GetHeight() * 3];
byte* pRealData;
pRealData=(byte*)LoadImg.GetBits();
int pit=LoadImg.GetPitch();//-line:-1056
for (int y=0; y<LoadImg.GetHeight(); y++)
for (int x=0; x<LoadImg.GetWidth(); x++)
{ if(LoadImg.GetBPP()==24)
{
*(tmp_buf -pit*(LoadImg.GetHeight()-1-y) +3*x)=*(pRealData + pit*y +3*x); ;
*(tmp_buf -pit*(LoadImg.GetHeight()-1-y) +3*x+1)=*(pRealData + pit*y +3*x+1); ;
*(tmp_buf -pit*(LoadImg.GetHeight()-1-y) +3*x+2)=*(pRealData + pit*y +3*x+2); ;
}
if(LoadImg.GetBPP()==8)
{
*(tmp_buf -3*pit*(LoadImg.GetHeight()-1-y) +3*x)=*(pRealData + pit*y +x); ;
*(tmp_buf -3*pit*(LoadImg.GetHeight()-1-y) +3*x+1)=*(pRealData + pit*y +x); ;
*(tmp_buf -3*pit*(LoadImg.GetHeight()-1-y) +3*x+2)=*(pRealData + pit*y +x); ;
}
}
CDib dib(CSize( LoadImg.GetWidth(),LoadImg.GetHeight()),24);
//dib.m_lpBMIH->biXPelsPerMeter=4724;
//dib.m_lpBMIH->biYPelsPerMeter=4724;
for(int i=0;i<3;i++)//增加长度
{
hr = AVIStreamSetFormat(ps,nFrames,dib.m_lpBMIH,40);
hr = AVIStreamWrite(ps, // stream pointer
nFrames , // time of this frame
1, // number to write
(LPBYTE) tmp_buf,
LoadImg.GetWidth()*LoadImg.GetHeight()*3,//bmpInfoHdr.biSizeImage , // size of this frame
AVIIF_KEYFRAME, // flags....
NULL,
NULL);
nFrames ++;
}
delete []tmp_buf;
}
}
}
AVIStreamClose(ps);
if(pfile != NULL)
AVIFileRelease(pfile);
AVIFileExit();
}
void CImageProcessView::OnRButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CImageProcessDoc* pDoc = GetDocument();
//for test
CDemoTimer exeTimer;
exeTimer.Reset();
/
TRACE("\nUsed Time is %.3f ms\n",exeTimer.GetTime(false)*1000);
CScrollView::OnRButtonDown(nFlags, point);
}