前言:
在令人討厭的的自動屏保中突然看到一張漂亮的圖片(懂就行!)归斤,就想趕緊按了鍵盤上的截屏鍵痊夭,當(dāng)發(fā)現(xiàn)無法去掉上面的文字。
于是乎脏里,圖像處理的我就和邱邱一起研究如何將其去掉她我。
思路:
該圖片上的文字和特別,特別在其實(shí)白色的迫横。白色——在cv中簡直就是最大的特征——三通道全是255Q荒选!
開始進(jìn)行:將制定文字區(qū)域截取出來员淫,直接上我的嘴子奧西最小值濾波合蔽。
效果:
代碼:
代碼就非常簡單了,使用了兩個函數(shù):(1)最小值濾波介返;(2)區(qū)域截取與復(fù)制
//功能:截取圖像IntImg的指定區(qū)域拴事,區(qū)域?yàn)椋簭模▁_stare,y_stare)坐標(biāo)開始沃斤,截取大小為 x_dustance, y_dustance(x和y方向的尺寸)
//返回:指定區(qū)域已經(jīng)被去掉字符
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;
//設(shè)置畫布繪制區(qū)域并復(fù)制
cv::Rect roi_rect = cv::Rect(x_stare, y_stare, x_dustance, y_dustance);
roi.copyTo(IntImg(roi_rect));//將ert這個很小的區(qū)域圖像,復(fù)制到IntImg這個大圖像中刃宵,具體的復(fù)制坐標(biāo)位置為:roi_rect這個區(qū)域
return IntImg;
}
//功能:最小值濾波__彩色(針對白色字體的去除)
//輸入:彩色圖像衡瓶,最小值濾波的濾波核大小
Mat MinFilterForColor(Mat src, int kernel)
{
vector<Mat>m;
split(src, m); //提取通道信息,但是當(dāng)未把其他通道設(shè)置為0時(shí)顯示為灰度圖牲证,但各通道信息不同
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;
}
調(diào)用方法:
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);
}
寫在最后:
這個過程是非常簡單的哮针,不登大雅之堂,但是其思路和方法值得初學(xué)者思考坦袍。
整個代碼也沒有做任何優(yōu)化十厢,健壯性也沒有測試。