图像旋转C ++的问题 [英] problem with image rotation c++

查看:71
本文介绍了图像旋转C ++的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


我有此代码用于图像旋转


i have this code for image rotation

#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;

void main()
{
	int theta=90;
	int r0,c0;
	int r1,c1;
	int rows,cols;
	rows=500;
	cols=700;
	int ary[500][700];
	int tary[500][700];
	float rads=(theta*3.1419265)/180;
	r0=rows/2;
	c0=cols/2;
	
	for (int r=0;r<rows;r++)
	{
		for(int l=0;l<cols;l++)
		{
				
			r1=(int)(r0+((r-r0)*cos(rads))-((l-c0)*sin(rads)));
			c1=(int)(c0+((r-r0)*sin(rads))-((l-c0)*cos(rads)));
			
			tary[r1][c1]=ary[r][l];
			
		}
	}
}



它似乎适用于小型阵列
但是当我尝试使用大数组时失败了

谁能告诉我为什么?



it seem to work with small arrays
but when i try it with big arrays it is fail

can any one tell me why??

推荐答案

您要在堆栈上分配数组

You are allocating your arrays on stack

int ary[500][700];
int tary[500][700];



假设您的int是32位的,这些都是350000x4 = 1400000字节.
这种类型的存储空间太大,无法在堆栈上分配.

将它们移到功能主体之外:



These are 350000x4=1400000 bytes each assuming that your ints are 32-bit.
This type of storage is way too large to allocate on stack.

Move them outside your function body:

int ary[500][700];
int tary[500][700];

void main()
{
}



这将告诉编译器/链接器静态分配它们.它将起作用.



This will tell the compiler/linker to allocate them statically. It will work.


除了解决方案1(在堆栈上分配)和解决方案2(在横向格式中不可能旋转导致生成另一个横向格式图像)中提到的问题之外,您还拥有恒定的PI使用的是错误的:它是3.1415926,而不是3.1419265(尽管您可能无法注意到结果图像中的差异;)

另外,您应该尽可能地根据浮点数进行计算,否则会累积舍入误差.如果以任意角度旋转,这可能会导致奇怪的伪像(请参见下文).

您的代码似乎旨在以任意角度旋转图像.如果这是您的目标,则您必须颠倒逻辑:不要取原始像素并将其旋转到新位置(可能在新图像的框架之外),而应遍历图像的像素. 目标图像,并找出原始图像的哪个像素(如果有)将旋转到该位置.在许多情况下,您会发现给定像素在原始图像中没有原点,因此您需要为这些像素分配一些背景色.例如在您的示例中,这对于列0到99和600到699中的所有像素都是正确的.在任意角度旋转的情况下,它需要更多的计算.

幸运的是,在旋转的情况下反转逻辑并不是那么困难:您只需要取消旋转角度即可.当然,您必须正确计算旋转角度(计算中的一个符号已关闭).

In addition to the issues mentioned in Solutions 1 (allocating on stack) and 2 (impossible rotation of landscape format resulting in another landscape format image), the constant PI you have used is wrong: it is 3.1415926, not 3.1419265 (although you may not be able to notice a difference in the resulting images ;)

Additionally, you should be doing calculations based on floats wherever possible, or you''ll accumulate rounding errors. This may result in odd artefacts if you rotate by arbitrary angles (see below).

Your code appears to be aimed at rotating an image by arbitrary angles. If that is your goal, you''ll have to reverse the logic: rather than taking the original pixels and rotating them into the new position (which may be outside the frame of the new image), you should iterate over the pixels of the target image and figure out which pixel of the original image - if any - would be rotated into this position. In many cases you''ll find that a given pixel has no origin in the original image, thus you need to assign some background color to those pixels. E. g. in your example, this is true for all pixels in columns 0 to 99 and 600 to 699. In case of an arbitrary angle rotation, it takes a bit more computation.

Reversing the logic thankfully isn''t so hard in case of a rotation: you''ll just have to negate the rotation angle. Of course, you have to calculate the rotation correctly (one of the signs in your calculation is off).

int width = 700; // using 'constant' rather than literals within the code
int height = 500;
int background = 0; // this is the background color - use a suitable value here

float rads = theta*3.1415926/180.0; // fixed constant PI
float cs = cos(-rads); // precalculate these values
float ss = sin(-rads);
float xcenter = (float)(width)/2.0;   // use float here!
float ycenter = (float)(height)/2.0;
for (int r = 0; r < height; ++r) {
   for (int c = 0; c < width; ++c) {
      // now find the pixel of the original image that is rotated to (r,c)
      // rotation formula assumes that origin = top-left and y points down
      int rorig = ycenter + ((float)(r)-ycenter)*cs - ((float)(c)-xcenter)*ss;
      int corig = xcenter + ((float)(r)-ycenter)*ss + ((float)(c)-xcenter)*cs;
      // now get the pixel value if you can
      int pixel = background; // in case there is no original pixel
      if (rorig >= 0 && rorig < height && corig >= 0 && corig < width) {
         pixel = ary[rorig][corig];
      }
      tary[r][c] = pixel;
   }
}


您的代码有两个问题.一种是您尝试从堆栈中分配数组,如果您的堆栈不足以容纳如此大的数据量,则可能会造成麻烦.

第二个问题是目标阵列的尺寸与源阵列的尺寸相同.旋转700x500的图像时,结果将是尺寸为500x700的图像.在循环的第一个迭代中,您正在尝试将像素(0,0)映射到(100,600)(等于tary [600,100]),该像素位于此数组的边界之外.因此,您必须旋转目标的尺寸数组,或者做一些边界检查.

顺便说一下,我将sin和cos计算放在循环之外,因为它们是恒定的,而且并不是每个编译器都足够聪明来检测到这一点.
There are two problems with your code. One is that you try to allocate the arrays from the stack, which might cause trouble if your stack is not large enough for such huge amounts of data.

The second problem is that your target array has the same dimensions as your source array. When you rotate an image of 700x500, the result will be an image of size 500x700. Already in the first iteration of your loop you are trying to map pixel (0,0) to (100,600) (equiv. to tary [600,100] which is outside the boundaries of this array. So either you must rotate the dimensions of your target array as well, or do some bounds checking.

By the way, I would take the sin and cos computations outside the loop, as they are constant and not every compiler might be smart enough to detect this.


这篇关于图像旋转C ++的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