opencv利用投影法进行水平切割和垂直切割

水平投影切割

#include<iostream>
#include <opencv2/opencv.hpp>  
using namespace std;
using namespace cv;
int main()
{
    IplImage * src = cvLoadImage("img1.jpg");
    IplImage *dst = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
    IplImage *img = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
    cvThreshold(src, dst, 100, 255, CV_THRESH_BINARY);
    IplImage* painty = cvCreateImage(cvGetSize(dst), IPL_DEPTH_8U, 1);
    cvZero(painty);
    int* h = new int[dst->height];
    memset(h, 0, dst->height * 4);
    int x, y;
    CvScalar s, t;//可以用来存放4个double数值的数组,一般用来存放像素值(不一定是灰度值哦)的,最多可以存放4个通道的 

    for (y = 0; y<dst->height; y++)
    {
        for (x = 0; x<dst->width; x++)
        {
            s = cvGet2D(dst, y, x);

            if (s.val[0] == 0)
                h[y]++;
        }
    }
    for (y = 0; y<dst->height; y++)
    {
        for (x = 0; x<h[y]; x++)
        {
            t.val[0] = 255;
            cvSet2D(painty, y, x, t);

        }
    }

    vector<Mat> roiList;//用于储存分割出来的每个字符
    int startIndex = 0;//记录进入字符区的索引
    int endIndex = 0;//记录进入空白区域的索引
    bool inBlock = false;//是否遍历到了字符区内
    char szName[30] = { 0 };
    for (int i = 0; i < dst->height; ++i)
    {
        if (!inBlock && h[i] !=0)//进入字符区了
        {
            inBlock = true;
            startIndex = i;
            cout << "startIndex is " << startIndex << endl;
        }
        else if (h[i] ==0 && inBlock)//进入空白区了
        {
            endIndex = i;
            inBlock = false;
            Mat dst1(src, 0);
            Mat roiImg;
            if (endIndex - startIndex>3)
            {
                roiImg = dst1(Range(startIndex, endIndex + 1), Range(0, dst1.cols));
                roiList.push_back(roiImg);
                sprintf(szName, "aa%d.jpg", i);
                imshow(szName, roiImg);
                imwrite(szName, roiImg);
            }           
        }
    }   

    cvNamedWindow("二值图像", 1);
    cvNamedWindow("水平投影", 1);
    cvShowImage("二值图像", dst);
    cvShowImage("水平投影", painty);
    cvWaitKey(0);
    cvDestroyAllWindows();
    cvReleaseImage(&dst);
    cvReleaseImage(&painty);
    return 0;
}

分割原图

水平投影图
这里写图片描述
分割结果图
这里写图片描述

垂直切割

#include<iostream>
#include <opencv2/opencv.hpp>  
using namespace std;
using namespace cv;
int main()
{
    IplImage * src = cvLoadImage("aa146.jpg");
    IplImage *dst = cvCreateImage(cvGetSize(src), 8, 1);
    IplImage *img = cvCreateImage(cvGetSize(src), 8, 1);
    //cvSmooth(src, src, CV_BLUR, 3, 3, 0, 0);
    cvCvtColor(src, img, CV_BGR2GRAY);
    cvThreshold(img, dst, 135, 255, CV_THRESH_BINARY);
    IplImage* paintx = cvCreateImage(cvGetSize(dst), IPL_DEPTH_8U, 1);
    cvZero(paintx);
    int* v = new int[dst->width];   
    memset(v, 0, dst->width * 4);
    int x, y;
    CvScalar s, t;//可以用来存放4个double数值的数组,一般用来存放像素值(不一定是灰度值哦)的,最多可以存放4个通道的  
    //垂直投影  
    for (x = 0; x<dst->width; x++)
    {
        for (y = 0; y<dst->height; y++)
        {
            s = cvGet2D(dst, y, x); //cvGet2D() 的函数原型是 : CvScalar cvGet2D (const CvArr * arr, int idx0, int idx1);   
            //函数返回的是一个CvScalar 容器,其参数中也有两个方向的坐标,  
            //但跟我们平常习惯的坐标不一样的是,idx0代表是的行,即高度,对应于我们平常坐标系的y,  
            //idx1代表的是列,即宽度,对应于我们平常坐标系的x,cvSet2D() 也类似。          
            //printf("area == %lf\n",s);  
            if (s.val[0] == 0)
                v[x]++;
        }
    }

    for (x = 0; x<dst->width; x++)
    {
        for (y = 0; y<v[x]; y++)
        {
            t.val[0] = 255;
            cvSet2D(paintx, y, x, t);
        }
    }
    cvShowImage("原图", src);
    cvShowImage("垂直投影", paintx);
    //分割

    vector<Mat> roiList;//用于储存分割出来的每个字符
    int startIndex = 0;//记录进入字符区的索引
    int endIndex = 0;//记录进入空白区域的索引
    bool inBlock = false;//是否遍历到了字符区内
    char szName[30] = { 0 };
    for (int i = 0; i < dst->width; ++i)
    {
        if (!inBlock && v[i] != 0)//进入字符区了
        {
            inBlock = true;
            startIndex = i;
            cout << "startIndex is " << startIndex << endl;
        }
        else if (v[i] == 0 && inBlock)//进入空白区了
        {
            endIndex = i;
            inBlock = false;
            Mat dst1(src, 0);
            Mat roiImg;
            if (endIndex - startIndex>3)
            {
                roiImg = dst1(Range(0, dst1.rows), Range(startIndex, endIndex + 1));
                roiList.push_back(roiImg);
                sprintf(szName, "aaa%d.jpg", i);
                imshow(szName, roiImg);
                imwrite(szName, roiImg);
            }
        }
    }
    cvWaitKey(0);
    cvDestroyAllWindows();
    cvReleaseImage(&dst);
    cvReleaseImage(&paintx);
    return 0;
}

原图和垂直投影图
这里写图片描述
切割结果图
这里写图片描述


猜你喜欢

转载自blog.csdn.net/lly_117/article/details/79404856