目的:利用sse求取圖像的垂直和水平梯度圖,加快求梯度圖的運算速度
代碼實現:
#include "stdio.h"
#include "opencv2\\opencv.hpp"
#include "sse.h"
using namespace std;
using namespace cv;
int main()
{
//[1] 讀取圖像,並把圖像轉化成灰度圖
Mat img = imread("003.jpg");
if (NULL == img.data)
{
printf("read img error!\n");
getchar();
}
Mat imgGray;
cvtColor(img, imgGray,CV_BGR2GRAY);
namedWindow("灰度圖", 0);
imshow("灰度圖", imgGray);
waitKey(0);
// [2] 將圖像數據轉化成浮點型數據
int nHeight = imgGray.rows;
int nWidth = imgGray.cols;
int nWidthDst = 0;
float* pData = (float*)_aligned_malloc(nWidth* nHeight * sizeof(float), 16);
memset(pData, 0, nWidth* nHeight* sizeof(float));
for (int i = 0; i < nHeight; i++)
{
for (int j = 0; j < nWidth; j++)
{
pData[i*nWidth + j] = (float)imgGray.data[i*nWidth + j];
}
}
// [3] 求取水平梯度圖Gx
float* pGxData = (float*)_aligned_malloc(nWidth* nHeight * sizeof(float), 16);
memset(pGxData, 0, nWidth* nHeight * sizeof(float));
float *Up, *Down, *Dx;
__m128 *_Dx;
int LOOP = nWidth/4;
for (int i = 1; i < nHeight - 2;i++)
{
Dx = &pGxData[i*nWidth];
_Dx = (__m128*)Dx;
for (int j = 0; j < LOOP; j++)
{
Up = &pData[(i - 1)*nWidth + j * 4];
Down = &pData[(i +1)*nWidth + j * 4];
*_Dx = SSE_SUB(SSE_LDu(Down), SSE_LDu(Up));
_Dx++;
}
}
// [4] 顯示水平梯度圖
char* tempData = (char*)malloc(nWidth* nHeight * sizeof(char));
memset(tempData, 0, nWidth* nHeight* sizeof(char));
for (int i = 0; i < nHeight; i++)
{
for (int j = 0; j < nWidth; j++)
{
tempData[i*nWidth + j] = (char)fabs(pGxData[i*nWidth + j]);
}
}
IplImage GxImg;
memset(&GxImg, 0, sizeof(IplImage));
GxImg.nSize = sizeof(IplImage);
GxImg.nChannels = 1;
GxImg.height = nHeight;
GxImg.width = nWidth;
GxImg.widthStep = nWidth;
GxImg.imageData = (char*)tempData;
cvNamedWindow("水平梯度圖", 0);
cvShowImage("水平梯度圖",&GxImg);
cvWaitKey(0);
// [5] 求取垂直梯度圖Gy(特別之處需要將圖像進行翻轉)
memset(pData, 0, nWidth* nHeight* sizeof(float));
for (int i = 0; i < nWidth; i++)
{
for (int j = 0; j < nHeight; j++)
{
pData[i*nHeight + j] = (float)imgGray.data[j*nWidth + i];
}
}
float* pGyData = (float*)_aligned_malloc(nWidth* nHeight * sizeof(float), 16);
memset(pGyData, 0, nWidth* nHeight * sizeof(float));
LOOP = nHeight / 4;
for (int i = 1; i < nWidth -1; i++)
{
Dx = &pGyData[i*nHeight];
_Dx = (__m128*)Dx;
for (int j = 0; j < LOOP; j++)
{
Up = &pData[(i - 1)*nHeight + j * 4];
Down = &pData[(i + 1)*nHeight + j * 4];
*_Dx = SSE_SUB(SSE_LDu(Down), SSE_LDu(Up));
_Dx++;
}
}
// [6] 顯示水平梯度圖
memset(tempData, 0, nWidth* nHeight* sizeof(char));
for (int i = 0; i < nHeight; i++)
{
for (int j = 0; j < nWidth; j++)
{
tempData[i*nWidth + j] = (char)fabs(pGyData[j*nHeight + i]);
}
}
IplImage GyImg;
memset(&GyImg, 0, sizeof(IplImage));
GyImg.nSize = sizeof(IplImage);
GyImg.nChannels = 1;
GyImg.height = nHeight;
GyImg.width = nWidth;
GyImg.widthStep = nWidth;
GyImg.imageData = (char*)tempData;
cvNamedWindow("垂直梯度圖", 0);
cvShowImage("垂直梯度圖", &GxImg);
cvWaitKey(0);
return 0;
}
結果:
參考資料:
http://blog.csdn.net/j56754gefge/article/details/46755565 (ssh.h見於該鏈接)
http://blog.csdn.net/chenchong_219/article/details/44683155