You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++基于像素连通域识别图片按钮并绘制标注框的代码实现问题

按钮识别程序补全方案

实现逻辑说明

  • 新增像素判断函数:根据像素RGB值判定是否属于按钮区域,可根据实际图像的按钮、背景色差调整阈值
  • 新增四连通递归搜索函数:遍历单个按钮的所有连通像素,自动计算该按钮的最小/最大横纵坐标,得到标注框的边界
  • 遍历全图触发搜索:每识别到一个未处理的按钮像素就启动连通域搜索,搜索完成后在边界绘制红色标注框
  • 按照PPM P3格式规范写入处理后的图像数据

完整补全代码

#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

class pixel_class {
private:
  int red, green, blue;
  bool exclude;  // if true, do not check this pixel
public:
  void loaddata(int v1, int v2, int v3);
  void datatofile(fstream & ppmfile);
  int getR() { return red; }
  int getG() { return green; }
  int getB() { return blue; }
  void setexclude(bool ex) { exclude = ex; }
  bool getexclude() { return exclude; }
};

void loadButtons();
// 新增辅助函数声明
bool isButtonPixel(int x, int y);
void dfsSearch(int x, int y);

int total, xmin, xmax, ymin, ymax;  // MUST be global if used
int screenx, screeny, maxcolours;   // you must use these
pixel_class picture[600][600];      // you must use this

int main() {

  // Step 1 : read in the image from Buttons.ppm
  loadButtons();

  // Step 2 : identify buttons and draw boxes
  for (int y = 0; y < screeny; y++) {
    for (int x = 0; x < screenx; x++) {
        if (isButtonPixel(x, y)) {
            // 初始化当前按钮的边界值
            xmin = x;
            xmax = x;
            ymin = y;
            ymax = y;
            // 四连通搜索当前按钮的所有像素
            dfsSearch(x, y);
            // 绘制红色矩形标注框,线宽2像素避免显示过细
            for (int px = xmin - 1; px <= xmax + 1; px++) {
                if (px >= 0 && px < screenx) {
                    if (ymin - 1 >= 0) picture[px][ymin - 1].loaddata(255, 0, 0);
                    if (ymax + 1 < screeny) picture[px][ymax + 1].loaddata(255, 0, 0);
                }
            }
            for (int py = ymin - 1; py <= ymax + 1; py++) {
                if (py >= 0 && py < screeny) {
                    if (xmin - 1 >= 0) picture[xmin - 1][py].loaddata(255, 0, 0);
                    if (xmax + 1 < screenx) picture[xmax + 1][py].loaddata(255, 0, 0);
                }
            }
        }
    }
  }

  // Step 3 : output the final .ppm file
  fstream outfile;
  string outfilename = "Labeled_Buttons.ppm";
  outfile.open(outfilename.c_str(), fstream::out);
  if (outfile.is_open() == false) {
    cout << "ERROR: 无法打开输出文件 " << outfilename << endl;
    exit(3);
  }
  // 写入PPM标准头信息
  outfile << "P3" << endl;
  outfile << "# 按钮标注结果图" << endl;
  outfile << screenx << " " << screeny << endl;
  outfile << maxcolours << endl;
  // 写入所有像素数据
  for (int y = 0; y < screeny; y++) {
    for (int x = 0; x < screenx; x++) {
        picture[x][y].datatofile(outfile);
    }
    outfile << endl;
  }
  outfile.close();
  cout << "处理完成,标注结果已保存为 " << outfilename << endl;
  return 0;
}

void loadButtons() {
  // load the picture from Buttons.ppm
  int x, y, R, G, B;
  fstream infile;
  string infilename, line;
  infilename = "Buttons.ppm";
  infile.open(infilename.c_str(), fstream::in);
  if (infile.is_open() == false) {
    cout << "ERROR: 无法打开输入文件 " << infilename << endl;
    exit(2);
  }
  getline(infile, line);  // this line is "P3"
  getline(infile, line);  // this line is "# filename"
  infile >> screenx >> screeny;  // this line is the size
  infile >> maxcolours;  // this line is 256
  for (y = 0; y < screeny; y++) {
    for (x = 0; x < screenx; x++) {
      infile >> R >> G >> B;
      picture[x][y].loaddata(R, G, B);
      picture[x][y].setexclude(false);
    }
  }
  infile.close();
}

// 判断是否为未处理的按钮像素,可根据实际图像调整阈值
bool isButtonPixel(int x, int y) {
    if (x < 0 || x >= screenx || y < 0 || y >= screeny) return false;
    if (picture[x][y].getexclude()) return false;
    // 示例判断逻辑:深色按钮、浅色背景,RGB之和小于600判定为按钮像素
    int sumRGB = picture[x][y].getR() + picture[x][y].getG() + picture[x][y].getB();
    return sumRGB < 600;
}

// 四连通域递归搜索,更新当前按钮的边界值
void dfsSearch(int x, int y) {
    if (!isButtonPixel(x, y)) return;
    // 标记为已处理避免重复搜索
    picture[x][y].setexclude(true);
    // 更新边界坐标
    xmin = min(xmin, x);
    xmax = max(xmax, x);
    ymin = min(ymin, y);
    ymax = max(ymax, y);
    // 按要求搜索四方向连通像素
    dfsSearch(x - 1, y);
    dfsSearch(x + 1, y);
    dfsSearch(x, y - 1);
    dfsSearch(x, y + 1);
}

//--------------- methods for the pixel_class ------------
void pixel_class::loaddata(int v1, int v2, int v3) {
  red = v1;
  green = v2;
  blue = v3;
}

void pixel_class::datatofile(fstream & ppmfile) {
  // write the data for one pixel to the ppm file
  ppmfile << red << " " << green;
  ppmfile << " " << blue << "  ";
}

注意事项

如果你的按钮和背景色差和默认判断逻辑不符,修改isButtonPixel函数里的RGB判定规则即可。

内容的提问来源于stack exchange,提问作者DiFFt HD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 22:48:03