В этом примере показано, как создать исполняемый файл C из MATLAB® код, который реализует простой фильтр Собеля для выполнения обнаружения ребра на изображениях. Исполняемый файл считывает изображение с диска, применяет алгоритм фильтрации Собеля, а затем сохраняет изменённое изображение.
Пример показывает, как сгенерировать и изменить пример основной функции, которую можно использовать при сборке исполняемого файла.
Чтобы завершить этот пример, установите следующие продукты:
MATLAB
MATLAB Coder™
Компилятор C (для большинства платформ компилятор C по умолчанию поставляется с MATLAB). Список поддерживаемых компиляторов см. в разделе Поддерживаемые компиляторы.
Можно использовать mex -setup
для изменения компилятора по умолчанию. См. Раздел «Изменение компилятора по умолчанию».
Файлы, которые вы используете в этом примере:
Имя файла | Тип файла | Описание |
---|---|---|
sobel.m | Код функции | Реализация MATLAB алгоритма фильтрации Собеля. sobel.m принимает изображение (представленное как двойная матрица) и пороговое значение в качестве входов. Алгоритм обнаруживает ребра в изображении (на основе порогового значения). sobel.m возвращает измененное изображение, отображающее ребра. |
hello.jpg | Файл изображений | Изображение, которое изменяет фильтр Собеля. |
Чтобы скопировать файлы примера в локальную рабочую папку:
Создайте локальную рабочую папку. Для примера, c:\coder\edge_detection
.
Перейдите к рабочей папке.
Скопируйте файлы sobel.m
и hello.jpg
из папки примеров sobel
в рабочую папку.
copyfile(fullfile(docroot, 'toolbox', 'coder', 'examples', 'sobel'))
Прочтите оригинальное изображение в матрицу MATLAB и отобразите его.
im = imread('hello.jpg');
Отображение изображения как базисы для сравнения с результатом фильтра Собеля.
image(im);
Алгоритм фильтрации Собеля работает с полутоновыми изображениями. Преобразуйте цветное изображение в эквивалентное полутоновое с нормированными значениями (0,0 для черного, 1,0 для белого).
gray = (0.2989 * double(im(:,:,1)) + 0.5870 * double(im(:,:,2)) + 0.1140 * double(im(:,:,3)))/255;
Чтобы запустить функцию MATLAB для фильтра Собеля, передайте матрицу полутонового изображения gray
и порог значение функции sobel
. Этот пример использует 0,7 для порогового значения.
edgeIm = sobel(gray, 0.7);
Чтобы отобразить измененное изображение, переформатируйте матрицу edgeIm
с функцией repmat
чтобы можно было передать его в image
команда.
im3 = repmat(edgeIm, [1 1 3]); image(im3);
Чтобы проверить, что сгенерированный код функционально эквивалентен оригинальному коду MATLAB и что ошибки времени выполнения не происходят, сгенерируйте MEX-функцию.
codegen -report sobel
codegen
генерирует MEX-функцию с именем sobel_mex
в текущей рабочей папке.
Чтобы запустить MEX-функцию для фильтра Собеля, передайте матрицу полутонового изображения gray
и порог значение функции sobel_mex
. Этот пример использует 0,7 для порогового значения.
edgeImMex = sobel_mex(gray, 0.7);
Чтобы отобразить измененное изображение, переформатируйте матрицу edgeImMex
с функцией repmat
чтобы можно было передать его в image
команда.
im3Mex = repmat(edgeImMex, [1 1 3]); image(im3Mex);
Это изображение совпадает с изображением, созданным с помощью функции MATLAB.
Несмотря на то, что вы можете написать пользовательскую основную функцию для вашего приложения, пример основной функции предоставляет шаблон, который поможет вам включить сгенерированный код.
Чтобы сгенерировать пример основной функции для фильтра Собеля:
Создайте объект строения для статической библиотеки C.
cfg = coder.config('lib');
Для объектов строения исходного кода C/C + +, статических библиотек, динамических библиотек и исполняемых файлов, настройка GenerateExampleMain
управляет генерацией примера основной функции. Для настройки задано значение 'GenerateCodeOnly'
по умолчанию, который генерирует пример основной функции, но не компилирует ее. В данном примере не изменяйте значение GenerateExampleMain
настройка.
Сгенерируйте статическую библиотеку C с помощью объекта строения.
codegen -report -config cfg sobel
Сгенерированные файлы для статической библиотеки находятся в папке codegen/lib/sobel
. Примеры основных файлов находятся в подпапке codegen/lib/sobel/examples
.
Не изменяйте файлы main.c
и main.h
в examples
подпапка. Если это так, при регенерации кода MATLAB Coder не регенерирует основные файлы примера. Он предупреждает вас, что обнаруживает изменения в сгенерированных файлах.
Скопируйте файлы main.c
и main.h
из папки codegen/lib/sobel/examples
в другое место. В данном примере скопируйте файлы в текущую рабочую папку. Измените файлы в новом расположении.
Пример основной функции объявляет и инициализирует данные, включая динамически выделенные данные, к нулевым значениям. Он вызывает функции точки входа с аргументами, установленными на нули значений, но не использует значения, возвращенные из функций точки входа.
Основная функция C должна соответствовать требованиям вашего приложения. Этот пример изменяет пример основной функции, чтобы удовлетворить требования приложения фильтра Собеля.
Этот пример изменяет файл main.c
так что приложение фильтра Собеля:
Считывает в полутоновом изображении из двоичного файла.
Применяет алгоритм фильтрации Собеля.
Сохранение измененного изображения в двоичном файле.
Измените функцию main
кому:
Примите файл, содержащий данные полутонового изображения и пороговое значение, в качестве входных параметров.
Вызовите функцию main_sobel
с адресом потока данных полутонового изображения и пороговым значением в качестве входных параметров.
В функциональном main
:
Удалите объявления void(argc)
и (void)argv
.
Объявите переменную filename
для хранения имени двоичного файла, содержащего данные полутонового изображения.
const char *filename;
Объявите переменную threshold
для удержания порога значения.
double threshold;
Объявите переменную fd
для хранения адреса данных полутонового изображения, которые считывает приложение filename
.
FILE *fd;
Добавление if
оператор, который проверяет наличие трех аргументов.
if (argc != 3) { printf("Expected 2 arguments: filename and threshold\n"); exit(-1); }
Назначьте входной параметр argv[1]
для файла, содержащего данные о полутоновом изображении, в filename
.
filename = argv[1];
Назначьте входной параметр argv[2]
для порогового значения, которое должно быть threshold
, преобразование входов из строки в число двойной точности.
threshold = atof(argv[2]);
Откройте файл, содержащий данные о полутоновом изображении, имя которого указано в filename
. Присвойте адрес потока данных fd
.
fd = fopen(filename, "rb");
Чтобы убедиться, что исполняемый файл может быть открыт filename
, напишите if
-оператор, который выходит из программы, если значение fd
является NULL
.
if (fd == NULL) { exit(-1); }
Замените вызов функции для main_sobel
по вызову main_sobel
с входными параметрами fd
и threshold
.
main_sobel(fd, threshold);
Закройте файл полутонового изображения после вызова sobel_terminate
.
fclose(fd);
В основном файле примера функция argInit_d1024xd1024_real_T
создает динамически выделенный массив переменного размера (emxArray) для изображения, которое вы передаете в фильтр Собеля. Эта функция инициализирует emxArray до размера по умолчанию, а элементы emxArray - до 0. Он возвращает инициализированный emxArray.
Для приложения фильтра Sobel измените функцию, чтобы считать данные полутонового изображения из двоичного файла в emxArray.
В функциональном argInit_d1024xd1024_real_T
:
Замените входной параметр void
с аргументом FILE *fd
. Эта переменная указывает на данные полутонового изображения, в которых читается функция.
static emxArray_real_T *argInit_d1024xd1024_real_T(FILE *fd)
Измените значения переменной iv2
для соответствия размерностям матрицы полутонового изображения gray
. iv2
содержит значения размеров для размерностей emxArray, который argInit_d1024xd1024_real_T
создает.
static int iv2[2] = { 484, 648 };
MATLAB хранит матричные данные в основном формате, в то время как C хранит матричные данные в основном формате строки. Объявите размерности соответственно.
Задайте переменную element
для сохранения значений, считанных из данных полутонового изображения.
double element;
Измените for
-цикл конструкция, чтобы считать точки данных из нормализованного изображения в element
путем добавления fread
команда на внутренний for
-цикл.
fread(&element, 1, sizeof(element), fd);
Внутри for
-цикл, назначить element
как набор значений для данных emxArray.
result->data[b_j0 + result->size[0] * b_j1] = element;
Измененные функциональные argInit_d1024xd1024_real_T инициализации
Функция MATLAB sobel.m
взаимодействует с массивами MATLAB, но приложение Sobel фильтрует интерфейсы с двоичными файлами.
Чтобы сохранить изображение, измененное алгоритмом фильтрации Собеля, в двоичный файл, создайте функцию saveImage
. Функция saveImage
записывает данные из emxArray в двоичный файл. В нем используется конструкция, подобная той, которая используется функцией argInit_d1024xd1024_real_T
.
В файл main.c
:
Определите функцию saveImage
который принимает адрес emxArray edgeImage
как вход и имеет выходной тип void.
static void saveImage(emxArray_uint8_T *edgeImage) { }
Задайте переменные b_j0
и b_j1
как они определены в функции argInit_d1024xd1024_real_T
.
int b_j0; int b_j1;
Задайте переменную element
для хранения данных, считанных из emxArray.
uint8_T element;
Откройте двоичный файл edge.bin
для записи измененного изображения. Присвоение адреса edge.bin
на FILE *fd
.
FILE *fd = fopen("edge.bin", "wb");
Чтобы убедиться, что исполняемый файл может быть открыт edge.bin
, напишите if
-оператор, который выходит из программы, если значение fd
является NULL
.
if (fd == NULL) { exit(-1); }
Написание вложенного for
-цикл создайте так же, как в функции argInit_d1024xd1024_real_T
.
for (b_j0 = 0; b_j0 < edgeImage->size[0U]; b_j0++) { for (b_j1 = 0; b_j1 < edgeImage->size[1U]; b_j1++) { } }
Внутри внутренней for
-цикл, присвойте значения из измененных данных изображения element
.
element = edgeImage->data[b_j0 + edgeImage->size[0] * b_j1];
После назначения на element
, напишите значение из element
в файл edge.bin
.
fwrite(&element, 1, sizeof(element), fd);
После for
-цикл конструкция, закрыть fd
.
fclose(fd);
В примере основной функции функция main_sobel
создает emxArrays для данных для полутоновых и измененных изображений. Он вызывает функцию argInit_d1024xd1024_real_T
чтобы инициализировать emxArray для полутонового изображения. main_sobel
передает как emxArrays, так и пороговое значение 0, которое выполняет функция инициализации argInit_real_T
возвращается к функции sobel
. Когда функция main_sobel
заканчивается, он отбрасывает результат функции sobel
.
Для приложения фильтра Sobel измените функцию main_sobel
кому:
В качестве входных параметров примите адрес данных полутонового изображения и пороговое значение.
Считывайте данные с адреса используя argInit_d1024xd1024_real_T
.
Передайте данные в алгоритм фильтрации Собеля с пороговым значением threshold
.
Сохраните результат с помощью saveImage
.
В функциональном main_sobel
:
Замените входные параметры в функцию на аргументы FILE *fd
и double threshold
.
static void main_sobel(FILE *fd, double threshold)
Передайте входной параметр fd
к вызову функции для argInit_d1024xd1024_real_T
.
originalImage = argInit_d1024xd1024_real_T(fd);
Замените пороговое значение, введенное в вызове функции, на sobel
с threshold
.
sobel(originalImage, threshold, edgeImage);
После вызова функции sobel
, вызовите функцию saveImage
с входом edgeImage
.
saveImage(edgeImage);
Чтобы соответствовать изменениям, внесенным в определения функций, внесите следующие изменения в объявления функций:
Измените вход функции *argInit_d1024xd1024_real_T
на FILE *fd
.
static emxArray_real_T *argInit_d1024xd1024_real_T(FILE *fd);
Измените входы функции main_sobel
на FILE *fd
и double threshold
.
static void main_sobel(FILE *fd, double threshold);
Добавьте функцию saveImage
.
static void saveImage(emxArray_uint8_T *edgeImage);
Для входных/выходных функций, которые вы используете в main.c
, добавить заголовочный файл stdio.h
в список включенных файлов.
#include <stdio.h>
main.c
Перейдите в рабочую папку, если вы в данный момент не находитесь в ней.
Создайте объект строения для независимого исполняемого файла на C.
cfg = coder.config('exe');
Сгенерируйте независимый исполняемый файл C для фильтра Собеля с помощью объекта строения и измененной основной функции.
codegen -report -config cfg sobel main.c main.h
По умолчанию, если MATLAB запускается в Windows® platform, исполняемый файл sobel.exe
генерируется в текущей рабочей папке. Если MATLAB запускается на платформе, отличной от Windows, расширение файла является соответствующим расширением для этой платформы. По умолчанию код, сгенерированный для исполняемого файла, находится в папке codegen/exe/sobel
.
Создайте матрицу MATLAB gray
если его нет в рабочем пространстве MATLAB:
im = imread('hello.jpg');
gray = (0.2989 * double(im(:,:,1)) + 0.5870 * double(im(:,:,2)) + 0.1140 * double(im(:,:,3)))/255;
Напишите матрицу gray
в двоичный файл с использованием fopen
и fwrite
команды. Приложение считывается в этом двоичном файле.
fid = fopen('gray.bin', 'w'); fwrite(fid, gray, 'double'); fclose(fid);
Запустите исполняемый файл, передав ему файл gray.bin
и пороговое значение 0,7.
Чтобы запустить пример в MATLAB на платформе Windows:
system('sobel.exe gray.bin 0.7');
Исполняемый файл генерирует edge.bin
.
Чтение файла edge.bin
в матрицу MATLAB edgeImExe
использование fopen
и fread
команды.
fd = fopen('edge.bin', 'r'); edgeImExe = fread(fd, size(gray), 'uint8'); fclose(fd);
Передайте матрицу edgeImExe
в repmat функций
и отобразите изображение.
im3Exe = repmat(edgeImExe, [1 1 3]); image(im3Exe);
Изображение соответствует изображениям из MATLAB и MEX-функций.