gpt4 book ai didi

c++ - 使用 OpenCV 从图像中去除水印

转载 作者:IT老高 更新时间:2023-10-28 14:00:55 30 4
gpt4 key购买 nike

首先我有这张图片,我想制作一个可以检测类似图片并从中删除圆圈(水印)的应用程序。

image has a watermark

int main(){
Mat im1,im2,im3,gray,gray2,result;

im2=imread(" (2).jpg");
namedWindow("x",CV_WINDOW_FREERATIO);
imshow("x",im2);

//converting it to gray
cvtColor(im2,gray,CV_BGR2GRAY);
// creating a new image that will have the cropped ellipse
Mat ElipseImg(im2.rows,im2.cols,CV_8UC1,Scalar(0,0,0));

//detecting the largest circle
GaussianBlur(gray,gray,Size(5,5),0);
vector<Vec3f> circles;
HoughCircles(gray,circles,CV_HOUGH_GRADIENT,1,gray.rows/8,100,100,100,0);

uchar x;
int measure=0;int id=0;
for(int i=0;i<circles.size();i++){
if(cvRound(circles[i][2])>measure && cvRound(circles[i][2])<1000){
measure=cvRound(circles[i][2]);
id=i;
}
}


Point center(cvRound(circles[id][0]),cvRound(circles[id][1]));
int radius=cvRound(circles[id][2]);
circle(im2,center,3,Scalar(0,255,0),-1,8,0);
circle(im2,center,radius,Scalar(0,255,0),2,8,0);
ellipse(ElipseImg,center,Size(radius,radius),0,0,360,Scalar(255,255,255),-1,8);
cout<<"center: "<<center<<" radius: "<<radius<<endl;



Mat res;
bitwise_and(gray,ElipseImg,result);
namedWindow("bitwise and",CV_WINDOW_FREERATIO);
imshow("bitwise and",result);

// trying to estimate the Intensity of the circle for the thresholding
x=result.at<uchar>(cvRound(circles[id][0]+30),cvRound(circles[id][1]));
cout<<(int)x;

//thresholding the output image
threshold(ElipseImg,ElipseImg,(int)x-10,250,CV_THRESH_BINARY);
namedWindow("threshold",CV_WINDOW_FREERATIO);
imshow("threshold",ElipseImg);

// making bitwise_or
bitwise_or(gray,ElipseImg,res);
namedWindow("bitwise or",CV_WINDOW_FREERATIO);
imshow("bitwise or",res);

waitKey(0);
}

到目前为止,我所做的是:

  1. 我把它转成灰度图
  2. 我使用霍夫圆检测最大的圆,然后在新图像中制作一个具有相同半径的圆
  3. 这个带有灰度的新圆圈使用 (bitwise_and) 给了我一个只有那个圆圈的图像
  4. 新图像的阈值
  5. bitwise_or阈值的结果

我的问题是这个圆圈内的弯曲白线上的任何黑色文字都没有出现。我试图通过使用像素值而不是阈值来去除颜色,但问题是一样的。那么有什么解决方案或建议吗?

结果如下: enter image description here

最佳答案

我不确定您的情况是否可以接受以下解决方案。但我认为它表现得稍微好一点,并且不关心水印的形状。

  • 使用形态过滤去除笔画。这应该给你一个背景图像。 background

  • 计算差异图像:差异=背景 - 初始,并对其进行阈值处理:二进制=阈值(差异)

binary1

  • 对背景图片进行阈值化,提取水印覆盖的暗区

dark

  • 从初始图像中,提取水印区域内的像素并对这些像素进行阈值处理,然后将它们粘贴到较早的二值图像中

binary2

以上是粗略的描述。下面的代码应该更好地解释它。

Mat im = [load the color image here];

Mat gr, bg, bw, dark;

cvtColor(im, gr, CV_BGR2GRAY);

// approximate the background
bg = gr.clone();
for (int r = 1; r < 5; r++)
{
Mat kernel2 = getStructuringElement(MORPH_ELLIPSE, Size(2*r+1, 2*r+1));
morphologyEx(bg, bg, CV_MOP_CLOSE, kernel2);
morphologyEx(bg, bg, CV_MOP_OPEN, kernel2);
}

// difference = background - initial
Mat dif = bg - gr;
// threshold the difference image so we get dark letters
threshold(dif, bw, 0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
// threshold the background image so we get dark region
threshold(bg, dark, 0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);

// extract pixels in the dark region
vector<unsigned char> darkpix(countNonZero(dark));
int index = 0;
for (int r = 0; r < dark.rows; r++)
{
for (int c = 0; c < dark.cols; c++)
{
if (dark.at<unsigned char>(r, c))
{
darkpix[index++] = gr.at<unsigned char>(r, c);
}
}
}
// threshold the dark region so we get the darker pixels inside it
threshold(darkpix, darkpix, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);

// paste the extracted darker pixels
index = 0;
for (int r = 0; r < dark.rows; r++)
{
for (int c = 0; c < dark.cols; c++)
{
if (dark.at<unsigned char>(r, c))
{
bw.at<unsigned char>(r, c) = darkpix[index++];
}
}
}

关于c++ - 使用 OpenCV 从图像中去除水印,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32125281/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com