OpenCV图像处理(13)——指定区域截取和指定区域复制

前言:
在令人讨厌的的自动屏保中突然看到一张漂亮的图片(懂就行!),就想赶紧按了键盘上的截屏键,当发现无法去掉上面的文字。
于是乎,图像处理的我就和邱邱一起研究如何将其去掉。
思路:
该图片上的文字和特别,特别在其实白色的。白色——在cv中简直就是最大的特征——三通道全是255!!
开始进行:将制定文字区域截取出来,直接上我的嘴子奥西最小值滤波。
效果:

带有文字的图像↑
去掉文字的图像↑

代码:
代码就非常简单了,使用了两个函数:(1)最小值滤波;(2)区域截取与复制

//功能:截取图像IntImg的指定区域,区域为:从(x_stare,y_stare)坐标开始,截取大小为 x_dustance,   y_dustance(x和y方向的尺寸)
//返回:指定区域已经被去掉字符
Mat FilerMinEraseTxt(Mat IntImg, int x_stare, int y_stare, int x_dustance, int y_dustance)
{
    auto rect = cv::Rect(x_stare,  y_stare,  x_dustance,  y_dustance );//( 1107.291)
    Mat image_roi = IntImg(rect);
    Mat ert = MinFilterForColor(image_roi, 5);
    Mat roi = ert;
    //设置画布绘制区域并复制
    cv::Rect roi_rect = cv::Rect(x_stare, y_stare, x_dustance, y_dustance);
    roi.copyTo(IntImg(roi_rect));//将ert这个很小的区域图像,复制到IntImg这个大图像中,具体的复制坐标位置为:roi_rect这个区域
    return IntImg;
}
//功能:最小值滤波__彩色(针对白色字体的去除)
//输入:彩色图像,最小值滤波的滤波核大小
Mat MinFilterForColor(Mat src, int kernel)
{
    vector<Mat>m;
    split(src, m); //提取通道信息,但是当未把其他通道设置为0时显示为灰度图,但各通道信息不同
    Mat R = m[0].clone();
    Mat G = m[1].clone();
    Mat B = m[2].clone();

    int r = (kernel - 1) / 2;
    Mat dst(src.size(), CV_8UC1);
    Mat dst1(src.size(), CV_8UC1);
    Mat dst2(src.size(), CV_8UC1);
    //for (int p=0;p<2;p++)
    {
        Mat dst_ex;

        copyMakeBorder(R, dst_ex, r, r, r, r, BORDER_CONSTANT, Scalar(255));
        for (int i = r; i < dst_ex.rows - r; i++)
        {
            for (int j = r; j < dst_ex.cols - r; j++)
            {
                int minVal = dst_ex.at<uchar>(i, j);
                for (int s = -r; s < r + 1; s++)
                {
                    for (int t = -r; t < r + 1; t++)
                    {
                        if (dst_ex.at<uchar>(i + s, j + t) < minVal)
                        {
                            minVal = dst_ex.at<uchar>(i + s, j + t);
                        }
                    }
                }
                dst.at<uchar>(i - r, j - r) = minVal;
            }
        }
    }

    //for (int p=0;p<2;p++)
    {
        Mat dst_ex;

        copyMakeBorder(G, dst_ex, r, r, r, r, BORDER_CONSTANT, Scalar(255));
        for (int i = r; i < dst_ex.rows - r; i++)
        {
            for (int j = r; j < dst_ex.cols - r; j++)
            {
                int minVal = dst_ex.at<uchar>(i, j);
                for (int s = -r; s < r + 1; s++)
                {
                    for (int t = -r; t < r + 1; t++)
                    {
                        if (dst_ex.at<uchar>(i + s, j + t) < minVal)
                        {
                            minVal = dst_ex.at<uchar>(i + s, j + t);
                        }
                    }
                }
                dst1.at<uchar>(i - r, j - r) = minVal;
            }
        }
    }

    //for (int p=0;p<2;p++)
    {
        Mat dst_ex;

        copyMakeBorder(B, dst_ex, r, r, r, r, BORDER_CONSTANT, Scalar(255));
        for (int i = r; i < dst_ex.rows - r; i++)
        {
            for (int j = r; j < dst_ex.cols - r; j++)
            {
                int minVal = dst_ex.at<uchar>(i, j);
                for (int s = -r; s < r + 1; s++)
                {
                    for (int t = -r; t < r + 1; t++)
                    {
                        if (dst_ex.at<uchar>(i + s, j + t) < minVal)
                        {
                            minVal = dst_ex.at<uchar>(i + s, j + t);
                        }
                    }
                }
                dst2.at<uchar>(i - r, j - r) = minVal;
            }
        }
    }
    vector<Mat>mn;
    mn.push_back(dst);
    mn.push_back(dst1);
    mn.push_back(dst2);
    Mat Rchannels;
    merge(mn, Rchannels);
    return Rchannels;
}

调用方法:

int main() 
{
    Mat src1 = cv::imread("C:\\Users\\Administrator\\Downloads\\11.bmp");
    imshow("含有文字图像", src1);
    Mat r= FilerMinEraseTxt(src1, 827, 267, 200, 24);
    Mat r1 = FilerMinEraseTxt(r, 1026, 268, 100, 24);
    Mat r2 = FilerMinEraseTxt(r1, 907, 314, 1041 - 907, 338 - 314);
    imshow("去掉文字图像",r2);
    waitKey(0);
}

写在最后:
这个过程是非常简单的,不登大雅之堂,但是其思路和方法值得初学者思考。
整个代码也没有做任何优化,健壮性也没有测试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

rexinx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值