opencv

2015-08-20 11 views
41

का उपयोग कर किसी छवि से वॉटरमार्क को हटाकर सबसे पहले मेरे पास यह छवि है और मैं ऐसा एप्लिकेशन बनाना चाहता हूं जो इस तरह की छवियों का पता लगा सके और उससे सर्कल (वॉटरमार्क) को हटा सके।opencv

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. स्केल के लिए मैं hough हलकों का उपयोग कर और उसके बाद में एक ही त्रिज्या के साथ एक चक्र बनाने के सबसे बड़े वृत्त का पता लगाने के एक नई छवि
  3. ग्रेस्केल वाले (bitwise_and) का उपयोग करके यह नया सर्कल मुझे केवल उस सर्कल के साथ एक छवि दें
  4. थ्रेसहोल्ड कि नई छवि
  5. bitwise_or सीमा

मेरे समस्या यह है कि इस चक्र के अंदर घुमावदार सफेद लाइन पर किसी भी काले पाठ प्रकट नहीं किया था है का परिणाम है। मैंने थ्रेसहोल्ड के बजाय पिक्सेल मानों का उपयोग कर रंग को हटाने की कोशिश की लेकिन समस्या एक ही समाधान या सुझाव है? enter image description here

उत्तर

34

मुझे यकीन है कि अगर निम्नलिखित समाधान अपने मामले में स्वीकार्य है नहीं कर रहा हूँ:

ये परिणाम हैं। लेकिन मुझे लगता है कि यह थोड़ा बेहतर प्रदर्शन करता है, और वॉटरमार्क के आकार की परवाह नहीं करता है।

  • morphological फ़िल्टरिंग का उपयोग कर स्ट्रोक निकालें। यह आपको एक पृष्ठभूमि छवि देना चाहिए। 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++]; 
     } 
    } 
} 
+0

बहुत बढ़िया है, यह बहुत अच्छी तरह से काम, लेकिन मैं गहरे रंग पृष्ठों के साथ समस्या है - गहरे रंग वॉटरमार्क - यह सिर्फ इसलिए यह अंत में किया कुछ भी नहीं की तरह है BW छवि के लिए पूरे वॉटरमार्क नकल, मैं ऐसा ही कुछ के साथ कैसे पेश कर सकते हैं ? –

+1

मध्यवर्ती छवियों की जांच करें: ** अंतर **, ** पृष्ठभूमि **, ** वॉटरमार्क मास्क ** और ** इंटरमीडिएट बाइनरी **। यहां हम ओत्सु विधि का उपयोग करते हैं, इसलिए थ्रेसहोल्डिंग के अधीन छवियां बेहतर थीं। आप देख सकते हैं कि वॉटरमार्क के अंदर के अक्षरों को वॉटरमार्क के एक हिस्से को फसल करके अपेक्षित रूप से विभाजित किया गया है जिसमें टेक्स्ट शामिल है और ओत्सु थ्रेसहोल्डिंग को लागू करना है। यह CV_THRESH_BINARY बनाम CV_THRESH_BINARY_INV का मामला भी हो सकता है। – dhanushka

+0

@dhanushka कृपया कोई भी वेक्टर लूपिंग पार्ट के लिए जावा कोड के साथ मदद कर सकता है। मुझे जावा में कुछ समतुल्य नहीं मिल रहा है। मैंने यहां प्रश्न पोस्ट किया -> http://answers.opencv.org/question/130997/how-to-parse-a-binary-image-pixel-by-pixel-in-java-open-cv/ –

 संबंधित मुद्दे