利用SSE求取水平與垂直梯度圖(筆記)

目的:利用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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章