Это дополнительный вопрос для генератора двумерных гауссовских изображений в C, реализации двумерной бикубической интерполяции в C и метода подплоскости для общей двумерной плоскости данных в C #. Помимо генерации гауссовского изображения и бикубической интерполяции, я пытаюсь сделать в этом посте функцию субизображения версии C, чтобы ROI (область интереса) изображения могут быть извлечены.
Пример выходного фрагмента изображения:
Экспериментальная реализация
SubMonoImage
реализация функции: операция извлечения фрагментов изображения дляMONOIMAGE
состав.MONOIMAGE SubMonoImage(const MONOIMAGE image, unsigned int locationx, unsigned int locationy, unsigned int sizex, unsigned int sizey) { MONOIMAGE output = CreateMonoImage(sizex, sizey); for (size_t y = 0; y < sizey; y++) { for (size_t x = 0; x < sizex; x++) { if ((locationy + y) < image.XSIZE && (locationx + x) < image.YSIZE) // valid location { output.IMAGE_DATA[GetMonoImageIndex(x, y, output)] = image.IMAGE_DATA[GetMonoImageIndex((locationx + x), (locationy + y), image)]; } } } return output; }
SubRGBImage
реализация функции: операция извлечения фрагментов изображения дляRGBIMAGE
состав.RGBIMAGE SubRGBImage(const RGBIMAGE image, unsigned int locationx, unsigned int locationy, unsigned int sizex, unsigned int sizey) { MONOIMAGE R = SubMonoImage(GetPlaneR(image), locationx, locationy, sizex, sizey); MONOIMAGE G = SubMonoImage(GetPlaneG(image), locationx, locationy, sizex, sizey); MONOIMAGE B = SubMonoImage(GetPlaneB(image), locationx, locationy, sizex, sizey); RGBIMAGE output = CreateRGBImageFromMonoImages(sizex, sizey, R, G, B); DeleteMonoImage(R); DeleteMonoImage(G); DeleteMonoImage(B); return output; }
basic_functions.h
: Содержит несколько объявлений основных функций./* Develop by Jimmy Hu */ #ifndef BASIC_FUNCTIONS_H #define BASIC_FUNCTIONS_H #include "base.h" #include "imageio.h" MONOIMAGE CreateMonoImage(const unsigned int, const unsigned int); void DeleteMonoImage(MONOIMAGE); MONOIMAGE GetPlaneR(const RGBIMAGE); MONOIMAGE GetPlaneG(const RGBIMAGE); MONOIMAGE GetPlaneB(const RGBIMAGE); RGBIMAGE CreateRGBImage(const unsigned int, const unsigned int); RGBIMAGE CreateRGBImageFromMonoImages(const unsigned int, const unsigned int, MONOIMAGE, MONOIMAGE, MONOIMAGE); void DeleteRGBImage(RGBIMAGE); size_t GetMonoImageIndex(const size_t, const size_t, const MONOIMAGE); size_t GetRGBImageIndex(const size_t, const size_t, const RGBIMAGE); size_t clip(const size_t, const size_t, const size_t); float clip_float(const float, const float, const float); #endif
basic_functions.c
: Содержит несколько основных определений функций./* Develop by Jimmy Hu */ #include "basic_functions.h" MONOIMAGE CreateMonoImage(const unsigned int sizex, const unsigned int sizey) { MONOIMAGE output; output.XSIZE = sizex; output.YSIZE = sizey; output.IMAGE_DATA = malloc(sizeof *output.IMAGE_DATA * sizex * sizey); if(output.IMAGE_DATA == NULL) { printf(stderr, "Memory allocation error!"); return output; } return output; } void DeleteMonoImage(MONOIMAGE image) { free(image.IMAGE_DATA); return; } MONOIMAGE GetPlaneR(const RGBIMAGE image) { MONOIMAGE output = CreateMonoImage(image.XSIZE, image.YSIZE); for (size_t y = 0; y < image.YSIZE; y++) { for (size_t x = 0; x < image.XSIZE; x++) { output.IMAGE_DATA[GetMonoImageIndex(x, y, output)] = image.IMAGE_DATA[GetRGBImageIndex(x, y, image)].channels[0]; } } return output; } MONOIMAGE GetPlaneG(const RGBIMAGE image) { MONOIMAGE output = CreateMonoImage(image.XSIZE, image.YSIZE); for (size_t y = 0; y < image.YSIZE; y++) { for (size_t x = 0; x < image.XSIZE; x++) { output.IMAGE_DATA[GetMonoImageIndex(x, y, output)] = image.IMAGE_DATA[GetRGBImageIndex(x, y, image)].channels[1]; } } return output; } MONOIMAGE GetPlaneB(const RGBIMAGE image) { MONOIMAGE output = CreateMonoImage(image.XSIZE, image.YSIZE); for (size_t y = 0; y < image.YSIZE; y++) { for (size_t x = 0; x < image.XSIZE; x++) { output.IMAGE_DATA[GetMonoImageIndex(x, y, output)] = image.IMAGE_DATA[GetRGBImageIndex(x, y, image)].channels[2]; } } return output; } RGBIMAGE CreateRGBImage(const unsigned int sizex, const unsigned int sizey) { RGBIMAGE output; output.XSIZE = sizex; output.YSIZE = sizey; output.IMAGE_DATA = malloc(sizeof *output.IMAGE_DATA * sizex * sizey); if(output.IMAGE_DATA == NULL) { printf(stderr, "Memory allocation error!"); return output; } return output; } RGBIMAGE CreateRGBImageFromMonoImages(const unsigned int sizex, const unsigned int sizey, MONOIMAGE R, MONOIMAGE G, MONOIMAGE B) { RGBIMAGE output; output.XSIZE = sizex; output.YSIZE = sizey; output.IMAGE_DATA = malloc(sizeof *output.IMAGE_DATA * sizex * sizey); if (output.IMAGE_DATA == NULL) { printf(stderr, "Memory allocation error!"); return output; } if ((R.XSIZE != G.XSIZE) || (G.XSIZE != B.XSIZE) || (R.XSIZE != B.XSIZE) || (R.YSIZE != G.YSIZE) || (G.YSIZE != B.YSIZE) || (R.YSIZE != B.YSIZE)) { printf(stderr, "Input size inequal!"); return output; } for (size_t y = 0; y < R.YSIZE; y++) { for (size_t x = 0; x < R.XSIZE; x++) { output.IMAGE_DATA[GetRGBImageIndex(x, y, output)].channels[0] = R.IMAGE_DATA[GetMonoImageIndex(x, y, R)]; output.IMAGE_DATA[GetRGBImageIndex(x, y, output)].channels[1] = G.IMAGE_DATA[GetMonoImageIndex(x, y, G)]; output.IMAGE_DATA[GetRGBImageIndex(x, y, output)].channels[2] = B.IMAGE_DATA[GetMonoImageIndex(x, y, B)]; } } return output; } void DeleteRGBImage(RGBIMAGE image) { free(image.IMAGE_DATA); return; } size_t GetMonoImageIndex(const size_t x, const size_t y, const MONOIMAGE image) { return y * image.XSIZE + x; } size_t GetRGBImageIndex(const size_t x, const size_t y, const RGBIMAGE image) { return y * image.XSIZE + x; } size_t clip(const size_t input, const size_t lowerbound, const size_t upperbound) { if (input < lowerbound) { return lowerbound; } if (input > upperbound) { return upperbound; } return input; } float clip_float(const float input, const float lowerbound, const float upperbound) { if (input < lowerbound) { return lowerbound; } if (input > upperbound) { return upperbound; } return input; }
base.h
: Содержит реализацию базового типа/* Develop by Jimmy Hu */ #ifndef BASE_H #define BASE_H #include <math.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define MAX_PATH 256 #define FILE_ROOT_PATH "./" #define True true #define False false typedef struct RGB { unsigned char channels[3]; } RGB; typedef struct HSV { long double channels[3]; // Range: 0 <= H < 360, 0 <= S <= 1, 0 <= V <= 255 }HSV; typedef struct BMPIMAGE { char FILENAME[MAX_PATH]; unsigned int XSIZE; unsigned int YSIZE; unsigned char FILLINGBYTE; unsigned char *IMAGE_DATA; } BMPIMAGE; typedef struct RGBIMAGE { unsigned int XSIZE; unsigned int YSIZE; RGB *IMAGE_DATA; } RGBIMAGE; typedef struct HSVIMAGE { unsigned int XSIZE; unsigned int YSIZE; HSV *IMAGE_DATA; } HSVIMAGE; typedef struct MONOIMAGE { unsigned int XSIZE; unsigned int YSIZE; unsigned char *IMAGE_DATA; } MONOIMAGE; typedef struct DOUBLEIMAGE { unsigned int XSIZE; unsigned int YSIZE; double *IMAGE_DATA; }; #endif
Полный код тестирования
/* Develop by Jimmy Hu */
#include "base.h"
#include "basic_functions.h"
#include "imageio.h"
MONOIMAGE BicubicInterpolationMonoImage(MONOIMAGE image, const int, const int);
RGBIMAGE BicubicInterpolationRGBImage(RGBIMAGE image, const int, const int);
unsigned char BicubicPolate(const unsigned char*, const float, const float);
float CubicPolate(const float, const float, const float, const float, const float);
/* Subimage extracting operation for MONOIMAGE structure
*/
MONOIMAGE SubMonoImage(const MONOIMAGE, unsigned int, unsigned int, unsigned int, unsigned int);
/* Subimage extracting operation for RGBIMAGE structure
*/
RGBIMAGE SubRGBImage(const RGBIMAGE, unsigned int, unsigned int, unsigned int, unsigned int);
int main(int argc, char** argv)
{
char *FilenameString;
FilenameString = malloc( sizeof *FilenameString * MAX_PATH);
printf("BMP image input file name:(ex:test): ");
scanf("%s", FilenameString);
BMPIMAGE BMPImage1 = bmp_file_read(FilenameString, false);
RGBIMAGE RGBImage1;
RGBImage1.XSIZE = BMPImage1.XSIZE;
RGBImage1.YSIZE = BMPImage1.YSIZE;
RGBImage1.IMAGE_DATA = raw_image_to_array(BMPImage1.XSIZE, BMPImage1.YSIZE, BMPImage1.IMAGE_DATA);
RGBIMAGE RGBImage2 = SubRGBImage(RGBImage1, 150, 100, 250, 300);
RGBIMAGE RGBImage3 = BicubicInterpolationRGBImage(RGBImage2, RGBImage2.XSIZE * 2, RGBImage2.YSIZE * 2);
printf("file name for saving:(ex:test): ");
scanf("%s", FilenameString);
bmp_write(FilenameString, RGBImage3.XSIZE, RGBImage3.YSIZE, array_to_raw_image(RGBImage3.XSIZE, RGBImage3.YSIZE, RGBImage3.IMAGE_DATA));
free(FilenameString);
DeleteRGBImage(RGBImage1);
DeleteRGBImage(RGBImage2);
DeleteRGBImage(RGBImage3);
return 0;
}
MONOIMAGE BicubicInterpolationMonoImage(MONOIMAGE image, const int newSizeX, const int newSizeY)
{
MONOIMAGE output = CreateMonoImage(newSizeX, newSizeY);
int originSizeX = image.XSIZE;
int originSizeY = image.YSIZE;
if (output.IMAGE_DATA == NULL)
{
printf(stderr, "Memory allocation error!");
return output;
}
float ratiox = (float)originSizeX / (float)newSizeX;
float ratioy = (float)originSizeY / (float)newSizeY;
for (size_t y = 0; y < newSizeY; y++)
{
for (size_t x = 0; x < newSizeX; x++)
{
float xMappingToOrigin = (float)x * ratiox;
float yMappingToOrigin = (float)y * ratioy;
float xMappingToOriginFloor = floor(xMappingToOrigin);
float yMappingToOriginFloor = floor(yMappingToOrigin);
float xMappingToOriginFrac = xMappingToOrigin - xMappingToOriginFloor;
float yMappingToOriginFrac = yMappingToOrigin - yMappingToOriginFloor;
unsigned char ndata[4 * 4];
for (int ndatay = -1; ndatay <= 2; ndatay++)
{
for (int ndatax = -1; ndatax <= 2; ndatax++)
{
ndata[(ndatay + 1) * 4 + (ndatax + 1)] = image.IMAGE_DATA[
clip(yMappingToOriginFloor + ndatay, 0, originSizeY - 1) * originSizeX +
clip(xMappingToOriginFloor + ndatax, 0, originSizeX - 1)
];
}
}
output.IMAGE_DATA[ y * newSizeX + x ] = BicubicPolate(ndata, xMappingToOriginFrac, yMappingToOriginFrac);
}
}
return output;
}
RGBIMAGE BicubicInterpolationRGBImage(RGBIMAGE image, const int newSizeX, const int newSizeY)
{
MONOIMAGE R = BicubicInterpolationMonoImage(GetPlaneR(image), newSizeX, newSizeY);
MONOIMAGE G = BicubicInterpolationMonoImage(GetPlaneG(image), newSizeX, newSizeY);
MONOIMAGE B = BicubicInterpolationMonoImage(GetPlaneB(image), newSizeX, newSizeY);
RGBIMAGE output = CreateRGBImageFromMonoImages(newSizeX, newSizeY, R, G, B);
DeleteMonoImage(R);
DeleteMonoImage(G);
DeleteMonoImage(B);
return output;
}
unsigned char BicubicPolate(const unsigned char* const ndata, const float fracx, const float fracy)
{
float x1 = CubicPolate( ndata[0], ndata[1], ndata[2], ndata[3], fracx );
float x2 = CubicPolate( ndata[4], ndata[5], ndata[6], ndata[7], fracx );
float x3 = CubicPolate( ndata[8], ndata[9], ndata[10], ndata[11], fracx );
float x4 = CubicPolate( ndata[12], ndata[13], ndata[14], ndata[15], fracx );
float output = clip_float(CubicPolate( x1, x2, x3, x4, fracy ), 0.0, 255.0);
return (unsigned char)output;
}
float CubicPolate(const float v0, const float v1, const float v2, const float v3, const float fracy)
{
float A = (v3-v2)-(v0-v1);
float B = (v0-v1)-A;
float C = v2-v0;
float D = v1;
return D + fracy * (C + fracy * (B + fracy * A));
}
MONOIMAGE SubMonoImage(const MONOIMAGE image, unsigned int locationx, unsigned int locationy, unsigned int sizex, unsigned int sizey)
{
MONOIMAGE output = CreateMonoImage(sizex, sizey);
for (size_t y = 0; y < sizey; y++)
{
for (size_t x = 0; x < sizex; x++)
{
if ((locationy + y) < image.XSIZE &&
(locationx + x) < image.YSIZE) // valid location
{
output.IMAGE_DATA[GetMonoImageIndex(x, y, output)] =
image.IMAGE_DATA[GetMonoImageIndex((locationx + x), (locationy + y), image)];
}
}
}
return output;
}
RGBIMAGE SubRGBImage(const RGBIMAGE image, unsigned int locationx, unsigned int locationy, unsigned int sizex, unsigned int sizey)
{
MONOIMAGE R = SubMonoImage(GetPlaneR(image), locationx, locationy, sizex, sizey);
MONOIMAGE G = SubMonoImage(GetPlaneG(image), locationx, locationy, sizex, sizey);
MONOIMAGE B = SubMonoImage(GetPlaneB(image), locationx, locationy, sizex, sizey);
RGBIMAGE output = CreateRGBImageFromMonoImages(sizex, sizey, R, G, B);
DeleteMonoImage(R);
DeleteMonoImage(G);
DeleteMonoImage(B);
return output;
}
Все предложения приветствуются.
Сводная информация:
На какой вопрос это продолжение?
Генератор двумерных гауссовских изображений в C,
Реализация двумерной бикубической интерполяции на языках C и
Метод подплоскости для общей двумерной плоскости данных в C #.
Какие изменения были внесены в код с момента последнего вопроса?
Я пытаюсь сделать в этом посте функцию подобраза версии C.
Почему запрашивается новый обзор?
Если есть какие-то улучшения, пожалуйста, дайте мне знать.
Справка
1 ответ
Есть изображения, которые гораздо лучше подходят для просмотра прямоугольных обрезков:
struct Image {
void *pixels;
enum format pixel_format;
size_t width;
size_t height;
size_t stride;
}
С участием pixels
указывая на верхнюю левую позицию в исходном изображении, и stride
скопировано с шага источника, то нам не нужно копировать данные. Если мы действительно хотим скопировать, это может быть отдельная функция. Это помогает разделить наши опасения.
Несвязанные, пожалуйста, не используйте имена ALL_CAPS для идентификаторов C. Обычно для макросов препроцессора используются заглавные буквы; их нужно различать, потому что они представляют собой текстовые замены, а не имена, и не ограничиваются определенной областью. Когда обычные имена пишутся заглавными буквами, становится сложнее выбрать макросы и проявить к ним необходимую осторожность.