29 #include <opencv2/core/version.hpp>
30 #include <opencv2/imgproc/imgproc.hpp>
31 #if CV_MAJOR_VERSION >= 3
32 # include <opencv2/imgcodecs.hpp>
34 # include <opencv2/highgui/highgui.hpp>
49 #define CHECK_STATUS(STMT) \
52 VPIStatus status = (STMT); \
53 if (status != VPI_SUCCESS) \
55 char buffer[VPI_MAX_STATUS_MESSAGE_LENGTH]; \
56 vpiGetLastStatusMessage(buffer, sizeof(buffer)); \
57 std::ostringstream ss; \
58 ss << vpiStatusGetName(status) << ": " << buffer; \
59 throw std::runtime_error(ss.str()); \
64 cv::Mat LogMagnitude(cv::Mat cpx);
65 cv::Mat CompleteFullHermitian(cv::Mat in, cv::Size fullSize);
66 cv::Mat InplaceFFTShift(cv::Mat mag);
68 int main(
int argc,
char *argv[])
90 throw std::runtime_error(std::string(
"Usage: ") + argv[0] +
" <cpu|cuda> <input image>");
93 std::string strBackend = argv[1];
94 std::string strInputFileName = argv[2];
99 if (strBackend ==
"cpu")
103 else if (strBackend ==
"cuda")
109 throw std::runtime_error(
"Backend '" + strBackend +
"' not recognized, it must be either cpu or cuda.");
115 cvImage = cv::imread(strInputFileName);
118 throw std::runtime_error(
"Can't open '" + strInputFileName +
"'");
151 CHECK_STATUS(
vpiSubmitFFT(stream, backend, fft, imageF32, spectrum, 0));
173 cv::Mat mag = InplaceFFTShift(LogMagnitude(CompleteFullHermitian(cvSpectrum, cvImage.size())));
176 normalize(mag, mag, 0, 255, cv::NORM_MINMAX);
179 imwrite(
"spectrum_" + strBackend +
".png", mag);
184 catch (std::exception &e)
186 std::cerr << e.what() << std::endl;
213 cv::Mat LogMagnitude(cv::Mat cpx)
217 assert(cpx.channels() == 2);
222 magnitude(reim[0], reim[1], mag);
225 mag += cv::Scalar::all(1);
227 mag = mag(cv::Rect(0, 0, mag.cols & -2, mag.rows & -2));
232 cv::Mat CompleteFullHermitian(cv::Mat in, cv::Size fullSize)
234 assert(in.type() == CV_32FC2);
236 cv::Mat out(fullSize, CV_32FC2);
237 for (
int i = 0; i < out.rows; ++i)
239 for (
int j = 0; j < out.cols; ++j)
244 p = in.at<cv::Vec2f>(i, j);
248 p = in.at<cv::Vec2f>((out.rows - i) % out.rows, (out.cols - j) % out.cols);
251 out.at<cv::Vec2f>(i, j) = p;
258 cv::Mat InplaceFFTShift(cv::Mat mag)
264 int cx = mag.cols / 2;
265 int cy = mag.rows / 2;
266 cv::Mat qTL(mag, cv::Rect(0, 0, cx, cy));
267 cv::Mat qTR(mag, cv::Rect(cx, 0, cx, cy));
268 cv::Mat qBL(mag, cv::Rect(0, cy, cx, cy));
269 cv::Mat qBR(mag, cv::Rect(cx, cy, cx, cy));
用于处理 OpenCV 与 VPI 的互操作性的函数。
VPIStatus vpiCreateFFT(uint64_t backends, int32_t inputWidth, int32_t inputHeight, const VPIImageFormat inFormat, const VPIImageFormat outFormat, VPIPayload *payload)
为直接快速傅里叶变换算法创建负载。
VPIStatus vpiSubmitFFT(VPIStream stream, uint64_t backend, VPIPayload payload, VPIImage input, VPIImage output, uint64_t flags)
对单张图像运行直接快速傅里叶变换。
VPIImageBuffer buffer
存储图像内容。
VPIImagePlanePitchLinear planes[VPI_MAX_PLANE_COUNT]
以 pitch-linear 布局存储的所有图像平面的数据。
VPIImageBufferPitchLinear pitch
以 pitch-linear 布局存储的图像。
VPIImageFormat format
图像格式。
VPIImageBufferType bufferType
图像缓冲区类型。
int32_t height
此平面的高度(像素)。
int32_t pitchBytes
一行开头与前一行开头之间的字节差。
void vpiImageDestroy(VPIImage img)
销毁一个图像实例。
struct VPIImageImpl * VPIImage
图像的句柄。
VPIStatus vpiImageLockData(VPIImage img, VPILockMode mode, VPIImageBufferType bufType, VPIImageData *data)
获取图像对象的锁并返回图像内容。
VPIStatus vpiImageCreate(int32_t width, int32_t height, VPIImageFormat fmt, uint64_t flags, VPIImage *img)
使用指定的标志创建一个空的图像实例。
VPIStatus vpiImageUnlock(VPIImage img)
释放图像对象的锁。
@ VPI_IMAGE_BUFFER_HOST_PITCH_LINEAR
主机可访问,平面以 pitch-linear 内存布局排列。
VPIStatus vpiImageCreateWrapperOpenCVMat(const cv::Mat &mat, VPIImageFormat fmt, uint64_t flags, VPIImage *img)
使用给定的图像格式将 cv::Mat 封装到 VPIImage 中。
struct VPIPayloadImpl * VPIPayload
算法负载的句柄。
struct VPIStreamImpl * VPIStream
流的句柄。
VPIStatus vpiStreamSync(VPIStream stream)
阻塞调用线程,直到此流队列中所有提交的命令都完成(队列为空)...
void vpiStreamDestroy(VPIStream stream)
销毁一个流实例并释放所有硬件资源。
VPIStatus vpiStreamCreate(uint64_t flags, VPIStream *stream)
创建一个流实例。
@ VPI_BACKEND_CUDA
CUDA 后端。
@ VPI_LOCK_READ
锁定内存仅用于读取。