Iphone 获取透明图像的边界框?

Iphone 获取透明图像的边界框?,iphone,c,objective-c,Iphone,C,Objective C,我将一个透明的.png加载到UIImage中 如何计算真实的边界框。例如,如果真实图像的尺寸小于.png尺寸 感谢您的帮助假设“图像的边框”只是图像中的一个矩形,以像素坐标指定 CGRect myImageViewRect = [myImageView frame]; CGSize myImageSize = [[myImageView image]size]; if(myImageSize.width < myImageViewRect.size.width){ NSLog(@"

我将一个透明的.png加载到UIImage中

如何计算真实的边界框。例如,如果真实图像的尺寸小于.png尺寸

感谢您的帮助

假设“图像的边框”只是图像中的一个矩形,以像素坐标指定

CGRect myImageViewRect = [myImageView frame];
CGSize myImageSize = [[myImageView image]size];

if(myImageSize.width < myImageViewRect.size.width){
   NSLog(@"it's width smaller!");
}
if(myImageSize.height < myImageViewRect.size.height){
   NSLog(@"it's height smaller!");
}
您需要
图像
的矩形,该矩形包含alpha大于
阈值
的所有像素(这相当于说不在此矩形中的所有像素的alpha小于
阈值
)。之后,您可以在屏幕坐标(或任何您想要的)中变换此矩形

基本算法是从包含整个图像的矩形开始,然后水平收缩矩形,然后垂直收缩(或垂直收缩,然后水平收缩)

我不知道Objective-C,所以我将代码放在纯C中(有些函数只是为了让代码更清晰):

typedef结构矩形
{
无符号整数x1,y1,x2,y2;
}矩形;
typedef结构图像
{
无符号整数的高度、宽度;
无符号整数*数据;
}形象;
无符号字符getPixelAlpha(图像*img,无符号整数x,无符号整数y)
{
无符号整数像素=0;//默认值=完全透明
如果(x>=img->宽度| y>=img->高度)
返回图像中的像素;
像素=img->data[x+y*img->width];
返回(无符号字符)((像素&0xFF000000)>>24);
}
空洞水平收缩(图像*img,无符号字符阈值,矩形*rect)
{
int x,y;
//左缩
对于(x=0;x<(int)img->width;x++)
{
//在x处找到垂直线的最大alpha
无符号字符lineAlphaMax=0;
对于(y=0;y<(int)img->height;y++)
{
无符号字符alpha=getPixelAlpha(img,x,y);
如果(alpha>lineAlphaMax)
lineAlphaMax=α;
}
//如果至少在线条的像素上,如果比“阈值”更不透明
//然后我们找到了矩形的左极限
如果(lineAlphaMax>=阈值)
{
rect->x1=x;
打破
}
}
//右倾
对于(x=img->width-1;x>=0;x--)
{
//在x处找到垂直线的最大alpha
无符号字符lineAlphaMax=0;
对于(y=0;y<(int)img->height;y++)
{
无符号字符alpha=getPixelAlpha(img,x,y);
如果(alpha>lineAlphaMax)
lineAlphaMax=α;
}
//如果至少在线条的像素上,如果比“阈值”更不透明
//然后我们找到了矩形的正确极限
如果(lineAlphaMax>=阈值)
{
rect->x2=x;
打破
}
}
}
//与水平收缩几乎相同。
垂直收缩无效(图像*img,无符号字符阈值,矩形*rect)
{
int x,y;
//畏缩
对于(y=0;y<(int)img->height;y++)
{
//求y处水平线的最大alpha
无符号字符lineAlphaMax=0;
对于(x=0;x<(int)img->width;x++)
{
无符号字符alpha=getPixelAlpha(img,x,y);
如果(alpha>lineAlphaMax)
lineAlphaMax=α;
}
//如果至少在线条的像素上,如果比“阈值”更不透明
//然后我们找到了矩形的上限
如果(lineAlphaMax>=阈值)
{
rect->y1=x;
打破
}
}
//从底部收缩
对于(y=img->高度-1;y>=0;y--)
{
//求y处水平线的最大alpha
无符号字符lineAlphaMax=0;
对于(x=0;x<(int)img->width;x++)
{
无符号字符alpha=getPixelAlpha(img,x,y);
如果(alpha>lineAlphaMax)
lineAlphaMax=α;
}
//如果至少在线条的像素上,如果比“阈值”更不透明
//然后我们找到了矩形的底部极限
如果(lineAlphaMax>=阈值)
{
rect->y2=x;
打破
}
}
}
//找到“真实”边界框
矩形findRealBoundingBox(图像*img,无符号字符阈值)
{
矩形r={0,0,img->width,img->height};
水平收缩(img、阈值和r);
垂直收缩(img、阈值和r);
返回r;
}

既然图像中有了以像素为单位的边界框坐标,您应该能够在设备坐标中对其进行变换。

让我重新表述一下:“如何在包含alpha值高于某个阈值的所有像素的部分透明图像中找到最小矩形?”。这就是你的意思吗?我从用户404709那里得到了答案,用户404709的答案对我来说很有用。可能存在一个(尽管不常见)问题
x
水平收缩中是
无符号的
,但是您正在使用
循环(x=img->width-1;x>=0;x--)
从右侧收缩。类似于
中的
y
垂直收缩
。不会有未定义的行为,因为
getPixelAlpha
检查边界,但如果阈值太高(与图像相比),它将无限期地循环。此外,您可以通过不重新考虑已处理的像素(尽管big-O性能不会改变)来加快搜索速度。您的意思是,图像的大小是(0,0)还是(w,0)还是(0,h)?如果允许
图像
的维度为
0
,那么这是另一个问题。然而,我的意思是,如果没有一个像素的alpha通道大于或等于
阈值
。说
threshold=0xFF
但是所有像素都有
getPixelAlpha(img,x,y)=threshold
将永远不会为真,因此您永远不会
从外部循环中中断。相反,循环将按预期运行,直到循环迭代器
x--
x
0[myImageView sizeToFit];
typedef struct Rectangle
{
    unsigned int x1, y1, x2, y2;
} Rectangle;

typedef struct Image
{
    unsigned int height,width;
    unsigned int* data;
} Image;

unsigned char getPixelAlpha(Image* img, unsigned int x, unsigned int y)
{
    unsigned int pixel = 0; // default = fully transparent

    if(x >= img->width || y >= img->height)
        return pixel; // Consider everything not in the image fully transparent

    pixel = img->data[x + y * img->width];
    return (unsigned char)((pixel & 0xFF000000) >> 24);
}

void shrinkHorizontally(Image* img, unsigned char threshold, Rectangle* rect)
{
    int x, y;

    // Shrink from left
    for(x = 0; x < (int)img->width; x++)
    {
        // Find the maximum alpha of the vertical line at x
        unsigned char lineAlphaMax = 0;
        for(y = 0; y < (int)img->height; y++)
        {
            unsigned char alpha = getPixelAlpha(img,x,y);
            if(alpha > lineAlphaMax)
                lineAlphaMax = alpha;
        }

        // If at least on pixel of the line if more opaque than 'threshold'
        // then we found the left limit of the rectangle
        if(lineAlphaMax >= threshold)
        {
            rect->x1 = x;
            break;
        }
    }


    // Shrink from right
    for(x = img->width - 1; x >= 0; x--)
    {
        // Find the maximum alpha of the vertical line at x
        unsigned char lineAlphaMax = 0;
        for(y = 0; y < (int)img->height; y++)
        {
            unsigned char alpha = getPixelAlpha(img,x,y);
            if(alpha > lineAlphaMax)
                lineAlphaMax = alpha;
        }

        // If at least on pixel of the line if more opaque than 'threshold'
        // then we found the right limit of the rectangle
        if(lineAlphaMax >= threshold)
        {
            rect->x2 = x;
            break;
        }
    }
}

// Almost the same than shrinkHorizontally.
void shrinkVertically(Image* img, unsigned char threshold, Rectangle* rect)
{
    int x, y;

    // Shrink from up
    for(y = 0; y < (int)img->height; y++)
    {
        // Find the maximum alpha of the horizontal line at y
        unsigned char lineAlphaMax = 0;
        for(x = 0; x < (int)img->width; x++)
        {
            unsigned char alpha = getPixelAlpha(img,x,y);
            if(alpha > lineAlphaMax)
                lineAlphaMax = alpha;
        }

        // If at least on pixel of the line if more opaque than 'threshold'
        // then we found the up limit of the rectangle
        if(lineAlphaMax >= threshold)
        {
            rect->y1 = x;
            break;
        }
    }


    // Shrink from bottom
    for(y = img->height- 1; y >= 0; y--)
    {
        // Find the maximum alpha of the horizontal line at y
        unsigned char lineAlphaMax = 0;
        for(x = 0; x < (int)img->width; x++)
        {
            unsigned char alpha = getPixelAlpha(img,x,y);
            if(alpha > lineAlphaMax)
                lineAlphaMax = alpha;
        }

        // If at least on pixel of the line if more opaque than 'threshold'
        // then we found the bottom limit of the rectangle
        if(lineAlphaMax >= threshold)
        {
            rect->y2 = x;
            break;
        }
    }
}

// Find the 'real' bounding box
Rectangle findRealBoundingBox(Image* img, unsigned char threshold)
{
    Rectangle r = { 0, 0, img->width, img->height };
    shrinkHorizontally(img,threshold,&r);
    shrinkVertically(img,threshold,&r);
    return r;
}