Удаление водяного знака из изображения с помощью opencv
Прежде всего, у меня есть это изображение, и я хочу создать приложение, которое может обнаружить такие изображения и удалить из него круг (водяной знак).
![изображение имеет водяной знак]()
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);
}
Пока что я сделал:
- Я конвертирую его в оттенки серого
- Я обнаруживаю самый большой круг, используя круги hough, а затем создаю круг с таким же радиусом в новом изображении
- Этот новый круг с серого цвета с использованием (
bitwise_and
) дает мне изображение только с этим кругом
- Порог нового изображения
-
bitwise_or
результат порога
Моя проблема в том, что любой черный текст на искривленной белой линии внутри этого круга не появился. Я попытался удалить цвет, используя значения пикселей вместо порога, но проблема такая же, как и любые решения или предложения?
Вот результаты:
![введите описание изображения здесь]()
Ответы
Ответ 1
Я не уверен, что в вашем случае приемлемо следующее решение. Но я думаю, что он работает немного лучше и не заботится о форме водяного знака.
-
Удалите штрихи с помощью морфологической фильтрации. Это должно дать вам фоновое изображение.
![background]()
-
Вычислить разностное изображение: разность = фон - начальная и пороговое значение: двоичный = порог (разность)
![binary1]()
- Порог фонового изображения и извлечение темной области, покрытой водяным знаком
![темный]()
- Из исходного изображения извлеките пиксели в области водяного знака и установите порог этих пикселей, затем вставьте их в более раннее двоичное изображение.
![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++];
}
}
}