title: How can I detect an object in image frame using OpenCV?
body: <p>I am developing a rover using Raspberry Pi , that will sweep a room and pick up objects fallen on the ground . To detect the object , I am using a reference Image , that is taken right at the start of the rover's operation , and an Image (new Image) that is clicked every 10 seconds . To determine if there is a change in the image frame , I do a image subtraction between the reference image and the new image . If any difference is found , it'll draw a contour around it , and if the contour area is greater than a certain threshold (cautionary step) , it concludes that there exists an object . </p>
  
  <p>I am using the following code -</p>
  
  <pre><code>import numpy as np
  import cv2,time
  
  img=cv2.imread("object1.jpg")
  img1=cv2.imread("object2.jpg")
  sub=cv2.subtract(img,img1)
  
  gray=cv2.cvtColor(sub,cv2.COLOR_BGR2GRAY)
  blur = cv2.GaussianBlur(gray,(3,3),0)
  _, contours, _= cv2.findContours(blur,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
  c=max(contours,key=cv2.contourArea)
  print(cv2.contourArea(c))
  
  if cv2.contourArea&gt;20000:
     print("Object detected !")
  </code></pre>
  
  <p>The above code just uses 2 images to calculate their difference and determine if there is an object present .Please note that  I have not posted the original code here that I will be using in my project .</p>
  
  <p>Now , the above code works fine for very controlled situations, say ,when the image background is very constant or there is no presence of shadow in it . But considering the fact that the rover will be moving around in the room , and there are chances that the lighting variations might trigger a false object detection , even if there is no real object in the frame . The difference might be triggered due to false contouring from shadow effects . </p>
  
  <p>I want to know , if there is any other way of achieving this object detection without doing foreground/background image subtraction . I have also considered using a ultrasonic sensor to detect the object's presence , however that is not a very reliable option . I would prefer a Image processing based solution .</p>
  
  <p>Thank you .</p>
  
  <p>==========================================================================</p>
  
  <p><strong>EDIT 1 -</strong>  </p>
  
  <p>So , I decided to change the algorithm a bit . I have done thresholding on both the foreground and background Images and then performed absdiff between the binary images , to obtain any frame change(object) . 
  The code is as follows - </p>
  
  <pre><code>import numpy as np
  import cv2,time
  
  img1=cv2.imread("back.jpeg")
  blur1 = cv2.GaussianBlur(img1,(5,5),0)
  gray1=cv2.cvtColor(blur1,cv2.COLOR_BGR2GRAY)
  ret,thresh1 = cv2.threshold(gray1,65,255,cv2.THRESH_BINARY_INV)
  
  img2=cv2.imread("front.jpeg")
  blur2 = cv2.GaussianBlur(img2,(5,5),0)
  gray2=cv2.cvtColor(blur2,cv2.COLOR_BGR2GRAY)
  ret,thresh2 = cv2.threshold(gray2,65,255,cv2.THRESH_BINARY_INV)
  
  diff=cv2.absdiff(thresh2,thresh1)
  diff=cv2.bitwise_xor(diff,thresh1)
  
  kernel = np.ones((2,2),np.uint8)
  diff=cv2.erode(diff,kernel,iterations = 1)
  diff=cv2.dilate(diff,kernel,iterations = 8)
  
  _, contours, _= cv2.findContours(diff,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
  c=max(contours,key=cv2.contourArea)
  x,y,w,h = cv2.boundingRect(c)
  cv2.rectangle(diff,(x,y),(x+w,y+h),(125,125,125),2)
  
  
  cv2.imshow("thresh",diff)
  cv2.waitKey(0)
  </code></pre>
  
  <p>"absdiff" is followed by Erosion and Dilation . After that , I find the largest contour and determine if there is an object . The images used in the algorithm are as follows -</p>
  
  <ol>
  <li><p>Background Image -
  <a href="https://i.stack.imgur.com/3uRGM.jpg" rel="nofollow noreferrer">Background Image</a></p></li>
  <li><p>Foreground Image - <a href="https://i.stack.imgur.com/fC8xG.jpg" rel="nofollow noreferrer">Foreground image </a></p></li>
  <li><p>Foreground Threshold - <a href="https://i.stack.imgur.com/OmW5k.png" rel="nofollow noreferrer">Foreground threshold Image</a></p></li>
  <li><p>Background Threshold - <a href="https://i.stack.imgur.com/ogQ3w.png" rel="nofollow noreferrer">Background threshold Image</a></p></li>
  <li><p>Difference Image - <a href="https://i.stack.imgur.com/iYA9r.png" rel="nofollow noreferrer">Final Image with contour and its boundary .</a></p></li>
  </ol>
  
  <p>As you can see , the detection works fine . I have few other foreground images which I have used to test the algorithm . They have given satisfactory results .I wanted to know , if there is any other way of achieving the same result with better efficiency .</p>
  
  <p>PS-  All of the foreground Images have been taken with Flash ON . I have tried with Flash OFF but there seems to exist a lot of noise in the image .</p>
  
  <p>=============================================================</p>
  
  <p><strong>EDIT 2-</strong></p>
  
  <p>Performance of the algo using other pictures - </p>
  
  <p>Note :- The Background Image has remained same .</p>
  
  <ol>
  <li>Object 1 - <a href="https://i.stack.imgur.com/pzupl.jpg" rel="nofollow noreferrer">Foreground Image 1</a></li>
  <li>Object 1 Detection - <a href="https://i.stack.imgur.com/3KMxm.png" rel="nofollow noreferrer">Foreground Image 1 Result</a></li>
  </ol>