主要内容

利用PARFOR加速图像对比度增强算法

这个例子展示了如何从MATLAB代码中生成一个独立的C库,它将一个简单的直方图均衡函数应用于图像以提高图像对比度。本例使用parfor在单独的线程上处理每个标准的三个RGB图像平面。该示例还展示了如何在生成C代码之前在MATLAB中生成和运行MEX函数,以验证MATLAB代码适合代码生成。

MATLAB Coder使用OpenMP可移植共享内存并行编程标准来实现对其的支持金宝appparfor.看到并行编程的OpenMP API规范.而MATLAB支持金宝appparfor通过创建多个工作会话,MATLAB Coder使用OpenMP创建运行在同一台机器上的多个线程。

先决条件

为了支持并行化,编译器必金宝app须支持OpenMP共享内存并行编程标准。如果您的编译器没有这种支持,那么您仍然可以运行这个示例,但是生成的代码将金宝app连续运行。

关于histequalize函数

histequalize.m函数接受一幅图像(表示为NxMx3矩阵),并返回一幅对比度增强的图像。

类型histequalize
函数equalizedImage = histequalize(originalImage) %#codegen % equalizedImage = histequalize(originalImage) %直方图均衡化(或线性化)以提高图像对比度。%给定一幅NxMx3图像,将图像中三个平面的直方图进行均衡化,以提高图像对比度。断言(大小(originalImage之下,1)< = 8192);断言(大小(originalImage之下,2)< = 8192);断言(大小(originalImage之下,3)= = 3);断言(isa (originalImage之下,' uint8 '));[L, originalHist] = computeHistogram(originalImage);equalizedImage = equalize(L, originalHist, originalImage);end function [L, originalHist] = computeHistogram(originalImage) L = double(max(max(max(originalImage)))) + 1;originalHist = coder.nullcopy(0(3升)); sz = size(originalImage); N = sz(1); M = sz(2); parfor plane = 1:sz(3) planeHist = zeros(1,L); for y = 1:N for x = 1:M r = originalImage(y,x,plane); planeHist(r+1) = planeHist(r+1) + 1; end end originalHist(plane,:) = planeHist; end end function equalizedImage = equalize(L, originalHist, originalImage) equalizedImage = coder.nullcopy(originalImage); sz = size(originalImage); N = sz(1); M = sz(2); normalizer = (L - 1)/(N*M); parfor plane = 1:sz(3) planeHist = originalHist(plane,:); for y = 1:N for x = 1:M r = originalImage(y,x,plane); s = 0; for j = 0:int32(r) s = s + planeHist(j+1); end s = normalizer * s; equalizedImage(y,x,plane) = s; end end end end

生成MEX函数

方法生成一个MEX函数codegen命令。

codegenhistequalize

在生成C代码之前,您应该首先在MATLAB中测试MEX函数,以确保它在功能上与原始MATLAB代码等价,并且不会发生运行时错误。默认情况下,codegen生成一个名为histequalize_mex在当前文件夹中。这允许您测试MATLAB代码和MEX函数,并比较结果。

阅读原始图像

使用标准的imread命令读取低对比度图像。

lcIm = imread (“LowContrast.jpg”);图像(lcIm);

运行MEX函数(直方图均衡算法)

通过低对比度图像。

hcIm = histequalize_mex (lcIm);

显示结果

图像(hcIm);

生成独立的C代码

codegen配置:自由histequalize

使用codegen配置:自由选项生成一个独立的C库。默认情况下,为库生成的代码在文件夹中codegen / lib / histequalize /

检查生成的函数

请注意,生成的代码包含使用多个线程控制代码并行化的OpenMP实用程序。

