First of all I have this image and I want to make an application that can detect images like it and remove the circle (watermark) from it.
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); }
So far what I made is:
bitwise_and
) gives me an image with only that circlebitwise_or
the result of the thresholdMy problem is that any black text on the curved white line inside this circle didn't appear. I tried to remove the color by using the pixel values instead of threshold, but the problem is the same. So any solutions or suggestions?
These are the results:
Photo Stamp Remover is a photo correction tool designed to remove watermark from image. It can also delete date stamps, logos and other undesired objects from the photos. As it has a user-friendly interface, it is very easy to start your removing watermarks.
I'm not sure if the following solution is acceptable in your case. But I think it performs slightly better, and doesn't care about the shape of the watermark.
Remove the strokes using morphological filtering. This should give you a background image.
Calculate the difference image: difference = background - initial, and threshold it: binary = threshold(difference)
Above is a rough description. Code below should explain it better.
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++]; } } }
A Python version of dhanushka's answer
# Import the necessary packages import cv2 import numpy as np def back_rm(filename): # Load the image img = cv2.imread(filename) # Convert the image to grayscale gr = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Make a copy of the grayscale image bg = gr.copy() # Apply morphological transformations for i in range(5): kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2 * i + 1, 2 * i + 1)) bg = cv2.morphologyEx(bg, cv2.MORPH_CLOSE, kernel2) bg = cv2.morphologyEx(bg, cv2.MORPH_OPEN, kernel2) # Subtract the grayscale image from its processed copy dif = cv2.subtract(bg, gr) # Apply thresholding bw = cv2.threshold(dif, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] dark = cv2.threshold(bg, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] # Extract pixels in the dark region darkpix = gr[np.where(dark > 0)] # Threshold the dark region to get the darker pixels inside it darkpix = cv2.threshold(darkpix, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] # Paste the extracted darker pixels in the watermark region bw[np.where(dark > 0)] = darkpix.T cv2.imwrite('final.jpg', bw) back_rm('watermark.jpg')
Here is the final result:
The processing time is very short using numpy
time python back_rm.py real 0m0.391s user 0m0.518s sys 0m0.185s
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With