opencv segment conntected characters - python

I am trying to do character detect for handwriting letters.
Upon recognizing itself, I use tesseract or opencv SVM, and works fine till now.
Everything works fine for segment letters until I hit those connected ones.
I use the following code to segment letters:
# -*- coding: utf-8 -*-
import numpy as np
import cv2
# from matplotlib import pyplot as plt
from os.path import dirname, join, basename
import sys
from glob import glob
trainpic=[]
targetdir = dirname(__file__)+'tmporigin'
#print glob(join(dirname(__file__)+'/cat','*.jpg'))
img = {}
debug = True
a_num = 0
for fn in glob(join(targetdir, '*')):
filename = basename(fn)
trainpic.append(cv2.imread(fn, 0))
img_rgb = cv2.imread(fn)
img = cv2.imread(fn, 0)
image_close = cv2.morphologyEx(img_rgb, cv2.MORPH_CLOSE, np.ones((1, 7), np.uint8))
#if debug:
# cv2.imshow('morphology', image_close)
# key = cv2.waitKey(0)
_, contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
samples = np.empty((0, 100))
responses = []
# keys = [i for i in range(48, 58)]
tmp_list = []
tmpcount = 0
for cnt in contours:
print 'contourarea:%s' % cv2.contourArea(cnt)
if cv2.contourArea(cnt) > 130: # 50 300
[x, y, w, h] = cv2.boundingRect(cnt)
print 'boundingRect width:%s' % w
print 'boundingRect height:%s' % h
if h > 28:
cv2.rectangle(img_rgb, (x, y), (x+w, y+h), (0, 0, 255), 2)
roi = img[y:y+h, x:x+w]
roismall = cv2.resize(roi, (45, 55))
if debug:
cv2.imshow('norm', img_rgb)
key = cv2.waitKey(0)
# tmp_list.append(roi)
tmpfilename = fn if tmpcount == 0 else fn.rsplit('.', 1)[0] + '_' + str(tmpcount) + '.png'
cv2.imwrite(tmpfilename, roismall)
tmpcount += 1
else:
print 'contarea less, skip...'
# print img[num].shape
a_num += 1
print '%s images processed' % a_num
So, its fine to handle letters with inter space like this guy(split to D and B):
However, failed to segment connected letters like this:
I googled a lot for connected letters and find related links like these two:
enter link description here
enter link description here
I tried a lot, e.g. morphology dilate, erode, open, close, watershed .etc but didn't fix my problem.
I use opencv 3.2.0 and python 2.7.10 upon my Ubuntu desktop.
Any suggestion is great appreciated.
Thanks.
Wesley

Related

Template matching with updating templates from previous detection

I am trying to write a code where after matching with a given template, the detected part of that frame becomes the template for the next frame.
temp = "image.png"
while True:
try:
_, frame = cap.read()
copy = frame.copy()
w,h=temp.shape[:-1]
res=cv2.matchTemplate(frame,temp,cv2.TM_CCOEFF_NORMED)
threshold=0.75
#try:
loc=np.where(res>=threshold)
print(len(loc))
for pt in zip(*loc[::-1]):
#cv2.rectangle(img,pt,(pt[0]+w,pt[1]+h),(0,255,255),2)
point = pt
cropped_image = copy[point[1]:point[1]+h, point[0]:point[0]+w]
temp = cropped_image #update the template
but after writing this code the template matching is going in totally wrong direction, even though if i remove the "temp = cropped_image" then the cropped_image is actually good.
You can find x,y,w,h of the matched image with cv2.minMaxLoc()
import cv2
src = cv2.imread("source.png", cv2.IMREAD_GRAYSCALE)
templit = cv2.imread("initial_template.png", cv2.IMREAD_GRAYSCALE)
result = cv2.matchTemplate(src, templit, cv2.TM_SQDIFF_NORMED)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(result)
x, y = minLoc
h, w = templit.shape
cropped_img = src[y: y + h, x: x + w]
//do template matching again with cropped_image

Overlay a given image above a list of images

