基於OpenCV影象最小二乘相位解包裹演算法
QT:5.5.1 編譯器:mcvs2012 OpenCV:2.4.9
演算法寫在Qt上一個按鈕上,相當於一個main函式,主要是變化的源影象與目標影象的深度,通道的匹配容易報錯。
void MainWindow::on_pushButton_clicked() { double pi = 3.14156; IplImage *img = cvLoadImage("D:/3.jpg"); //讀取本地圖片 IplImage *imgGray = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1); //建立灰度圖頭 cvCvtColor(img,imgGray,CV_RGB2GRAY); //轉為灰度圖 IplImage *imgSobel = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1); //影象在x,y方向上做兩次微分 cvSobel(imgGray,imgSobel,2,2,5); IplImage *imgSobel_64F = cvCreateImage(cvGetSize(img),IPL_DEPTH_64F,1); //矩陣深度由8U轉為64F cvConvertScale(imgSobel, imgSobel_64F, 1.0/255, 0); IplImage *imgPhase = cvCreateImage(cvGetSize(img),IPL_DEPTH_64F,1); //做正方向離散餘弦變化 cvDCT(imgSobel_64F,imgPhase,CV_DXT_FORWARD); for(int i=0;i<imgPhase->height;i++) //遍歷影象 for(int j=0;j<imgPhase->width;j++) { double k1 = 2*cos((i-1)*pi/(imgPhase->height)); double k2 = 2*cos((j-1)*pi/(imgPhase->width)); double k = k1 + k2 - 4; CvScalar k0 = cvScalar(cvGet2D(imgPhase,i,j).val[0]/k); cvSet2D(imgPhase,i,j,k0); //對不同元素做相應加減 } IplImage *imgPhaseDst = cvCreateImage(cvGetSize(imgPhase),IPL_DEPTH_64F,1); CvScalar tmp = cvScalar((cvGet2D(imgPhase,1,1).val[0]-cvGet2D(imgPhase,1,2).val[0]-cvGet2D(imgPhase,2,1).val[0])/2); //第一個元素特殊處理 cvSet2D(imgPhaseDst,1,1,tmp); cvDCT(imgPhase,imgPhaseDst,CV_DXT_INVERSE); //反離散餘弦變化 cvNamedWindow("Phase"); //顯示解包裹相點陣圖 cvShowImage("Phase",imgPhaseDst); } 下面是MATLAB程式碼,寫在子函式中: %% ***********************橫向剪下最小二乘解包裹演算法函式************* function Un_Pha = Unwrap_Alg(Phi) %**************判斷輸入圖片轉化為單通道(灰度圖)*********** X = size(Phi); Phi = double(rgb2gray(Phi)); %********************對包裹相位求一階偏微分************** [m,n] = size(Phi); Phidx = zeros(m,n); phidy = zeros(m,n); Phidx(1:m-1,:) = angle(exp(j*(Phi(2:m,:)-Phi(1:m-1,:)))); %在X方向微分 phidy(:,1:n-1) = angle(exp(j*(Phi(:,2:n)-Phi(:,1:n-1)))); %在Y方向微分 %********************對包裹相位求二階偏微分************** Rou3 = zeros(m,n); Rou3dx = zeros(m,n); Rou3dy = zeros(m,n); Rou3dx(1:m-1,:) = angle(exp(j*(Phidx(2:m,:)-Phidx(1:m-1,:))));%在X方向二次微分 Rou3dy(:,1:n-1) = angle(exp(j*(phidy(:,2:n)-phidy(:,1:n-1))));%在Y方向二次微分 Rou3 = Rou3dx + Rou3dy; %二階的二次微分值相加 %***********************DCT求解泊松方程******************** % 橫向剪下最小二乘解包裹實際是求解離散泊松方程 tic %時間計時開始 PP3 = dct2(Rou3); %離散泊松變換 for ii=1:m for jj=1:n k1=2*cos((ii-1)*pi/(m)); k2=2*cos((jj-1)*pi/(n)); KK = k1+k2-4; PH3(ii,jj) = PP3(ii,jj)/KK; %離散泊松變換後,乘以一個因子 end end PH3(1,1) = -(PH3(1,2) + PH3(2,1) - PP3(1,1))/2; Un_Pha = idct2(PH3); %離散泊松反變換 toc %時間計時結束 Un_Pha = Un_Pha(1:m,1:n); Mat型別的,圖片的行數列數必須是偶數:
void MainWindow::on_pushButton_3_clicked() { double pi = 3.14156; Mat img = imread("D:/1.jpg",1); Mat imgGray; cvtColor(img,imgGray,CV_BGR2GRAY); Mat imgSobel; Sobel(imgGray,imgSobel,CV_8U,2,2,3,1,0,BORDER_DEFAULT); Mat imgPhase,imgPhaseTmp; imgSobel.convertTo(imgPhaseTmp,CV_64FC1); cv::dct(imgPhaseTmp,imgPhase,CV_DXT_FORWARD); for(int i=1;i<(imgPhase.rows);i++) for(int j=1;j<(imgPhase.cols);j++) { double k1 = 2*cos((i-1)*pi/(imgPhase.rows)); double k2 = 2*cos((j-1)*pi/(imgPhase.cols)); double k = k1 + k2 -4; imgPhase.at<uchar>(i,j) /= k; } imgPhase.at<uchar>(1,1) = (imgPhase.at<uchar>(1,1)-imgPhase.at<uchar>(1,2)-imgPhase.at<uchar>(2,1))/2; Mat imgPhaseDst; cv::dct(imgPhase,imgPhaseDst,CV_DXT_INVERSE); namedWindow("src",1); imshow("src",imgPhaseDst); } 以上用opencv的程式碼有一些考慮不周到的地方,改進一下,還是有些問題,矩陣存在負數問題,利用Mat_加以解決,DCT離散餘弦變換的問題,當影象矩陣是double型,dct正變換,再變換,圖形只剩下邊界,原因不知,正在解決。
double pi = 3.141593; Mat imgGray = imread("D:/Pic/4.jpg",0); //imshow("gray",imgGray); //Mat imgGray; //cvtColor(img,imgGray,CV_BGR2GRAY); Mat imgGray1,imgGray2,imgSobelX1,imgSobelY1,imgSobelX1Tmp,imgSobelY1Tmp,imgSobelX2,imgSobelY2,imgSobelXY; imgGray1.create(imgGray.rows-1,imgGray.cols-1,imgGray.type()); imgGray2.create(imgGray.rows-1,imgGray.cols-1,imgGray.type()); imgSobelX1.create(imgGray.rows-1,imgGray.cols-1,imgGray.type()); imgSobelY1.create(imgGray.rows-1,imgGray.cols-1,imgGray.type()); imgSobelX1Tmp.create(imgGray.rows-2,imgGray.cols-2,imgGray.type()); imgSobelY1Tmp.create(imgGray.rows-2,imgGray.cols-2,imgGray.type()); imgSobelX2.create(imgGray.rows-2,imgGray.cols-2,imgGray.type()); imgSobelY2.create(imgGray.rows-2,imgGray.cols-2,imgGray.type()); imgSobelXY.create(imgGray.rows-2,imgGray.cols-2,imgGray.type()); double xSin,yCos; for(int i=0;i<imgGray1.rows;i++) for(int j=0;j<imgGray1.cols;j++) { imgGray1.at<uchar>(i,j) = imgGray.at<uchar>(i+1,j)-imgGray.at<uchar>(i,j); imgGray2.at<uchar>(i,j) = imgGray.at<uchar>(i,j+1)-imgGray.at<uchar>(i,j); } //imshow("imgGray1",imgGray1); for(int i=0;i<imgGray1.rows;i++) for(int j=0;j<imgGray1.cols;j++) { xSin = sin(imgGray1.at<uchar>(i,j)); yCos = cos(imgGray1.at<uchar>(i,j)); if(xSin>0) { if(yCos>0) imgSobelX1.at<uchar>(i,j) = atan(abs(xSin/yCos)); else if(yCos<0) imgSobelX1.at<uchar>(i,j) = pi - atan(abs(xSin/yCos)); else imgSobelX1.at<uchar>(i,j) = pi/2; } else if(xSin<0) { if(yCos>0) imgSobelX1.at<uchar>(i,j) = 0-atan(abs(xSin/yCos)); else if(yCos<0) imgSobelX1.at<uchar>(i,j) = atan(abs(xSin/yCos)) - pi; else imgSobelX1.at<uchar>(i,j) = 0 - pi/2; } else if(yCos>0) imgSobelX1.at<uchar>(i,j) = 0; else if(yCos<0) imgSobelX1.at<uchar>(i,j) = pi/2; else imgSobelX1.at<uchar>(i,j) = 0; } //imshow("x",imgSobelX1); for(int i=0;i<imgGray2.rows;i++) for(int j=0;j<imgGray2.cols;j++) { xSin = sin(imgGray2.at<uchar>(i,j)); yCos = cos(imgGray2.at<uchar>(i,j)); if(xSin>0) { if(yCos>0) imgSobelY1.at<uchar>(i,j) = atan(abs(xSin/yCos)); else if(yCos<0) imgSobelY1.at<uchar>(i,j) = pi - atan(abs(xSin/yCos)); else imgSobelY1.at<uchar>(i,j) = pi/2; } else if(xSin<0) { if(yCos>0) imgSobelY1.at<uchar>(i,j) = 0-atan(abs(xSin/yCos)); else if(yCos<0) imgSobelY1.at<uchar>(i,j) = atan(abs(xSin/yCos)) - pi; else imgSobelY1.at<uchar>(i,j) = 0-pi/2; } else if(yCos>0) imgSobelY1.at<uchar>(i,j) = 0; else if(yCos<0) imgSobelY1.at<uchar>(i,j) = pi/2; else imgSobelY1.at<uchar>(i,j) = 0; } //imshow("y",imgSobelY1); ////////////////////////2次微分////////////////////////////// for(int i=0;i<imgSobelX1Tmp.rows;i++) for(int j=0;j<imgSobelX1Tmp.cols;j++) { imgSobelX1Tmp.at<uchar>(i,j) = imgSobelX1.at<uchar>(i+1,j)-imgSobelX1.at<uchar>(i,j); imgSobelY1Tmp.at<uchar>(i,j) = imgSobelY1.at<uchar>(i,j+1)-imgSobelY1.at<uchar>(i,j); } for(int i=0;i<imgSobelX1Tmp.rows;i++) for(int j=0;j<imgSobelX1Tmp.cols;j++) { xSin = sin(imgSobelX1Tmp.at<uchar>(i,j)); yCos = cos(imgSobelX1Tmp.at<uchar>(i,j)); if(xSin>0) { if(yCos>0) imgSobelX2.at<uchar>(i,j) = atan(abs(xSin/yCos)); else if(yCos<0) imgSobelX2.at<uchar>(i,j) = pi - atan(abs(xSin/yCos)); else imgSobelX2.at<uchar>(i,j) = pi/2; } else if(xSin<0) { if(yCos>0) imgSobelX2.at<uchar>(i,j) = -atan(abs(xSin/yCos)); else if(yCos<0) imgSobelX2.at<uchar>(i,j) = atan(abs(xSin/yCos)) - pi; else imgSobelX2.at<uchar>(i,j) = -pi/2; } else if(yCos>0) imgSobelX2.at<uchar>(i,j) = 0; else if(yCos<0) imgSobelX2.at<uchar>(i,j) = pi/2; else imgSobelX2.at<uchar>(i,j) = 0; } for(int i=0;i<imgSobelY1Tmp.rows;i++) for(int j=0;j<imgSobelY1Tmp.cols;j++) { xSin = sin(imgSobelY1Tmp.at<uchar>(i,j)); yCos = cos(imgSobelY1Tmp.at<uchar>(i,j)); if(xSin>0) { if(yCos>0) imgSobelY2.at<uchar>(i,j) = atan(abs(xSin/yCos)); else if(yCos<0) imgSobelY2.at<uchar>(i,j) = pi - atan(abs(xSin/yCos)); else imgSobelY2.at<uchar>(i,j) = pi/2; } else if(xSin<0) { if(yCos>0) imgSobelY2.at<uchar>(i,j) = 0-atan(abs(xSin/yCos)); else if(yCos<0) imgSobelY2.at<uchar>(i,j) = atan(abs(xSin/yCos)) - pi; else imgSobelY2.at<uchar>(i,j) = 0-pi/2; } else if(xSin>0) imgSobelY2.at<uchar>(i,j) = 0; else if(yCos<0) imgSobelY2.at<uchar>(i,j) = pi/2; else imgSobelY2.at<uchar>(i,j) = 0; } imgSobelXY = imgSobelX2 + imgSobelY2; //imshow("xy",imgSobelXY); Mat imgPhase,imgPhaseTmp,imgPhaseTmp1; imgSobelXY.convertTo(imgPhaseTmp,CV_64FC1); cv::dct(imgPhaseTmp,imgPhaseTmp1,CV_DXT_FORWARD); imgPhase.create(imgPhaseTmp.rows,imgPhaseTmp.cols,imgPhaseTmp.type()); //imshow("imgPhase",imgPhaseTmp1); for(int i=0;i<(imgPhaseTmp1.rows);i++) for(int j=0;j<(imgPhaseTmp1.cols);j++) { double k1 = 2*cos(i*pi/(imgPhaseTmp1.rows)); double k2 = 2*cos(j*pi/(imgPhaseTmp1.cols)); double k = k1 + k2 - 4; //k為負數 //qDebug()<<k; imgPhase.at<uchar>(i,j) = imgPhaseTmp1.at<uchar>(i,j) / k; //imgPhase.at<uchar>(i,j) = k; //qDebug()<<imgPhase.at<uchar>(i,j); } //imshow("imgPhase1",imgPhase); Mat imgPhaseDst; cv::dct(imgPhase,imgPhaseDst,CV_DXT_INVERSE); //imgPhaseDst為最後的結果圖
以下是Mat_型別的,此型別矩陣可以存在負數。
double pi = 3.141593; Mat img = imread("D:/Pic/4.jpg",1); Mat imgGray; cvtColor(img,imgGray,CV_BGR2GRAY); //imwrite("D:/5.jpg",imgGray); Mat imgGray1,imgGray2,imgSobelX1,imgSobelY1,imgSobelX1Tmp,imgSobelY1Tmp,imgSobelX2,imgSobelY2,imgSobelXY; imgGray1.create(imgGray.rows-1,imgGray.cols-1,imgGray.type()); imgGray2.create(imgGray.rows-1,imgGray.cols-1,imgGray.type()); imgSobelX1.create(imgGray.rows-1,imgGray.cols-1,imgGray.type()); imgSobelY1.create(imgGray.rows-1,imgGray.cols-1,imgGray.type()); imgSobelX1Tmp.create(imgGray.rows-2,imgGray.cols-2,imgGray.type()); imgSobelY1Tmp.create(imgGray.rows-2,imgGray.cols-2,imgGray.type()); imgSobelX2.create(imgGray.rows-2,imgGray.cols-2,imgGray.type()); imgSobelY2.create(imgGray.rows-2,imgGray.cols-2,imgGray.type()); imgSobelXY.create(imgGray.rows-2,imgGray.cols-2,imgGray.type()); double xSin,yCos; //Sobel(imgGray,imgSobelX1,CV_8U,1,0,7,1,0,BORDER_DEFAULT); for(int i=0;i<imgGray1.rows;i++) imgGray1.row(i) = imgGray.row(i+1)-imgGray.row(i); for(int i=0;i<imgGray1.rows;i++) for(int j=0;j<imgGray1.cols;j++) { xSin = sin(imgGray1.at<uchar>(i,j)); yCos = cos(imgGray1.at<uchar>(i,j)); if(xSin>0) { if(yCos>0) imgSobelX1.at<uchar>(i,j) = atan(abs(xSin/yCos)); else if(yCos<0) imgSobelX1.at<uchar>(i,j) = pi - atan(abs(xSin/yCos)); else imgSobelX1.at<uchar>(i,j) = pi/2; } else if(xSin<0) { if(yCos>0) imgSobelX1.at<uchar>(i,j) = 0-atan(abs(xSin/yCos)); else if(yCos<0) imgSobelX1.at<uchar>(i,j) = atan(abs(xSin/yCos)) - pi; else imgSobelX1.at<uchar>(i,j) = 0-pi/2; } else if(yCos>0) imgSobelX1.at<uchar>(i,j) = 0; else if(yCos<0) imgSobelX1.at<uchar>(i,j) = pi/2; else imgSobelX1.at<uchar>(i,j) = 0; } //Sobel(imgGray,imgSobelY1,CV_8U,0,1,7,1,0,BORDER_DEFAULT); for(int i=0;i<imgGray2.cols;i++) imgGray2.col(i) = imgGray.col(i+1)-imgGray.col(i); for(int i=0;i<imgGray2.rows;i++) for(int j=0;j<imgGray2.cols;j++) { xSin = sin(imgGray2.at<uchar>(i,j)); yCos = cos(imgGray2.at<uchar>(i,j)); if(xSin>0) { if(yCos>0) imgSobelY1.at<uchar>(i,j) = atan(abs(xSin/yCos)); else if(yCos<0) imgSobelY1.at<uchar>(i,j) = pi - atan(abs(xSin/yCos)); else imgSobelY1.at<uchar>(i,j) = pi/2; } else if(xSin<0) { if(yCos>0) imgSobelY1.at<uchar>(i,j) = 0-atan(abs(xSin/yCos)); else if(yCos<0) imgSobelY1.at<uchar>(i,j) = atan(abs(xSin/yCos)) - pi; else imgSobelY1.at<uchar>(i,j) = 0-pi/2; } else if(yCos>0) imgSobelY1.at<uchar>(i,j) = 0; else if(yCos<0) imgSobelY1.at<uchar>(i,j) = pi/2; else imgSobelY1.at<uchar>(i,j) = 0; } ////////////////////////2次微分////////////////////////////// //Sobel(imgSobelX1,imgSobelX2,CV_8U,1,0,7,1,0,BORDER_DEFAULT); for(int i=0;i<imgSobelX1Tmp.rows;i++) imgSobelX1Tmp.row(i) = imgSobelX1.row(i+1)-imgSobelX1.row(i); for(int i=0;i<imgSobelX1Tmp.rows;i++) for(int j=0;j<imgSobelX1Tmp.cols;j++) { xSin = sin(imgSobelX1Tmp.at<uchar>(i,j)); yCos = cos(imgSobelX1Tmp.at<uchar>(i,j)); if(xSin>0) { if(yCos>0) imgSobelX2.at<uchar>(i,j) = atan(abs(xSin/yCos)); else if(yCos<0) imgSobelX2.at<uchar>(i,j) = pi - atan(abs(xSin/yCos)); else imgSobelX2.at<uchar>(i,j) = pi/2; } else if(xSin<0) { if(yCos>0) imgSobelX2.at<uchar>(i,j) = -atan(abs(xSin/yCos)); else if(yCos<0) imgSobelX2.at<uchar>(i,j) = atan(abs(xSin/yCos)) - pi; else imgSobelX2.at<uchar>(i,j) = -pi/2; } else if(yCos>0) imgSobelX2.at<uchar>(i,j) = 0; else if(yCos<0) imgSobelX2.at<uchar>(i,j) = pi/2; else imgSobelX2.at<uchar>(i,j) = 0; } //Sobel(imgSobelY1,imgSobelY2,CV_8U,0,1,7,1,0,BORDER_DEFAULT); for(int i=0;i<imgSobelY1Tmp.cols;i++) imgSobelY1Tmp.col(i) = imgSobelY1.col(i+1)-imgSobelY1.col(i); for(int i=0;i<imgSobelY1Tmp.rows;i++) for(int j=0;j<imgSobelY1Tmp.cols;j++) { xSin = sin(imgSobelY1Tmp.at<uchar>(i,j)); yCos = cos(imgSobelY1Tmp.at<uchar>(i,j)); if(xSin>0) { if(yCos>0) imgSobelY2.at<uchar>(i,j) = atan(abs(xSin/yCos)); else if(yCos<0) imgSobelY2.at<uchar>(i,j) = pi - atan(abs(xSin/yCos)); else imgSobelY2.at<uchar>(i,j) = pi/2; } else if(xSin<0) { if(yCos>0) imgSobelY2.at<uchar>(i,j) = 0-atan(abs(xSin/yCos)); else if(yCos<0) imgSobelY2.at<uchar>(i,j) = atan(abs(xSin/yCos)) - pi; else imgSobelY2.at<uchar>(i,j) = 0-pi/2; } else if(xSin>0) imgSobelY2.at<uchar>(i,j) = 0; else if(yCos<0) imgSobelY2.at<uchar>(i,j) = pi/2; else imgSobelY2.at<uchar>(i,j) = 0; } imgSobelXY = imgSobelX2 + imgSobelY2; //namedWindow("x",1); //namedWindow("y",1); namedWindow("xy",1); //imshow("x",imgSobelX2); //imshow("y",imgSobelY2); imshow("xy",imgSobelXY); //for(int i=200;i<220;i++) //for(int j=200;j<220;j++) //qDebug()<<imgSobelXY.at<uchar>(i,j); Mat imgPhase,imgPhaseTmp; imgSobelXY.convertTo(imgPhaseTmp,CV_64FC1); cv::dct(imgPhaseTmp,imgPhase,CV_DXT_FORWARD); //namedWindow("phasePre",1); //imshow("phasePre",imgPhase); /*Mat imgPhase1; imgPhase1.create(imgPhase.size(),imgPhase.type()); for(int i=0;i<imgPhase.rows;i++) { const uchar* inData=imgPhase.ptr<uchar>(i); uchar* outData=imgPhase1.ptr<uchar>(i); for(int j=0;j<imgPhase.cols;j++) { double k1 = 2*cos((i-1)*pi/(imgPhase.rows)); double k2 = 2*cos((j-1)*pi/(imgPhase.cols)); double k = k1 + k2 - 4; outData[j]=inData[j]/k; } }*/ for(int i=1;i<(imgPhase.rows);i++) for(int j=1;j<(imgPhase.cols);j++) { double k1 = 2*cos((i-1)*pi/(imgPhase.rows)); double k2 = 2*cos((j-1)*pi/(imgPhase.cols)); double k = k1 + k2 - 4; //qDebug()<<k; //qDebug()<<k2; imgPhase.at<uchar>(i,j) /= k; //qDebug()<<imgPhase.at<uchar>(i,j); } //imgPhase.at<uchar>(1,1) = (imgPhase.at<uchar>(1,1)-imgPhase.at<uchar>(1,2)-imgPhase.at<uchar>(2,1))/2; //namedWindow("phasePre1",1); //imshow("phasePre1",imgPhase); Mat imgPhaseDst; cv::dct(imgPhase,imgPhaseDst,CV_DXT_INVERSE); namedWindow("phase",1); imshow("phase",imgPhaseDst);
----------------------------------------------------------分割線(2017.5.9)----------------------------------------------------------------
終於在opencv環境下實現了最小二乘去包裹演算法,貼上MATLAB(第一幅圖)與opencv(第二幅圖)的效果圖:
總結一下出現的問題及解決的方法:
imshow()函式,顯示矩陣中的負數時,會將負數置0顯示,也就是一個黑色畫素;
Mat矩陣運算時,如果出現負數,也會置0;
opencv離散餘弦正變換的第一個點顯示INF(無窮大),導致反變換矩陣都變成INF,用相鄰點的值代替INF,總的來說,MATLAB與opencv的DCT變換效果不太一樣。
處理opencv中的負數矩陣,利用Mat_型:
img = imread("D:/Pic/4.jpg",0); Mat_<int> img1 = img; opencv中好多自帶的函式的輸入矩陣需要double型,可直接用Mat_<double>型的矩陣作為輸入。 為了便於觀察,用qwtplot3d圖形庫對影象進行三維顯示:
程式碼如下(除錯註釋的程式碼沒有去掉):
void MainWindow::on_pushButton_4_clicked() { double pi = 3.141593; Mat img = imread("D:/Pic/4.jpg",0); Mat_<int> imgGray = img; Mat_<int> imgGray1,imgGray2,imgSobelX1,imgSobelY1,imgSobelX1Tmp,imgSobelY1Tmp,imgSobelX2,imgSobelY2,imgSobelXY; imgGray1.create(imgGray.rows-1,imgGray.cols-1); imgGray2.create(imgGray.rows-1,imgGray.cols-1); imgSobelX1.create(imgGray.rows-1,imgGray.cols-1); imgSobelY1.create(imgGray.rows-1,imgGray.cols-1); imgSobelX1Tmp.create(imgGray.rows-2,imgGray.cols-2); imgSobelY1Tmp.create(imgGray.rows-2,imgGray.cols-2); imgSobelX2.create(imgGray.rows-2,imgGray.cols-2); imgSobelY2.create(imgGray.rows-2,imgGray.cols-2); imgSobelXY.create(imgGray.rows-2,imgGray.cols-2); float xSin,yCos; for(int i=0;i<imgGray1.rows;i++) for(int j=0;j<imgGray1.cols;j++) { imgGray1.at<int>(i,j) = imgGray.at<int>(i+1,j)-imgGray.at<int>(i,j); imgGray2.at<int>(i,j) = imgGray.at<int>(i,j+1)-imgGray.at<int>(i,j); } //imshow("imgGray1",imgGray1); for(int i=0;i<imgGray1.rows;i++) for(int j=0;j<imgGray1.cols;j++) { xSin = sin(imgGray1.at<int>(i,j)); yCos = cos(imgGray1.at<int>(i,j)); if(xSin>0) { if(yCos>0) imgSobelX1.at<int>(i,j) = atan(abs(xSin/yCos)); else if(yCos<0) imgSobelX1.at<int>(i,j) = pi - atan(abs(xSin/yCos)); else imgSobelX1.at<int>(i,j) = pi/2; } else if(xSin<0) { if(yCos>0) imgSobelX1.at<int>(i,j) = 0-atan(abs(xSin/yCos)); else if(yCos<0) imgSobelX1.at<int>(i,j) = atan(abs(xSin/yCos)) - pi; else imgSobelX1.at<int>(i,j) = 0 - pi/2; } else if(yCos>0) imgSobelX1.at<int>(i,j) = 0; else if(yCos<0) imgSobelX1.at<int>(i,j) = pi/2; else imgSobelX1.at<int>(i,j) = 0; } //imshow("x",imgSobelX1); for(int i=0;i<imgGray2.rows;i++) for(int j=0;j<imgGray2.cols;j++) { xSin = sin(imgGray2.at<int>(i,j)); yCos = cos(imgGray2.at<int>(i,j)); if(xSin>0) { if(yCos>0) imgSobelY1.at<int>(i,j) = atan(abs(xSin/yCos)); else if(yCos<0) imgSobelY1.at<int>(i,j) = pi - atan(abs(xSin/yCos)); else imgSobelY1.at<int>(i,j) = pi/2; } else if(xSin<0) { if(yCos>0) imgSobelY1.at<int>(i,j) = 0-atan(abs(xSin/yCos)); else if(yCos<0) imgSobelY1.at<int>(i,j) = atan(abs(xSin/yCos)) - pi; else imgSobelY1.at<int>(i,j) = 0-pi/2; } else if(yCos>0) imgSobelY1.at<int>(i,j) = 0; else if(yCos<0) imgSobelY1.at<int>(i,j) = pi/2; else imgSobelY1.at<int>(i,j) = 0; } //imshow("y",imgSobelY1); ////////////////////////2次微分////////////////////////////// for(int i=0;i<imgSobelX1Tmp.rows;i++) for(int j=0;j<imgSobelX1Tmp.cols;j++) { imgSobelX1Tmp.at<int>(i,j) = imgSobelX1.at<int>(i+1,j)-imgSobelX1.at<int>(i,j); imgSobelY1Tmp.at<int>(i,j) = imgSobelY1.at<int>(i,j+1)-imgSobelY1.at<int>(i,j); } for(int i=0;i<imgSobelX1Tmp.rows;i++) for(int j=0;j<imgSobelX1Tmp.cols;j++) { xSin = sin(imgSobelX1Tmp.at<int>(i,j)); yCos = cos(imgSobelX1Tmp.at<int>(i,j)); if(xSin>0) { if(yCos>0) imgSobelX2.at<int>(i,j) = atan(abs(xSin/yCos)); else if(yCos<0) imgSobelX2.at<int>(i,j) = pi - atan(abs(xSin/yCos)); else imgSobelX2.at<int>(i,j) = pi/2; } else if(xSin<0) { if(yCos>0) imgSobelX2.at<int>(i,j) = -atan(abs(xSin/yCos)); else if(yCos<0) imgSobelX2.at<int>(i,j) = atan(abs(xSin/yCos)) - pi; else imgSobelX2.at<int>(i,j) = -pi/2; } else if(yCos>0) imgSobelX2.at<int>(i,j) = 0; else if(yCos<0) imgSobelX2.at<int>(i,j) = pi/2; else imgSobelX2.at<int>(i,j) = 0; } for(int i=0;i<imgSobelY1Tmp.rows;i++) for(int j=0;j<imgSobelY1Tmp.cols;j++) { xSin = sin(imgSobelY1Tmp.at<int>(i,j)); yCos = cos(imgSobelY1Tmp.at<int>(i,j)); if(xSin>0) { if(yCos>0) imgSobelY2.at<int>(i,j) = atan(abs(xSin/yCos)); else if(yCos<0) imgSobelY2.at<int>(i,j) = pi - atan(abs(xSin/yCos)); else imgSobelY2.at<int>(i,j) = pi/2; } else if(xSin<0) { if(yCos>0) imgSobelY2.at<int>(i,j) = 0-atan(abs(xSin/yCos)); else if(yCos<0) imgSobelY2.at<int>(i,j) = atan(abs(xSin/yCos)) - pi; else imgSobelY2.at<int>(i,j) = 0-pi/2; } else if(xSin>0) imgSobelY2.at<int>(i,j) = 0; else if(yCos<0) imgSobelY2.at<int>(i,j) = pi/2; else imgSobelY2.at<int>(i,j) = 0; } imgSobelXY = imgSobelX2 + imgSobelY2; //imshow("xy",imgSobelXY); /*for(int i=0;i<imgSobelXY.rows;i++) for(int j=0;j<imgSobelXY.cols;j++) { qDebug()<<imgSobelXY.at<double>(i,j); }*/ Mat_<double> imgSobelXYD(imgSobelXY.rows,imgSobelXY.cols,CV_64FC1); imgSobelXY.convertTo(imgSobelXYD,CV_64FC1); Mat_<double> imgPhase,imgPhaseTmp; //imgSobelXY.convertTo(imgPhaseTmp,CV_64FC1); cv::dct(imgSobelXYD,imgPhaseTmp,CV_DXT_FORWARD); imgPhase.create(imgPhaseTmp.rows,imgPhaseTmp.cols); //imshow("imgPhase",imgPhaseTmp); for(int i=0;i<(imgPhaseTmp.rows);i++) for(int j=0;j<(imgPhaseTmp.cols);j++) { double k1 = 2*cos(i*pi/(imgPhaseTmp.rows)); double k2 = 2*cos(j*pi/(imgPhaseTmp.cols)); double k = k1 + k2 - 4; //k為負數 //qDebug()<<k; imgPhase.at<double>(i,j) = imgPhaseTmp.at<double>(i,j) / k; if(imgPhase.at<double>(i,j) > 100000.0 ) imgPhase.at<double>(i,j) = imgPhase.at<double>(i,j-1); //imgPhase.at<uchar>(i,j) = k; //qDebug()<<imgPhase.at<uchar>(i,j); } //imshow("imgPhase",imgPhase); //imgPhase.at<double>(0,0)=imgPhase.at<double>(0,1); //for(int i=0;i<imgPhase.rows;i++) // for(int j=0;j<imgPhase.cols;j++) // qDebug()<<imgPhase.at<double>(i,j); Mat_<double> imgPhaseDst; cv::dct(imgPhase,imgPhaseDst,CV_DXT_INVERSE); //imshow("img",imgPhaseDst); //for(int i=0;i<imgPhaseDst.rows;i++) //for(int j=0;j<imgPhaseDst.cols;j++) //qDebug()<<imgPhaseDst.at<double>(i,j); //////////////////////////////3D////////////////////////////////// //Mat imgx(imgPhaseDst.rows, imgPhaseDst.cols, CV_64FC1); //imgPhaseDst.convertTo(imgx, CV_64FC1); //imgx為要顯示的double矩陣 Mat_<double> imgx = imgPhaseDst; Plot* plot = new Plot(imgx); QGridLayout *grid = new QGridLayout(ui->frame); grid->addWidget(plot,0,0); plot->setTitle("3D"); plot->coordinates()->axes[X1].setLabelString("X(um)"); //只能寫在這 plot->coordinates()->axes[Y1].setLabelString("Y(um)"); //設定座標軸標籤 plot->coordinates()->axes[Z1].setLabelString("Z(nm)"); plot->coordinates()->axes[Z2].setLabelString("Z(nm)"); plot->coordinates()->axes[Z3].setLabelString("Z(nm)"); plot->coordinates()->axes[Z4].setLabelString("Z(nm)"); double start,stop; //設定顏色條 plot->coordinates()->axes[Z1].limits(start,stop); plot->legend()->setLimits(start,stop); // plot->legend()->setAutoScale(true); // plot->resize(600,600); plot->show(); grid->~QGridLayout(); }