类型codegen / lib / histequalize / histequalize.c
/ * *文件:histequalize.c * * matlab编码器版本:5.1 * c / c ++源代码:24-us-2020 19:22:02 * // *包括文件* / #include“histequalize.h”#包括“histequalize_data.h”#include“histequalize_emxutil.h”#include“histequalize_initialize.h”#include“histequalize_types.h”#include  #include  / *函数声明* /静态void computehistogram(const emxarray_uint8_t *原始图像,双* l,double原稿hist_data [],int notionalhist_size [2]);静态void均衡(双L,const double原稿hist_data [],const emxarray_uint8_t *原始图像,emxarray_uint8_t * companyizedimage);静态双RT_ROUNDD_SNF(双U);/ *函数定义* / / * *参数:const emxarray_uint8_t *原始图像* double * l * double原稿hist_data [] * int notionhist_size [2] *返回类型:void * /静态void computehistograph(const emxarray_uint8_t * worlialImage,double * l,Double OriginalHist_data [],int notionalhist_size [2]){double planehist_data [256];int b_i;INT I;int loop_ub;int maxval_size_idx_1; int npages; int p; int plane; int vlen; int x; int xOffset; int xPageOffset; int y; short planeHist_size[2]; unsigned char maxval_data[24576]; unsigned char b_maxval[3]; unsigned char maxval; unsigned char r; maxval_size_idx_1 = originalImage->size[1]; if (originalImage->size[1] == 0) { maxval_size_idx_1 = originalImage->size[1]; vlen = originalImage->size[1] * 3; if (0 <= vlen - 1) { memset(&maxval_data[0], 0, vlen * sizeof(unsigned char)); } } else { vlen = originalImage->size[0]; npages = originalImage->size[1] * originalImage->size[2]; for (p = 0; p < npages; p++) { xPageOffset = p * vlen; maxval_data[p] = originalImage->data[xPageOffset]; for (i = 2; i <= vlen; i++) { xOffset = (xPageOffset + i) - 1; if (maxval_data[p] < originalImage->data[xOffset]) { maxval_data[p] = originalImage->data[xOffset]; } } } } for (p = 0; p < 3; p++) { xPageOffset = p * maxval_size_idx_1; b_maxval[p] = maxval_data[xPageOffset]; for (i = 2; i <= maxval_size_idx_1; i++) { xOffset = (xPageOffset + i) - 1; if (b_maxval[p] < maxval_data[xOffset]) { b_maxval[p] = maxval_data[xOffset]; } } } maxval = b_maxval[0]; if (b_maxval[0] < b_maxval[1]) { maxval = b_maxval[1]; } if (maxval < b_maxval[2]) { maxval = b_maxval[2]; } *L = (double)maxval + 1.0; originalHist_size[0] = 3; originalHist_size[1] = maxval + 1; vlen = originalImage->size[0]; npages = originalImage->size[1]; #pragma omp parallel for \ num_threads(omp_get_max_threads()) \ private(r,planeHist_data,planeHist_size,loop_ub,y,x,b_i) for (plane = 0; plane < 3; plane++) { planeHist_size[1] = (short)*L; loop_ub = (int)*L; if (0 <= loop_ub - 1) { memset(&planeHist_data[0], 0, loop_ub * sizeof(double)); } for (y = 0; y < vlen; y++) { for (x = 0; x < npages; x++) { r = originalImage->data[(y + originalImage->size[0] * x) + originalImage->size[0] * originalImage->size[1] * plane]; b_i = (int)(r + 1U); if (r + 1U > 255U) { b_i = 255; } loop_ub = (int)(r + 1U); if (r + 1U > 255U) { loop_ub = 255; } planeHist_data[(unsigned char)b_i - 1] = planeHist_data[(unsigned char) loop_ub - 1] + 1.0; } } loop_ub = planeHist_size[1]; for (b_i = 0; b_i < loop_ub; b_i++) { originalHist_data[plane + 3 * b_i] = planeHist_data[b_i]; } } } /* * Arguments : double L * const double originalHist_data[] * const emxArray_uint8_T *originalImage * emxArray_uint8_T *equalizedImage * Return Type : void */ static void equalize(double L, const double originalHist_data[], const emxArray_uint8_T *originalImage, emxArray_uint8_T *equalizedImage) { double normalizer; double s; int M; int N; int i; int j; int plane; int x; int y; unsigned char r; N = equalizedImage->size[0] * equalizedImage->size[1] * equalizedImage->size[2]; equalizedImage->size[0] = originalImage->size[0]; equalizedImage->size[1] = originalImage->size[1]; equalizedImage->size[2] = originalImage->size[2]; emxEnsureCapacity_uint8_T(equalizedImage, N); N = originalImage->size[0]; M = originalImage->size[1]; normalizer = (L - 1.0) / ((double)(unsigned int)originalImage->size[0] * (double)(unsigned int)originalImage->size[1]); #pragma omp parallel for \ num_threads(omp_get_max_threads()) \ private(s,r,y,x,i,j) for (plane = 0; plane < 3; plane++) { for (y = 0; y < N; y++) { for (x = 0; x < M; x++) { r = originalImage->data[(y + originalImage->size[0] * x) + originalImage->size[0] * originalImage->size[1] * plane]; s = 0.0; i = r; for (j = 0; j <= i; j++) { s += originalHist_data[plane + 3 * j]; } s *= normalizer; s = rt_roundd_snf(s); if (s < 256.0) { if (s >= 0.0) { r = (unsigned char)s; } else { r = 0U; } } else if (s >= 256.0) { r = MAX_uint8_T; } else { r = 0U; } equalizedImage->data[(y + equalizedImage->size[0] * x) + equalizedImage->size[0] * equalizedImage->size[1] * plane] = r; } } } } /* * Arguments : double u * Return Type : double */ static double rt_roundd_snf(double u) { double y; if (fabs(u) < 4.503599627370496E+15) { if (u >= 0.5) { y = floor(u + 0.5); } else if (u > -0.5) { y = u * 0.0; } else { y = ceil(u - 0.5); } } else { y = u; } return y; } /* * equalizedImage = histequalize(originalImage) * Histogram equalization (or linearization) for improving image contrast. * Given an NxMx3 image, equalizes the histogram of each of the three image * planes in order to improve image contrast. * Arguments : const emxArray_uint8_T *originalImage * emxArray_uint8_T *equalizedImage * Return Type : void */ void histequalize(const emxArray_uint8_T *originalImage, emxArray_uint8_T *equalizedImage) { double originalHist_data[768]; double L; int originalHist_size[2]; if (!isInitialized_histequalize) { histequalize_initialize(); } computeHistogram(originalImage, &L, originalHist_data, originalHist_size); equalize(L, originalHist_data, originalImage, equalizedImage); } /* * File trailer for histequalize.c * * [EOF] */