OpenCV 实现图片的水平投影与垂直投影,并进行行

对于印刷体图片来说,进行水平投影和垂直投影可以很快的进行分割,本文就在OpenCV中如何进行水平投影和垂直投影通过代码进行说明。

水平投影:二维图像在y轴上的投影

垂直投影:二维图像在x轴上的投影

由于投影的图像需要进行二值化,本文采用积分二值化的方式,对图片进行处理。

具体代码如下:

//积分二值化
void thresholdIntegral (Mat inputMat, Mat& outputMat)
{

int nRows = inputMat.rows;
    int nCols = inputMat.cols;

// create the integral image
    Mat sumMat;
    integral (inputMat, sumMat);

int S = MAX (nRows, nCols) / 8;
    double T = 0.15;

// perform thresholding
    int s2 = S / 2;
    int x1, y1, x2, y2, count, sum;

int* p_y1, *p_y2;
    uchar* p_inputMat, *p_outputMat;

for (int i = 0; i < nRows; ++i)
    {
        y1 = i - s2;
        y2 = i + s2;

if (y1 < 0)
        {
            y1 = 0;
        }
        if (y2 >= nRows)
        {
            y2 = nRows - 1;
        }

p_y1 = sumMat.ptr<int> (y1);
        p_y2 = sumMat.ptr<int> (y2);
        p_inputMat = inputMat.ptr<uchar> (i);
        p_outputMat = outputMat.ptr<uchar> (i);

for (int j = 0; j < nCols; ++j)
        {
            // set the SxS region
            x1 = j - s2;
            x2 = j + s2;

if (x1 < 0)
            {
                x1 = 0;
            }
            if (x2 >= nCols)
            {
                x2 = nCols - 1;
            }

count = (x2 - x1)* (y2 - y1);

// I(x,y)=s(x2,y2)-s(x1,y2)-s(x2,y1)+s(x1,x1)
            sum = p_y2[x2] - p_y1[x2] - p_y2[x1] + p_y1[x1];

if ((int) (p_inputMat[j] * count) < (int) (sum* (1.0 - T)))
            {
                p_outputMat[j] = 0;
            }
            else
            {
                p_outputMat[j] = 255;
            }
        }
    }
}
//垂直方向投影
void picshadowx (Mat binary)
{
    Mat paintx (binary.size(), CV_8UC1, Scalar (255)); //创建一个全白图片,用作显示

int* blackcout = new int[binary.cols];
    memset (blackcout, 0, binary.cols * 4);

for (int i = 0; i < binary.rows; i++)
    {
        for (int j = 0; j < binary.cols; j++)
        {
            if (binary.at<uchar> (i, j) == 0)
            {
                blackcout[j]++; //垂直投影按列在x轴进行投影
            }
        }
    }
    for (int i = 0; i < binary.cols; i++)
    {
        for (int j = 0; j < blackcout[i]; j++)
        {
            paintx.at<uchar> (binary.rows-1-j, i) = 0; //翻转到下面,便于观看
        }
    }
    delete blackcout;
    imshow ("paintx", paintx);

}
//水平方向投影并行分割
void picshadowy (Mat binary)

  //是否为白色或者黑色根据二值图像的处理得来
    Mat painty (binary.size(), CV_8UC1, Scalar (255)); //初始化为全白
 
  //水平投影
  int* pointcount = new int[binary.rows]; //在二值图片中记录行中特征点的个数
    memset (pointcount, 0, binary.rows * 4);//注意这里需要进行初始化

for (int i = 0; i < binary.rows; i++)
    {
        for (int j = 0; j < binary.cols; j++)
        {
            if (binary.at<uchar> (i, j) == 0)
            {
                pointcount[i]++; //记录每行中黑色点的个数 //水平投影按行在y轴上的投影
            }
        }
    }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/c9d917217e9628a6f22660c3f494ee53.html