C++如何使用指针数组缩小图像
C++ how to shrink an image using a pointer array?
我正在编写一个处理图像的 c++ 程序,这是缩小图像的函数。 有一个"像素"指针数组和一个定义了图像颜色的类。 除了Visual Studio中包含的库之外,我不能使用任何其他库进行此图像程序。 我对此功能有问题,我需要遍历图像中的像素并将其拆分为块;用户将输入块的宽度/高度。 创建块后,需要从每个块中获取平均RGB值(该平均值将成为单个新像素),并且所有块的排列都将"缩小"图像。 到目前为止,似乎创建块是因为图像变小,但我的图像完全变成灰色。RGB 像素的总数正确添加,但代码的其余部分必须关闭某些内容,我无法确定它。这是我的代码:
//creates a block of average colors based on range of pixels given
pixel CreateBlock(int start, int stop, pixel** currpix, int blockHeight, int blockWidth)
{
pixel** block; //Problem? might have to be a single pointer pixel* block[];
block = new pixel*[blockHeight];
for (int i = 0; i < blockHeight; i++)
block[i] = new pixel[blockWidth];
pixel newPix;
float totred = 0, totblue = 0, totgreen = 0;
int redav = 0.0, blueav = 0.0, greenav = 0.0;
for (int i = 0; i < blockHeight; i++)
{
for (int j = 0; j < blockWidth; j++)
{
totred = totred + block[i][j].red;
totblue = totblue + block[i][j].blue;
totgreen = totgreen + block[i][j].green;
}
}
redav = totred / (blockHeight*blockWidth);
blueav = totblue / (blockHeight* blockWidth);
greenav = totgreen / (blockHeight*blockWidth);
newPix.red = redav;
newPix.blue = blueav;
newPix.green = greenav;
return newPix;
}
//make a new image that is a smaller resampling of the bigger image
void averageRegions(int blockWidth, int blockHeight)
{
int height = displayed->getHeight(), width = displayed->getWidth();
int i = 0, j = 0;
pixel** currpix = displayed->getPixels(); //PROBLEM
image* shrunk = displayed;
//shrunk->getPixels();
shrunk->createNewImage(width / blockWidth, height / blockHeight);
while (i < height)
{
while (j < width)
{
int start = i, stop = i + 10;
shrunk->getPixels()[i][j] = CreateBlock(start, stop, currpix, blockHeight, blockWidth);
j = j + blockWidth;
}
i = i + blockHeight;
}
return;
}
下面是图像类:
class image {
public:
image(); //the image constructor (initializes everything)
image(string filename); //a image constructor that directly loads an image from disk
~image(); //the image destructor (deletes the dynamically created pixel array)
void createNewImage(int width, int height); //this function deletes any current image data and creates a new blank image
//with the specified width/height and allocates the needed number of pixels
//dynamically.
bool loadImage(string filename); //load an image from the specified file path. Return true if it works, false if it is not a valid image.
//Note that we only accept images of the RGB 8bit colorspace!
void saveImage(string filename); //Save an image to the specified path
pixel** getPixels(); //return the 2-dimensional pixels array
int getWidth(); //return the width of the image
int getHeight(); //return the height of the image
void viewImage(CImage* myImage); //This function is called by the windows GUI. It returns the image in format the GUI understands.
private:
void pixelsToCImage(CImage* myImage); //this function is called internally by the image class.
//it converts our pixel struct array to a standard BGR uchar array with word spacing.
//(Don't worry about what this does)
pixel** pixels; // pixel data array for image
int width, height; // stores the image dimensions
};
这是像素类:
class pixel
{
public:
unsigned char red; //the red component
unsigned char green; //the green component
unsigned char blue; //the blue component
};
好的,减去大量的内存泄漏和误导性名称,您在CreateBlock
中找到平均值的正确想法。 我会尝试如下:
pixel averagePixels(pixel **oldImage, int startRow, int startCol, int blockHeight, int blockWidth){
float rTot, gTot, bTot;
pixel avg;
for(int i = startRow ; i < blockHeight + startRow ; i++){
for(int j = startCol ; j < blockWidth + startCol ; j++){
rTot += oldImage[i][j].red;
gTot += oldImage[i][j].green;
bTot += oldImage[i][j].blue;
}
}
avg.red = rTot / (blockHeight * blockWidth);
avg.green = gTot / (blockHeight * blockWidth);
avg.blue = bTot / (blockHeight * blockWidth);
return avg;
}
pixel **shrinkImage(pixel **oldImage, int blockHeight, int blockWidth){
int newHeight = oldImage->getHeight() / blockHeight;
int newWidth = oldImage->getWidth() / blockWidth;
pixel **newImage = new pixel* [newHeight];
for(int i = 0 ; i < newHeight ; i++)
newImage[i] = new pixel[newWidth];
for(int i = 0 ; i < newHeight){
for(int j = 0 ; j < newWidth){
newImage[i][j] = averagePixels(oldImage, blockHeight * i, blockWidth * j, blockWidth, blockHeight);
}
}
return newImage;
}
免责声明,我实际上还没有测试过任何这些,确保新的 rgb 值在可接受的范围内(我认为是 0-255? 您还需要一些边界检查/特殊情况,以应对图像大小不能完全被块大小整除的情况。
您没有在CreateBlock
代码中使用currpix
。您正在对代码中分配的随机数求平均值:
block = new pixel*[blockHeight];
for (int i = 0; i < blockHeight; i++)
block[i] = new pixel[blockWidth];
问题似乎是您在此处使用未初始化的值:
totred = totred + block[i][j].red;
totblue = totblue + block[i][j].blue;
totgreen = totgreen + block[i][j].green;
您分配了block
,但未能初始化任何值。 因此red
、green
和blue
都有随机值。
您还有一个内存泄漏 - 您在此处分配了block
,但未能解除分配它:
pixel** block;
block = new pixel*[blockHeight];
for (int i = 0; i < blockHeight; i++)
block[i] = new pixel[blockWidth];
取而代之的是,最简单的解决方案是使用 std::vector<std::vector<pixel>>
:
#include <vector>
//...
std::vector<std::vector<pixel> > block(blockHeight, std::vector<pixel>(blockWidth));
一行代码可以完成循环完成的所有操作,还可以消除内存泄漏。 它真正没有做的是使用您需要的值初始化block
。 这些值是什么 - 你需要确定它们。
相关文章:
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- OpenCV EqualizeHist()从彩色图像创建黑白图像
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 平均图像时图像损坏
- 在C++中使用GDAL可以将图像的像素坐标转换为lat,long吗
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- Vulkan验证层不断在VkQueuePresentKHR()上抛出图像布局错误
- 使用FFMPEG将RGB图像序列保存到.mp4时出现问题
- 将RGB图像保存为PPM格式
- 我无法缩小此分段错误的原因
- 将图像添加到资源文件夹UWP C++
- 彩色图像的卤化物处理平均值
- C++射线示踪剂ppm表示没有足够的数据来显示图像
- 使用 SSE 以最快的速度缩小 8 位灰度图像
- 插值用于在 OpenCV 中平滑缩小图像
- QLabel扩展以适应一个大图像,但不能缩小以适应一个小图像
- C++如何使用指针数组缩小图像
- 快速图像缩小在C/ c++