首先是边缘检测,加上原图像是图像锐化。函数
直方图均衡:把原始图的直方图变换为均匀分布的形式,增长像素灰度值的动态范围,提升图像对比度。 spa
主要步骤:先统计各个像素占所有像素的比例,而后像素x的 直方图均衡后的像素值就是(x的比例+全部像素值比x小的比例)*255。实现图像均衡的结果。code
实验结果:orm
原图像:blog
直方图均衡后的图像:rem
代码:(是在MFC上实现的,课程祖传模板)string
void CDemoView::OnImagestretchingHistogramequalization() { // TODO: 在此添加命令处理程序代码 CDemoDoc *pDoc = GetDocument(); HDIB dib = pDoc->GetHDIB(); LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)dib); int width = ::DIBWidth(lpDIB); int height = ::DIBHeight(lpDIB); LPBITMAPINFOHEADER phead = (LPBITMAPINFOHEADER)lpDIB; int biBitCount = phead->biBitCount / 8; if (biBitCount != 1) { ::MessageBox(0, "ERROR!NOT GRAY LEVEL IMAGE!", NULL, MB_OK); ::GlobalUnlock(dib); return; } int lineByte = (width * biBitCount + 3) / 4 * 4; unsigned char *lpDIBBits = (unsigned char *)::FindDIBBits(lpDIB); int palSize = ::PaletteSize((LPSTR)lpDIB); //调色板尺寸 HANDLE dibNew = ::GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER) + palSize + height * lineByte); LPSTR lpDIBNew = (LPSTR) ::GlobalLock(dibNew); ::memcpy((unsigned char*)lpDIBNew, (unsigned char*)lpDIB, sizeof(BITMAPINFOHEADER) + palSize + height * lineByte); unsigned char *lpDIBBitsNew = (unsigned char *)::FindDIBBits(lpDIBNew); int max = 0; int min = 255; int data; int i, j; double pix[256]; for (i = 0;i < 256;++i) { pix[i] = 0; } for (i = 0;i < height;i++) { for (j = 0;j < width;j++) { data = *(lpDIBBits + i * lineByte + j); pix[data]++; } } for (i = 1;i < 256;++i) { pix[i] = pix[i] + pix[i - 1]; } for (i = 1;i < 256;++i) { pix[i] = pix[i]/width/height*255; } for (i = 0;i < height;i++) { for (j = 0;j < width;j++) { *(lpDIBBitsNew + i * lineByte + j) = (int)(pix[*(lpDIBBits + i * lineByte + j)] + 0.5); } } ::GlobalUnlock(dib); ::GlobalUnlock(dibNew); CMainFrame* pFrame = (CMainFrame *)(AfxGetApp()->m_pMainWnd); pFrame->SendMessage(WM_COMMAND, ID_FILE_NEW); CDemoView* pView = (CDemoView*)pFrame->MDIGetActive()->GetActiveView(); CDemoDoc* pDocNew = pView->GetDocument(); pDocNew->ReplaceHDIB((HDIB)dibNew); pDocNew->InitDIBData(); pDocNew->UpdateAllViews(pView); Invalidate(); }
laplace算子:it
采用参考点匹配来计算旋转参数:io
二维旋转能够用一下方程拟合:图像处理
u,v是原图像坐标。x,y是徐艳转后图像的坐标。
记下七组点的坐标,采用最小二乘法计算系数。
代码以下路所示:
函数采用了eigen库的矩阵Matrixxd模块, 其中七组点的数量根据交互的形式记在vector<int>pointvec
void CDemoView::OnLeastsquaremethodk() { // TODO: 在此添加命令处理程序代码 CDemoDoc *pDoc = GetDocument(); HDIB dib = pDoc->GetHDIB(); LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)dib); int height = ::DIBHeight(lpDIB); int width = ::DIBWidth(lpDIB); LPBITMAPINFOHEADER phead = (LPBITMAPINFOHEADER)lpDIB; int biBitCount = phead->biBitCount / 8; int lineByte = (width * biBitCount + 3) / 4 * 4; unsigned char *lpDIBBits = (unsigned char *)::FindDIBBits(lpDIB); int palSize = ::PaletteSize((LPSTR)lpDIB); //调色板尺寸 HANDLE dibNew = ::GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER) + palSize + height * lineByte); LPSTR lpDIBNew = (LPSTR) ::GlobalLock(dibNew); ::memcpy((unsigned char*)lpDIBNew, (unsigned char*)lpDIB, sizeof(BITMAPINFOHEADER) + palSize ); unsigned char *lpDIBBitsNew = (unsigned char *)::FindDIBBits(lpDIBNew); MatrixXd b1, b2; MatrixXd X=MatrixXd::Zero(7, 6); MatrixXd Y1= MatrixXd::Zero(7, 1); MatrixXd Y2 = MatrixXd::Zero(7, 1); if (pointVec.size() == 14) { for (int i = 0;i < 7;++i) { CPoint point = pointVec[i]; point.y = height - point.y; X(i, 0) = 1; X(i, 1) = point.x; X(i, 2) = point.y; X(i, 3) = point.x*point.x; X(i, 4) = point.y*point.y; X(i, 5) = point.x*point.y; } for (int i = 7;i < 14;++i) { CPoint point = pointVec[i]; point.y = height - point.y; Y1(i - 7, 0) = point.x; Y2(i - 7, 0) = point.y; } } MatrixXd tmp = (X.transpose()*X).inverse(); b1 =tmp*X.transpose()*Y1; b2 = tmp * X.transpose()*Y2; CString string; pointVec.clear(); string.Format("k100:%3f,k110:%3f,k101:%f,k120:%3f,k102:%3f,k111:%3f\nk200:%3f,k210:%3f,k201:%3f,k220:%3f,k202:%3f,k221:%3f", b1(0,0), b1(1, 0), b1(2, 0), b1(3, 0), b1(4, 0), b1(5, 0), b2(0, 0), b2(1, 0), b2(2, 0), b2(3, 0), b2(4, 0), b2(5, 0) ); ::MessageBox(0,string, "dataMessage", MB_OKCANCEL); for (int i = 0;i < height;++i) { for (int j = 0;j < width;++j) { for (int z = 0;z < biBitCount;++z) { *(lpDIBBitsNew + i * lineByte + j * biBitCount + z) = 0; } } } for (int i = 0;i < height;++i) { for (int j = 0;j < width;++j) { tmpdata(0, 0) = 1; tmpdata(0, 1) = j; tmpdata(0, 2) = i; tmpdata(0, 3) = j*j; tmpdata(0, 4) = i*i; tmpdata(0, 5) = i*j; float xnum = (tmpdata * b1).determinant(); float ynum = (tmpdata * b2).determinant(); int xint = (int)xnum; int yint = (int)ynum; for (int z = 0;z < biBitCount;++z) { if (xnum >= 0 && xnum < width&&ynum >= 0 && ynum <= height) { if (xnum >= 1 && xnum < width - 1 && ynum >= 1 && ynum <= height - 1) *(lpDIBBitsNew + i * lineByte + j * biBitCount + z) = *(lpDIBBits + yint * lineByte + xint * biBitCount + z) + (*(lpDIBBits + (yint + 1) * lineByte + xint * biBitCount + z) - *(lpDIBBits + yint * lineByte + xint * biBitCount + z))*(ynum - yint) + (*(lpDIBBits + yint * lineByte + (xint + 1) * biBitCount + z) - *(lpDIBBits + yint * lineByte + xint * biBitCount + z))*(xnum - xint) + (*(lpDIBBits + (yint + 1) * lineByte + (xint + 1) * biBitCount + z) + *(lpDIBBits + yint * lineByte + xint * biBitCount + z) - *(lpDIBBits + (yint + 1) * lineByte + xint * biBitCount + z) - *(lpDIBBits + yint * lineByte + (xint + 1) * biBitCount + z))*(xnum - xint)*(ynum - yint); else *(lpDIBBitsNew + i * lineByte + j * biBitCount + z) = *(lpDIBBits + yint * lineByte + xint * biBitCount + z); } } } } ::GlobalUnlock(dib); ::GlobalUnlock(dibNew); CMainFrame* pFrame = (CMainFrame *)(AfxGetApp()->m_pMainWnd); pFrame->SendMessage(WM_COMMAND, ID_FILE_NEW); CDemoView* pView = (CDemoView*)pFrame->MDIGetActive()->GetActiveView(); CDemoDoc* pDocNew = pView->GetDocument(); pDocNew->ReplaceHDIB((HDIB)dibNew); pDocNew->InitDIBData(); pDocNew->UpdateAllViews(pView); Invalidate(); }
大津阈值分割:最大方差分割:
代码以下:
void CDemoView::OnOtsuthresholdsegmentation() { // TODO: 在此添加命令处理程序代码 CDemoDoc *pDoc = GetDocument(); HDIB dib = pDoc->GetHDIB(); LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)dib); int width = ::DIBWidth(lpDIB); int height = ::DIBHeight(lpDIB); LPBITMAPINFOHEADER phead = (LPBITMAPINFOHEADER)lpDIB; int biBitCount = phead->biBitCount / 8; if (biBitCount != 1) { ::MessageBox(0, "ERROR!NOT GRAY LEVEL IMAGE!", NULL, MB_OK); ::GlobalUnlock(dib); return; } int lineByte = (width * biBitCount + 3) / 4 * 4; unsigned char *lpDIBBits = (unsigned char *)::FindDIBBits(lpDIB); int palSize = ::PaletteSize((LPSTR)lpDIB); //调色板尺寸 HANDLE dibNew = ::GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER) + palSize + height * lineByte); LPSTR lpDIBNew = (LPSTR) ::GlobalLock(dibNew); ::memcpy((unsigned char*)lpDIBNew, (unsigned char*)lpDIB, sizeof(BITMAPINFOHEADER) + palSize + height * lineByte); unsigned char *lpDIBBitsNew = (unsigned char *)::FindDIBBits(lpDIBNew); int max = 0; int min = 255; int data; int i, j; double pix[256]; int sumpix = height * width; for (i = 0;i < 256;++i) { pix[i] = 0; } for (i = 0;i < height;i++) { for (j = 0;j < width;j++) { data = *(lpDIBBits + i * lineByte + j); pix[data]++; } } for (i = 0;i < 256;++i) { pix[i] = pix[i] / sumpix; } double SquErr[256]; for (int i = 0;i < 256;++i) { //T=i 为阈值 double w0 = 0, w1 = 0; double u0 = 0, u1 = 0; for (j = 0;j < i;++j) { w0 = w0 + pix[j]; u0 =u0+ j * pix[j]; } if(w0!=0) u0 = u0 / w0; w1 = 1 - w0; for (j = i;j < 256;++j) { u1 =u1 +j * pix[j]; } if(w1!=0) u1 = u1 / w1; SquErr[i] = w0 * w1*(u1 - u0)*(u1 - u0); } int maxpos=0; double maxerr = SquErr[0]; for (i = 0;i < 256;++i) { //求最大方差 if (maxerr < SquErr[i]) { maxpos = i; maxerr = SquErr[i]; } } for (i = 0;i < height;i++) { for (j = 0;j < width;j++) { if(*(lpDIBBits + i * lineByte + j)<maxpos) *(lpDIBBitsNew + i * lineByte + j) = 0; else *(lpDIBBitsNew + i * lineByte + j) = 255; } } ::GlobalUnlock(dib); ::GlobalUnlock(dibNew); CMainFrame* pFrame = (CMainFrame *)(AfxGetApp()->m_pMainWnd); pFrame->SendMessage(WM_COMMAND, ID_FILE_NEW); CDemoView* pView = (CDemoView*)pFrame->MDIGetActive()->GetActiveView(); CDemoDoc* pDocNew = pView->GetDocument(); pDocNew->ReplaceHDIB((HDIB)dibNew); pDocNew->InitDIBData(); pDocNew->UpdateAllViews(pView); Invalidate(); }
还有图像压缩的一些东西,下次再写