基于图的图像分割(Graph-BasedImageSegmentation)的分块实现

    xiaoxiao2023-10-26  29

    最初的代码自然是大牛写的,我只是在此基础之上,实现分块分割,暂未开启多线程。

    引用:

    Efficient Graph-Based Image Segmentation,IJCV 2004,MIT Code

    直接上代码吧,给有同样需求的童鞋参考。

    头文件:

    #pragma once #ifdef DLLProvider #define DLL_API_C extern "C" __declspec(dllexport) #define DLL_API __declspec(dllexport) #else #define DLL_API_C extern "C" __declspec(dllimport) #define DLL_API __declspec(dllimport) #endif //nBgValue = 0/255; block_size = 2048; sigma = 0.0; k = 0.0; min_size = 100; int ImgSegmentBlock(unsigned char* pDataSrc, int width, int height, int nBgValue, unsigned char* pDataDst, int block_size, float sigma, float k, int min_size); //只能接受8位3通道输入,返回值为分块数目,输出连通域的索引从1开始(nLastIndex必须为0) int ImgSegmentBlockMark(unsigned char* pDataSrc, int width, int height, int nBgValue, unsigned int* pDataDst, int block_size, int nLastIndex, float sigma, float k, int min_size);

    cpp文件:

    /* Copyright (C) 2006 Pedro Felzenszwalb This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <cstdio> #include <cstdlib> #include <image.h> #include <misc.h> #include <pnmfile.h> #include "segment-image.h" #include <map> //#define DLLProvider #include "imgseg.h" //参数范围 #define SIGMA_MIN 0.1 #define SIGMA_MAX 0.5 #define K_MIN 5 #define K_MAX 100 #ifndef MIN # define MIN(a,b) ((a) > (b) ? (b) : (a)) #endif #ifndef MAX # define MAX(a,b) ((a) < (b) ? (b) : (a)) #endif void inline CheckParameters(int width, int height, float& sigma, float& k) { if (sigma < 1e-5) { //根据宽高自动设置sigma的值 sigma = MAX(SIGMA_MIN, MIN(SIGMA_MAX, MAX(width, height) / 10000.0)); } if (k < 1e-5) { //根据宽高自动设置k的值 k = MAX(K_MIN, MIN(K_MAX, MAX(width, height) / 50.0)); } } int SegmentPPM(const char* szFilePath, float sigma, float k, int min_size, const char* szDstPath) { if (szFilePath == nullptr) { return -1; } printf("loading input image.\n"); image<rgb> *input = loadPPM(szFilePath); int width = input->width(); int height = input->height(); //CheckParameters(width, height, sigma, k); printf("processing\n"); int num_ccs; image<rgb> *seg = segment_image(input, sigma, k, min_size, &num_ccs); savePPM(seg, szDstPath); printf("got %d components\n", num_ccs); printf("done! uff...thats hard work.\n"); return 0; } int ImgSegmentBlock(unsigned char* pDataSrc, int width, int height, int nBgValue, unsigned char* pDataDst, int block_size, float sigma, float k, int min_size) { if (pDataSrc == nullptr || pDataDst == nullptr) { return -1; } CheckParameters(width, height, sigma, k); int num_ccs = 0; if (block_size <= 0 || width < block_size && height < block_size) { image<rgb> *input = new image<rgb>(width, height); memcpy(input->data, pDataSrc, width * height * 3); printf("processing\n"); image<rgb> *seg = segment_image(input, sigma, k, min_size, &num_ccs); memcpy(pDataDst, seg->data, width * height * 3); printf("got %d components\n", num_ccs); printf("done! uff...thats hard work.\n"); } else { //分块处理当前数据块 int nColIndex = (width - 1) / block_size + 1; //计算列方向上块数 int nRowIndex = (height - 1) / block_size + 1; //计算行方向块数 int nBlockWidth = block_size; //当前块宽度 int nBlockHeight = block_size; //当前块高度 unsigned char* pDataBlock = new unsigned char[nBlockWidth * nBlockHeight * 3](); unsigned char* pDataBlockDst = new unsigned char[nBlockWidth * nBlockHeight * 3](); for (int nRI = 0; nRI < nRowIndex; nRI++) { unsigned char* pRDataSrc = pDataSrc + nRI * block_size * width * 3; unsigned char* pRDataDst = pDataDst + nRI * block_size * width * 3; for (int nCI = 0; nCI < nColIndex; nCI++) { nBlockWidth = block_size; nBlockHeight = block_size; //行列末尾小块处理 if (nCI == nColIndex - 1 && width % block_size != 0)nBlockWidth = (width) % block_size; if (nRI == nRowIndex - 1 && height % block_size != 0)nBlockHeight = (height) % block_size; //得到每一块的数据 unsigned char* pCDataSrc = pRDataSrc + nCI * block_size * 3; unsigned char* pCDataDst = pRDataDst + nCI * block_size * 3; for (size_t j = 0; j < nBlockHeight; ++j) { unsigned char* pSubDataSrc = pCDataSrc + j * width * 3; unsigned char* pSubBlockDataDst = pDataBlock + j * nBlockWidth * 3; memcpy(pSubBlockDataDst, pSubDataSrc, nBlockWidth * 3); } num_ccs += ImgSegmentBlock(pDataBlock, nBlockWidth, nBlockHeight, nBgValue, pDataBlockDst, -1, sigma, k, min_size); //将目标结果覆盖到当前区域 for (size_t j = 0; j < nBlockHeight; ++j) { unsigned char* pSubDataDst = pCDataDst + j * width * 3; unsigned char* pSubBlockDataDst = pDataBlockDst + j * nBlockWidth * 3; memcpy(pSubDataDst, pSubBlockDataDst, nBlockWidth * 3); } } } delete[] pDataBlock; delete[] pDataBlockDst; } return num_ccs; } int ImgSegmentBlockMark(unsigned char* pDataSrc, int width, int height, int nBgValue, unsigned int* pDataDst, int block_size, int nLastIndex, float sigma, float k, int min_size) { if (pDataSrc == nullptr || pDataDst == nullptr) { return -1; } CheckParameters(width, height, sigma, k); int num_ccs = 0; if (block_size <= 0 || width < block_size && height < block_size) { image<rgb> *input = new image<rgb>(width, height); memcpy(input->data, pDataSrc, width * height * 3); printf("processing\n"); universe* u = segment_image(input, sigma, k, min_size); int num_ccs = u->num_sets(); std::map<int, int> mvs; for (size_t j = 0; j < height; ++j) { unsigned int* data = pDataDst + j * width; for (size_t i = 0; i < width; ++i) { int comp = u->find(j * width + i); if (mvs.find(comp) == mvs.end()) { mvs.insert(std::make_pair(comp, ++nLastIndex)); } data[i] = mvs[comp]; } } printf("got %d components\n", num_ccs); printf("done! uff...thats hard work.\n"); delete input; delete u; return num_ccs; } else { //分块处理当前数据块 int nColIndex = (width - 1) / block_size + 1; //计算列方向上块数 int nRowIndex = (height - 1) / block_size + 1; //计算行方向块数 int nBlockWidth = block_size; //当前块宽度 int nBlockHeight = block_size; //当前块高度 unsigned char* pDataBlock = new unsigned char[nBlockWidth * nBlockHeight * 3](); unsigned int* pDataBlockDst = new unsigned int[nBlockWidth * nBlockHeight](); for (int nRI = 0; nRI < nRowIndex; nRI++) { unsigned char* pRDataSrc = pDataSrc + nRI * block_size * width * 3; unsigned int* pRDataDst = pDataDst + nRI * block_size * width; for (int nCI = 0; nCI < nColIndex; nCI++) { nBlockWidth = block_size; nBlockHeight = block_size; //行列末尾小块处理 if (nCI == nColIndex - 1 && width % block_size != 0)nBlockWidth = (width) % block_size; if (nRI == nRowIndex - 1 && height % block_size != 0)nBlockHeight = (height) % block_size; //得到每一块的数据 unsigned char* pCDataSrc = pRDataSrc + nCI * block_size * 3; unsigned int* pCDataDst = pRDataDst + nCI * block_size; for (size_t j = 0; j < nBlockHeight; ++j) { unsigned char* pSubDataSrc = pCDataSrc + j * width * 3; unsigned char* pSubBlockDataDst = pDataBlock + j * nBlockWidth * 3; memcpy(pSubBlockDataDst, pSubDataSrc, nBlockWidth * 3); } nLastIndex += ImgSegmentBlockMark(pDataBlock, nBlockWidth, nBlockHeight, nBgValue, pDataBlockDst, -1, nLastIndex, sigma, k, min_size); //将目标结果覆盖到当前区域 for (size_t j = 0; j < nBlockHeight; ++j) { unsigned int* pSubDataDst = pCDataDst + j * width; unsigned int* pSubBlockDataDst = pDataBlockDst + j * nBlockWidth; memcpy(pSubDataDst, pSubBlockDataDst, nBlockWidth * sizeof(int)); } } } delete[] pDataBlock; delete[] pDataBlockDst; } return nLastIndex; }

    更多的交流,欢迎留言。

    最新回复(0)