0

I am working on a project that recognize 7 segment numbers on the device.

Here is the code I have


import cv2
import numpy as np
from matplotlib import pyplot as plt
import urllib
from urllib import request 
import imutils


#I used this to connect the webcam app on the tablet 
url='http://192.168.0.121:8080/shot.jpg'
tW=52
tH=98
while True:

    
    
    imgResp = urllib.request.urlopen(url)

    
    imgNp = np.array(bytearray(imgResp.read()),dtype=np.uint8)

    
    frame = cv2.imdecode(imgNp,-1)

   
    height, width = frame.shape[:2]

   
    top_left_x = int (width / 4)
    top_left_y = int ((height / 2) + (height / 6))
    bottom_right_x = int ((width / 4) +(width/5))
    bottom_right_y = int ((height / 2) - (height / 55))

   
    cv2.rectangle(frame, (top_left_x,top_left_y), (bottom_right_x,bottom_right_y), 255, 3)
    cv2.imshow('user_window',frame)

     
    cropped = frame[bottom_right_y:top_left_y , top_left_x:bottom_right_x]


    
    cv2.imshow('cropped',cropped)

   
    gray = cv2.cvtColor(cropped, cv2.COLOR_BGR2GRAY)
  
    blur = cv2.GaussianBlur(gray, (5, 5), 0)
 
    canny = cv2.Canny(blur, 10, 70)
 
    ret, mask = cv2.threshold(canny, 70, 255, cv2.THRESH_BINARY)

    cv2.imshow('mask',mask)



    



   

       
    methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED']
    found=None
    detected_number=None
    for meth in methods: 
        print(meth)
        
     
        for a in range(0,10):
          
            
          
            templatepath = ('C:\\Users\\USER\\Desktop\\test\\verniersegment\\'+str(a)+'vernier.png') # trainImage
           
            template =  cv2.imread(templatepath,1) # trainImage
            print('비교하는 숫자',a)
            
            
           
            template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
            templateBinary = cv2.threshold(template, 84, 255, cv2.THRESH_BINARY)[1]
          
            template = cv2.Canny(templateBinary, 50, 200)
         
            (tH, tW) = template.shape[:2]
           
            cv2.imshow("Template", template)
          
          
           
            for scale in np.linspace (0.2,1.0,num=10)[::-1]:
               
                resized=imutils.resize(mask,width=int(mask.shape[1]*scale) )
              
                r=float(resized.shape[1]/mask.shape[1])
              

               
                cv2.imshow('resized',resized)
               

      
                if resized.shape[0]<tH or resized.shape[1]<tW:
                    print("비교이미지가 template보다 작아짐 ")
                    break
                 
                method=eval(meth)
                #matchtemplate함수로 사이즈가 바뀐 부분 ,template을 method방식으로 비교한다
                threshold = 0.8
                compare = cv2.matchTemplate(resized,template,method)
                
                    
              
                (minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(compare)

              
                clone = np.dstack([resized, resized, resized])
                #cv2.rectangle(clone, (maxLoc[0], maxLoc[1]),(maxLoc[0] + tW, maxLoc[1] + tH), (0, 0, 255), 2)
               

 
                if found is None or maxVal > found[0]:
                    maxVal2=maxVal
                    found = (maxVal2, maxLoc, r,a)
                 
                    
          
                maxLoc=found[1]
            
                r=found[2]
                (startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r))
                (endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r))
             
                if maxVal2>7000000:
                    cv2.rectangle(mask, (startX, startY), (endX, endY), (255,0, 0), 2)
              
        if maxVal2>5000000:
            cv2.putText(mask,str(found[3]),(startX+10,startY+10), cv2.FONT_HERSHEY_COMPLEX, 2 ,(255,0,0), 2)

    cv2.imshow("Finalized", mask)
    


    if cv2.waitKey(1) == 13: 
        break

cv2.destroyAllWindows()   


Right now, the output is the live video with the rectangle draw on the dtected number. Here is the link to the output video I uploaded on youtube to post here.

output video

The video livestream is not smooth and stopping , and I would like to know how many frames are being processed in a second, so that I can make the output livestream smooth.

I tried manual function to count the frames

def count_frames_manual(video):
    # initialize the total number of frames read
    total = 0
    # loop over the frames of the video
    while True:
        # grab the current frame
        (grabbed, frame) = video.read()

        # check to see if we have reached the end of the
        # video
        if not grabbed:
            break
        # increment the total number of frames read
        total += 1
        return total
    # return the total number of frames in the

print(count_frames_manual(mask))

But when I run the function, I have the following error

AttributeError                            Traceback (most recent call last)
<ipython-input-9-dd97690639f7> in <module>
----> 1 print(count_frames_manual(mask))

<ipython-input-8-ab227eb24e08> in count_frames_manual(video)
      5     while True:
      6         # grab the current frame
----> 7         (grabbed, frame) = video.read()
      8 
      9         # check to see if we have reached the end of the

AttributeError: 'numpy.ndarray' object has no attribute 'read'

Seems like mask is a NumPy object and I am not sure how to proceed to count the frames in this case.

Please help.

And if there is a way to make the live steam smoother, please let me know too!

Thanks ahead!

Narae
  • 59
  • 1
  • 10

2 Answers2

0

whow, i see no way this could run smoothly. You need to refactor your code, like, totally; and preferentially use local camera. Also matchTemplate is probably not a good choice for pattern recognition both because it`s very sensitive to all transformations and noice and because it is very slow.

to measure fps place this at the beginning of the file

import time
fps = 0
tau = time.time()

and this near opencv message dispatch callback

now = time.time()
if now > tau:  # avoid div0
    fps = (fps*9 +1/(now-tau))/10
tau = now
print(fps)

if cv2.waitKey(1) == 13: 
    break
JVod
  • 151
  • 5
0

The way to measure fps is described in this question: fps - how to divide count by time function to determine fps

With respect to making the video smoother try to resize the images before the canny and gauassian filters to reduce the computational cost, this to a point where not much information is lost.

You can try another edge detection algorithm like the laplacian operator or sobel filter, you can also use high pass filters (kernel with positive values towards the center and negative coefficients towards the periphery) these filters sacrifice precision in exchange of better times. Finally I recommend a c++ implementation to get faster processing.

Andrewgmz
  • 355
  • 3
  • 11