I want to overlay a given image above a list of images and copy all images that fit to one folder what is the best programation language should I use?
Here is example of images I want to overlay the red hat and copy all the images with red hat to ine folder
here is image :
I tried with Python many exmaple but it didn't work
I tired this I found it in this website but it still didn't work:
import cv2
import numpy as np
from matplotlib import pyplot as plt
from PIL import Image
import os, errno
threshold = 0.8 #set threshold
resultsDirectory = 'results'
sourceDirectory = os.fsencode(r'C:\Users\Amir\Desktop\Nouveau dossier (2)\rrr')
templateDirectory = os.fsencode(r'C:\Users\Amir\Desktop\Nouveau dossier (2)\3.png')
detectedCount = 0
for file in os.listdir(sourceDirectory):
filename = os.fsdecode(file)
if filename.endswith(".jpg") or filename.endswith(".png"):
print (filename)
img_rgb = cv2.imread(r'C:\Users\Amir\Desktop\Nouveau dossier (2)\rrr'+filename)
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
for templateFile in os.listdir(templateDirectory):
templateFilename = os.fsdecode(templateFile)
if filename.endswith(".jpg") or filename.endswith(".png"):
template = cv2.imread(r'C:\Users\Amir\Desktop\Nouveau dossier (2)\3.png'+templateFilename,0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
loc = np.where( res >= threshold)
if (len(loc[0])):
detectedCount = detectedCount + 1
for pt in zip(*loc[::-1]):
cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
cv2.imwrite(resultsDirectory+'/res_'+filename+'.png',img_rgb)
print ('/res_'+filename+'.png'+' saved')
# break
print ('detected positive ' + str(detectedCount))
continue
else:
continue

OpenCV error: (-215:Assertion failed) s >= 0 in function 'cv::setSize' in Face Recognition program: Python

I have written two scripts main_program.py and detector.py to do perform face detection and recognition. I first train the classifier then use it recognize faces. But the training isn't happening because the program exits with an error.
here is the code for both the scripts:
For main_program.py :-
import cv2
import os
import numpy as np
import detector as dec
test_img = cv2.imread(r'C:\Users\JasonPC\Desktop\FaceDetection\Test Images\j1.jpg')
faces_detected, gray_img = dec.faceDetect(test_img)
print('Faces Detected: ', faces_detected)
faces, faceID = dec.labels_for_training_data(r'C:\Users\JasonPC\Desktop\FaceDetection\Resources')
face_recognizer = dec.train_classifier(faces, faceID)
name = {0:'Obama', 1:'Trump'}
for faces in faces_detected:
(x, y, w, h) = face
roi_gray = gray_img[y : y + h, x : x + h]
label, confidence = face_recognizer.predict(roi_gray)
confidence('confidence: ', confidence)
print('label: ', label)
dec.draw_rect(test_img, face)
predicted_name = name[label]
dec.put_text(test_img, predicted_name, x, y)
result_img = cv2.resize(test_img, (200, 200))
cv2.imshow('Face Detection', result_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
And here the code for detector.py
import cv2
import os
import numpy as np
def faceDetect(img):
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
classifier = cv2.CascadeClassifier(r'C:\Users\JasonPC\Documents\CodeVault\Python\FaceDetection\Classifiers\haarcascade_frontalface_alt.xml')
# classifier = cv2.CascadeClassifier(r'C:\Users\JasonPC\Documents\CodeVault\Python\FaceRecognition\Classifier.xml')
# val = classifier.load(r'C:\Users\JasonPC\Documents\CodeVault\Python\FaceRecognition\Classifier.xml')
faces = classifier.detectMultiScale(gray_img, scaleFactor = 1.5, minNeighbors = 5 )
return faces, gray_img
def labels_for_training_data(directory):
faces = []
faceID = []
for path, subdirnames, filenames in os.walk(directory):
for filename in filenames:
if filename.startswith("."):
print('Skipping system file...')
continue
id = os.path.basename(path)
img_path = os.path.join(path, filename)
print('img_path: ', img_path)
print('id: ', id)
test_img = cv2.imread(img_path)
if test_img is None:
print('Image is not loaded properly')
continue
faces_rect, gray_img = faceDetect(test_img)
if len(faces_rect) != 1:
continue # since multiple faces has been detected in an single image
(x, y , w, h) = faces_rect[0]
roi_gray = gray_img[y : y + 1, x : x + h]
faces.append(roi_gray)
faceID.append(int(id))
return faces, faceID
def train_classifier(faces, faceID):
face_recognizer = cv2.face.LBPHFaceRecognizer_create()
face_recognizer.train(faces, np.array(faceID))
return face_recognizer
def draw_rect(test_img, face):
(x, y , w, h) = face
cv2.rectangle(test_img, (x, y), (x + w, y + h), (255, 0, 0), thickness = 5)
def put_text(test_img, text, x, y):
cv2.putText(test_img, text, (x, y), cv2.FONT_HERSHEY_DUPLEX, 5, (255,0, 0), 6)
But I am stuck with an error!
Traceback (most recent call last):
File "c:/Users/JasonPC/Desktop/FaceDetection/main_program.py", line
29, in <module>
face_recognizer = dec.train_classifier(faces, faceID)
File "c:\Users\JasonPC\Desktop\FaceDetection\detector.py", line 44,
in train_classifier
face_recognizer.train(faces, np.array(faceID))
cv2.error: OpenCV(4.3.0) C:\projects\opencv-python\opencv\modules\core\src\matrix.cpp:235: error: (-215:Assertion failed) s >= 0 in function 'cv::setSize'
Please help me debug this error!
many many thanks!

Unable to get the output image

i'm fairly new to python and openCV and i have been experimenting with some code that i found online. so thank you in advance for helping
although im using the imshow() function defined in opencv im unable to display the image
from __future__ import division
from __future__ import print_function
import random
import numpy as np
import cv2
def main():
"put img into target img of size imgSize, transpose for TF and normalize gray-values"
img=cv2.imread("C:\\Users\\bnsid\\Desktop\\a01-003-00-02.png", cv2.IMREAD_GRAYSCALE)
imgSize=(128,32)
dataAugmentation = True
if img is None:
img = np.zeros([imgSize[1], imgSize[0]])
# dataaugmentation
if dataAugmentation:
stretch = (random.random() - 0.5) # -0.5 .. +0.5
wStretched = max(int(img.shape[1] * (1 + stretch)), 1) # random width, but at least 1
img = cv2.resize(img, (wStretched, img.shape[0])) # stretch horizontally by factor 0.5 .. 1.5
# create target image and copy sample image into it
(wt, ht) = imgSize
(h, w) = img.shape
fx = w / wt
fy = h / ht
f = max(fx, fy)
newSize = (max(min(wt, int(w / f)), 1), max(min(ht, int(h / f)), 1)) # scale according to f (result at least 1 and at most wt or ht)
img = cv2.resize(img, newSize)
target = np.ones([ht, wt]) * 255
target[0:newSize[1], 0:newSize[0]] = img
# transpose for TF
img = cv2.transpose(target)
# normalize
(m, s) = cv2.meanStdDev(img)
m = m[0][0]
s = s[0][0]
img = img - m
img = img / s if s>0 else img
cv2.imshow('Greyscale_Stretched', img)
k= cv2.waitKey(0) & 0xFF
if k == 27: # wait for ESC key to exit
cv2.destroyAllWindows()
elif k == ord('s'): # wait for 's' key to save and exit
cv2.imwrite('grey.png', img)
cv2.destroyAllWindows()
Just tested your code. You need to call the main() function somewhere. Since you haven't done that, the function is not executed.
simply add main() at the end of the code, and everything works.
def main():
#your code here
print("placeholder")
main()
The main() function you have declared and defined here does not act like the main() entry function in C++. If you would like similar behavior, use this:
def function_name():
print('placeholder')
if __name__ == '__main__':
function_name() #for eg: main()

Irrelevant results with peopledetect.py

I want to detect people in an image. For that I tried to use the code peopledetect.py.
#!/usr/bin/env python
import numpy as np
import cv2
help_message = '''
USAGE: peopledetect.py <image_names> ...
Press any key to continue, ESC to stop.
'''
def inside(r, q):
rx, ry, rw, rh = r
qx, qy, qw, qh = q
return rx > qx and ry > qy and rx + rw < qx + qw and ry + rh < qy + qh
def draw_detections(img, rects, thickness = 1):
for x, y, w, h in rects:
# the HOG detector returns slightly larger rectangles than the real objects.
# so we slightly shrink the rectangles to get a nicer output.
pad_w, pad_h = int(0.15*w), int(0.05*h)
cv2.rectangle(img, (x+pad_w, y+pad_h), (x+w-pad_w, y+h-pad_h), (0, 255, 0), thickness)
if __name__ == '__main__':
import sys
from glob import glob
import itertools as it
print help_message
hog = cv2.HOGDescriptor()
hog.setSVMDetector( cv2.HOGDescriptor_getDefaultPeopleDetector() )
print "hi"
for fn in it.chain(*map(glob, sys.argv[1:])):
print fn, ' - ',
try:
img = cv2.imread(fn)
'''rows,cols,z = img.shape
print rows,cols
rows = float(rows)
cols = float(cols)
#img = cv2.resize(img,None,fx=384.0/rows, fy=256.0/cols, interpolation = cv2.INTER_CUBIC)
print img.shape'''
except:
print 'loading error'
continue
found, w = hog.detectMultiScale(img, winStride=(100,100), padding=(32,32), scale=1.05)
found_filtered = []
for ri, r in enumerate(found):
for qi, q in enumerate(found):
if ri != qi and inside(r, q):
break
else:
found_filtered.append(r)
draw_detections(img, found)
draw_detections(img, found_filtered, 3)
print '%d (%d) found' % (len(found_filtered), len(found))
cv2.imshow('img', img)
ch = 0xFF & cv2.waitKey()
if ch == 27:
break
cv2.destroyAllWindows()
But it is showing irrelevant results(not detecting people in some cases and detecting objects(non-people) in some cases.What changes should I do in the code?

Categories

Resources