【问题标题】:Creating a bounding box in image with transparency在具有透明度的图像中创建边界框
【发布时间】:2017-03-17 19:21:38
【问题描述】:

我想用一种特定颜色裁剪图像,就像透明蒙版一样,我想创建一个最小的框来包围图像。

我的意思的图片肯定会更好地解释它:

RGB(255,0,255) 是透明蒙版,绿色框代表所需的边界框。

我已经算出了边界框的顶线:

    int nAlloc = (128 * 128) * 4;
    unsigned char* buf = new unsigned char[nAlloc];
    GetBitmapBits(hBMP, nAlloc, buf);
    for(int i = 0; i < nAlloc; i += 4)
    {
        if(buf[i] == 255 && buf[i + 1] == 0 && buf[i + 2] == 255)
        {
            continue;
        }
        // If I hit a first non-transparent pixel, 
        // I can then calculate the row where is that pixel located.
        else if(set_pixel == false)
        {
            set_pixel = true;
            index = ceil((float)(i / 4.0 / 128.0));
        }
        ... // Converting non-transparent pixels to Black&White
    }

    //I'm then drawing the bitmap to window like so:
    TransparentBlt(hdc, 5, 305 - index, 128, 128, hDC, 0, 0, 128, 128, RGB(255, 0, 255));

我想,我也知道如何确定最后一行,但我不确定,也不知道如何找出边界框的边。

【问题讨论】:

  • 您可能会使用flood fill 算法(这个问题有点像逆洪水填充)。
  • @JonathanPotter 那没有给我边界线,对吧?我不想影响任何像素,我只想得到弹跳框。我认为这对于这个问题来说太复杂了。
  • 你实际上不会做任何填充,但递归算法会让你找到对象的边缘。

标签: c++ winapi image-processing


【解决方案1】:

要找到图像的边界框,您只需逐行和逐列遍历图像,直到找到不透明的像素。 通过这样做,您可以获得边界框的最小值和最大值。

RECT BoundingBox = { 0,0,0,0 };
const int nAlloc = (128 * 128) * 4;
unsigned char* buf = new unsigned char[nAlloc];
GetBitmapBits(hBMP, nAlloc, buf);

bool found;

//search upper bound
found = false;
for (int row = 0; row<128 && !found; row++) //row
{
    for (int col = 0; col<128 && !found; col++) //column
    {
        int idx = (row * 128 + col) * 4;
        if (!(buf[idx] == 255 && buf[idx + 1] == 0 && buf[idx + 2] == 255)) //not transparent
        {
            BoundingBox.top = row;
            found = true;
        }
    }
}

//search lower bound
found = false;
for (int row = 127; row >= 0 && !found; row--) //row
{
    for (int col = 127; col >= 0 && !found; col--) //column
    {
        int idx = (row * 128 + col) * 4;
        if (!(buf[idx] == 255 && buf[idx + 1] == 0 && buf[idx + 2] == 255)) //not transparent           {
            BoundingBox.bottom = row;
            found = true;
        }
    }
}


//search left bound
found = false;
for (int col = 0; col<128 && !found; col++) //row
{
    for (int row = 0; row<128 && !found; row++) //column
    {
        int idx = (row * 128 + col) * 4;
        if (!(buf[idx] == 255 && buf[idx + 1] == 0 && buf[idx + 2] == 255)) //not transparent           {
            BoundingBox.left = col;
            found = true;
        }
    }
}


//search right bound
found = false;
for (int col = 127; col >= 0 && !found; col--) //row
{
    for (int row = 127; row >= 0 && !found; row--) //column
    {
        int idx = (row * 128 + col) * 4;
        if (!(buf[idx] == 255 && buf[idx + 1] == 0 && buf[idx + 2] == 255)) //not transparent           {
            BoundingBox.right = col;
            found = true;
        }
    }
}

//now the variable "BoundingBox" contains your BoundingBox

希望我的回答对你有所帮助。

【讨论】:

  • 这个不错,但实际上并不能解决我的问题。我也需要找到双方。不仅仅是我在问题中提到的顶部和底部。
  • 但是如果你向下滚动,这段代码也有边
  • 像魅力一样工作:)
【解决方案2】:

我不知道是否有一种优雅的方法可以做到这一点,但您可以简单地扫描整个图像,同时记录非透明像素的最小和最大列。

const int rowcnt = 128;
const int colcnt = 128;
const int bytesperpix = 4;
int pos = 0;
int colmin = colcnt;
int colmax = 0;
int colpos = 0;
for(int r = 0; r < rowcnt; ++r)
{
    for(int c = 0; c < colcnt * bytesperpix; c += 4)
    {
        pos = r * colcnt * bytesperpix + c;
        if(buf[pos] == 255 && buf[pos + 1] == 0 && buf[pos + 2] == 255)
        {
            continue;
        }
        else
        {
            colpos = c / bytesperpix;
            if(colpos < colmin)
                colmin = colpos;
            else if(colpos > colmax)
                colmax = colpos;
        }
    }
}

【讨论】:

  • 我认为这行不通。位图在一维中只有 4 个字节。所以当你在列中迭代时,它应该只是从 0 到 127。当我之前尝试过代码而不进一步查看它时,它总是会命中第二个 if 语句。
  • 我修改了代码。现在它迭代从 0 到 128 的行和从 0 到 512 的列。
  • 它仍然满足第二个条件。在此循环之后,colmax 等于值 65532。
  • 我希望你复制了整个代码,因为我在其他地方也改了一些错误。
猜你喜欢
  • 2017-12-18
  • 1970-01-01
  • 2021-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-11
相关资源
最近更新 更多