10

私は次のような画像を持っています:

ソース

数字の周りの黒い行と列を削除したい。だから私は結果が次のようになることを望みます:

出力

私はこれを試してみます:

void findX(IplImage* imgSrc,int* min, int* max){
    int i;
    int minFound=0;
    CvMat data;
    CvScalar maxVal=cvRealScalar(imgSrc->width * 255);
    CvScalar val=cvRealScalar(0);
    //For each col sum, if sum < width*255 then we find the min
    //then continue to end to search the max, if sum< width*255 then is new max
    for (i=0; i< imgSrc->width; i++){
        cvGetCol(imgSrc, &data, i);
        val= cvSum(&data);
        if(val.val[0] < maxVal.val[0]){
            *max= i;
            if(!minFound){
                *min= i;
                minFound= 1;
            }
        }
    }
}

void findY(IplImage* imgSrc,int* min, int* max){
    int i;
    int minFound=0;
    CvMat data;
    CvScalar maxVal=cvRealScalar(imgSrc->width * 255);
    CvScalar val=cvRealScalar(0);
    //For each col sum, if sum < width*255 then we find the min
    //then continue to end to search the max, if sum< width*255 then is new max
    for (i=0; i< imgSrc->height; i++){
        cvGetRow(imgSrc, &data, i);
        val= cvSum(&data);
        if(val.val[0] < maxVal.val[0]){
            *max=i;
            if(!minFound){
                *min= i;
                minFound= 1;
            }
        }
    }
}
CvRect findBB(IplImage* imgSrc){
    CvRect aux;
    int xmin, xmax, ymin, ymax;
    xmin=xmax=ymin=ymax=0;

    findX(imgSrc, &xmin, &xmax);
    findY(imgSrc, &ymin, &ymax);

    aux=cvRect(xmin, ymin, xmax-xmin, ymax-ymin);

    //printf("BB: %d,%d - %d,%d\n", aux.x, aux.y, aux.width, aux.height);

    return aux;

}

だから私は使用します:

IplImage *my_image = cvLoad....
CvRect bb = findBB(my_image);
IplImage *new_image = cvCreateImage(cvSize(bb.width,bb.height), my_image->depth, 1);
cvShowImage("test",new_image);

それはうまく機能しません。新しい画像に黒い行または列があり、それらが存在するかどうかを確認しようとします。私に何ができる?誰かが私を助けることができますか?(私の英語はごめんなさい!)

4

1 に答える 1

24

これを行う1つの方法は、次の画像に示すように、バウンディングボックス手法を実行して数字を検出することです。

ここに画像の説明を入力してください

あなたの画像はすでに処理されているので、私が使用するバウンディングボックスのテクニックははるかに簡単です。

その手順の後、実際に行う必要があるのは、元の画像のROI(関心領域)をボックスで定義された領域に設定して、トリミング効果を実現し、オブジェクトを分離することです。

ここに画像の説明を入力してください

結果の画像では、境界線に白ではないピクセルの行/列が1つ余分にあることに注意してください。まあ、彼らも黒ではありません。これは、画像を白黒に2値化するためのしきい値メソッドを実行しなかったためです。以下のコードは、画像のグレースケールバージョンで実行されているバウンディングボックス手法を示しています。

これは、あなたが望むものを達成するためのロードマップです。教育目的で、OpenCVのC++インターフェイスを使用して作成したコードを共有しています。あなたはそれをCインターフェースに変換できると確信しています。

#include <cv.h>
#include <highgui.h>

#include <vector>


int main(int argc, char* argv[])
{
    cv::Mat img = cv::imread(argv[1]);

    // Convert RGB Mat to GRAY
    cv::Mat gray;
    cv::cvtColor(img, gray, CV_BGR2GRAY);

    // Store the set of points in the image before assembling the bounding box
    std::vector<cv::Point> points;
    cv::Mat_<uchar>::iterator it = gray.begin<uchar>();
    cv::Mat_<uchar>::iterator end = gray.end<uchar>();
    for (; it != end; ++it)
    {
        if (*it) points.push_back(it.pos());
    }

    // Compute minimal bounding box
    cv::RotatedRect box = cv::minAreaRect(cv::Mat(points));

// Draw bounding box in the original image (debug purposes)
//cv::Point2f vertices[4];
//box.points(vertices);
//for (int i = 0; i < 4; ++i)
//{
        //cv::line(img, vertices[i], vertices[(i + 1) % 4], cv::Scalar(0, 255, 0), 1, CV_AA);
//}
//cv::imshow("box", img);
//cv::imwrite("box.png", img);

    // Set Region of Interest to the area defined by the box
    cv::Rect roi;
    roi.x = box.center.x - (box.size.width / 2);
    roi.y = box.center.y - (box.size.height / 2);
    roi.width = box.size.width;
    roi.height = box.size.height;

    // Crop the original image to the defined ROI
    cv::Mat crop = img(roi);
    cv::imshow("crop", crop);

    cv::imwrite("cropped.png", crop);
    cvWaitKey(0);

    return 0;
}
于 2012-04-25T14:35:10.903 に答える