Related
my project uses object detection by pixel color to identify some things, and I would like the mouse to click automatically with left mouse button when the object that was identified passes over my mouse cursor, how do I do that ? preferably using mouse_event
import time
import win32api
from win32gui import GetDC
from PIL import ImageGrab
import numpy as np
import overlay
def filter_detection_result(matrix, result):
mask = np.isin(matrix, result)
detection_matrix = np.zeros(matrix.shape, dtype=int)
np.place(detection_matrix, mask, result)
return detection_matrix
def rgb_2_int(rgb):
rgb_int = rgb[0]
rgb_int = (rgb_int << 8) + rgb[1]
rgb_int = (rgb_int << 8) + rgb[2]
return rgb_int
def img_2_matrix(img):
rgb_matrix = np.asarray(img).reshape((radius * 2) ** 2, 3)
int_matrix = np.array(list(map(rgb_2_int, rgb_matrix)))
return int_matrix.reshape((radius * 2), (radius * 2))
def detection(field_of_view):
matrix = img_2_matrix(ImageGrab.grab(field_of_view))
result = np.asarray(np.intersect1d(matrix, config))
if result.size >= 120:
detected_matrix = filter_detection_result(matrix, result)
i, j = np.where(detected_matrix != 0)
print(i)
_overlay.create_box(fov, win32api.RGB(255, 255, 255))
_overlay = overlay.Overlay(GetDC(0))
radius = 20
try:
config = np.loadtxt('config.txt', dtype=int, delimiter='\n')
print('[+] loaded')
except Exception as err:
print(err)
while True:
x, y = win32api.GetCursorPos()
fov = (x - radius, y - radius, x + radius, y + radius)
detection(fov)
time.sleep(.15)
while doing image stitching code in google colab I got an error can anyone help how to resolve it?
ERROR: File "<ipython-input-12-7c271414318b>", line 58
def filter_matches(self, matches, ratio = 0.75):
^
IndentationError: unindent does not match any outer indentation level
CODE:
import os
import sys
import cv2
import math
import numpy as np
import utils
from numpy import linalg
class AlignImagesRansac(object):
def _init_(self, image_dir, key_frame, output_dir, img_filter=None):
'''
image_dir: 'C:\Users\Hamza Ahmed\Desktop\auto' containing all images
key_frame: 'C:\Users\Hamza Ahmed\Desktop\auto\c.jpg' of the base image
output_dir: 'C:\Users\Hamza Ahmed\Desktop\auto' where to save output images
optional:
img_filter = 'JPG'; None->Take all images
'''
self.key_frame_file = os.path.split(key_frame)[-1]
self.output_dir = output_dir
# Open the directory given in the arguments
self.dir_list = []
try:
self.dir_list = os.listdir(image_dir)
if img_filter:
# remove all files that doen't end with .[image_filter]
self.dir_list = filter(lambda x: x.find(img_filter) > -1, self.dir_list)
try: #remove Thumbs.db, is existent (windows only)
self.dir_list.remove('Thumbs.db')
except ValueError:
pass
except:
print >> sys.stderr, ("Unable to open directory: %s" % image_dir)
sys.exit(-1)
self.dir_list = map(lambda x: os.path.join(image_dir, x), self.dir_list)
self.dir_list = filter(lambda x: x != key_frame, self.dir_list)
base_img_rgb = cv2.imread(key_frame)
if base_img_rgb == None:
raise IOError("%s doesn't exist" %key_frame)
# utils.showImage(base_img_rgb, scale=(0.2, 0.2), timeout=0)
# cv2.destroyAllWindows()
final_img = self.stitchImages(base_img_rgb, 0)
def filter_matches(self, matches, ratio = 0.75):
filtered_matches = []
for m in matches:
if len(m) == 2 and m[0].distance < m[1].distance * ratio:
filtered_matches.append(m[0])
return filtered_matches
def imageDistance(self, matches):
sumDistance = 0.0
for match in matches:
sumDistance += match.distance
return sumDistance
def findDimensions(self, image, homography):
base_p1 = np.ones(3, np.float32)
base_p2 = np.ones(3, np.float32)
base_p3 = np.ones(3, np.float32)
base_p4 = np.ones(3, np.float32)
(y, x) = image.shape[:2]
base_p1[:2] = [0,0]
base_p2[:2] = [x,0]
base_p3[:2] = [0,y]
base_p4[:2] = [x,y]
max_x = None
max_y = None
min_x = None
min_y = None
for pt in [base_p1, base_p2, base_p3, base_p4]:
hp = np.matrix(homography, np.float32) * np.matrix(pt, np.float32).T
hp_arr = np.array(hp, np.float32)
normal_pt = np.array([hp_arr[0]/hp_arr[2], hp_arr[1]/hp_arr[2]], np.float32)
if ( max_x == None or normal_pt[0,0] > max_x ):
max_x = normal_pt[0,0]
if ( max_y == None or normal_pt[1,0] > max_y ):
max_y = normal_pt[1,0]
if ( min_x == None or normal_pt[0,0] < min_x ):
min_x = normal_pt[0,0]
if ( min_y == None or normal_pt[1,0] < min_y ):
min_y = normal_pt[1,0]
min_x = min(0, min_x)
min_y = min(0, min_y)
return (min_x, min_y, max_x, max_y)
def stitchImages(self, base_img_rgb, round=0):
if ( len(self.dir_list) < 1 ):
return base_img_rgb
# print base_img_rgb.channels()
# if(image.channels()==1)
# { /* Grayscale */ }
# else if (image.channels==4)
# { /* ARGB or RGBA image */
base_img = cv2.GaussianBlur(cv2.cvtColor(base_img_rgb,cv2.COLOR_BGR2GRAY), (5,5), 0)
# Use the SIFT feature detector
detector = cv2.SIFT()
# Find key points in base image for motion estimation
base_features, base_descs = detector.detectAndCompute(base_img, None)
# Create new key point list
# key_points = []
# for kp in base_features:
# key_points.append((int(kp.pt[0]),int(kp.pt[1])))
# utils.showImage(base_img, key_points, scale=(0.2, 0.2), timeout=0)
# cv2.destroyAllWindows()
# Parameters for nearest-neighbor matching
FLANN_INDEX_KDTREE = 1 # bug: flann enums are missing
flann_params = dict(algorithm = FLANN_INDEX_KDTREE,
trees = 5)
matcher = cv2.FlannBasedMatcher(flann_params, {})
print ("Iterating through next images...")
closestImage = None
# TODO: Thread this loop since each iteration is independent
# Find the best next image from the remaining images
for next_img_path in self.dir_list:
print ("Reading %s..." % next_img_path)
if ( self.key_frame_file in next_img_path ):
print ("\t Skipping %s..." % self.key_frame_file)
continue
# Read in the next image...
next_img_rgb = cv2.imread(next_img_path)
next_img = cv2.GaussianBlur(cv2.cvtColor(next_img_rgb,cv2.COLOR_BGR2GRAY), (5,5), 0)
# if ( next_img.shape != base_img.shape ):
# print "\t Skipping %s, bad shape: %s" % (next_img_path, next_img.shape)
# continue
print ("\t Finding points...")
# Find points in the next frame
next_features, next_descs = detector.detectAndCompute(next_img, None)
matches = matcher.knnMatch(next_descs, trainDescriptors=base_descs, k=2)
print ("\t Match Count: ", len(matches))
matches_subset = self.filter_matches(matches)
print ("\t Filtered Match Count: ", len(matches_subset))
distance = self.imageDistance(matches_subset)
print ("\t Distance from Key Image: ", distance)
averagePointDistance = distance/float(len(matches_subset))
print ("\t Average Distance: ", averagePointDistance)
kp1 = []
kp2 = []
for match in matches_subset:
kp1.append(base_features[match.trainIdx])
kp2.append(next_features[match.queryIdx])
p1 = np.array([k.pt for k in kp1])
p2 = np.array([k.pt for k in kp2])
H, status = cv2.findHomography(p1, p2, cv2.RANSAC, 5.0)
print ('%d / %d inliers/matched' % (np.sum(status), len(status)))
inlierRatio = float(np.sum(status)) / float(len(status))
# if ( closestImage == None or averagePointDistance < closestImage['dist'] ):
if ( closestImage == None or inlierRatio > closestImage['inliers'] ):
closestImage = {}
closestImage['h'] = H
closestImage['inliers'] = inlierRatio
closestImage['dist'] = averagePointDistance
closestImage['path'] = next_img_path
closestImage['rgb'] = next_img_rgb
closestImage['img'] = next_img
closestImage['feat'] = next_features
closestImage['desc'] = next_descs
closestImage['match'] = matches_subset
print ("Closest Image: ", closestImage['path'])
print ("Closest Image Ratio: ", closestImage['inliers'])
self.dir_list = filter(lambda x: x != closestImage['path'], self.dir_list)
# utils.showImage(closestImage['img'], scale=(0.2, 0.2), timeout=0)
# cv2.destroyAllWindows()
H = closestImage['h']
H = H / H[2,2]
H_inv = linalg.inv(H)
if ( closestImage['inliers'] > 0.1 ): # and
(min_x, min_y, max_x, max_y) = self.findDimensions(closestImage['img'], H_inv)
# Adjust max_x and max_y by base img size
max_x = max(max_x, base_img.shape[1])
max_y = max(max_y, base_img.shape[0])
move_h = np.matrix(np.identity(3), np.float32)
if ( min_x < 0 ):
move_h[0,2] += -min_x
max_x += -min_x
if ( min_y < 0 ):
move_h[1,2] += -min_y
max_y += -min_y
print ("Homography: \n", H)
print ("Inverse Homography: \n", H_inv)
print ("Min Points: ", (min_x, min_y))
mod_inv_h = move_h * H_inv
img_w = int(math.ceil(max_x))
img_h = int(math.ceil(max_y))
print ("New Dimensions: ", (img_w, img_h))
# Warp the new image given the homography from the old image
base_img_warp = cv2.warpPerspective(base_img_rgb, move_h, (img_w, img_h))
print ("Warped base image")
# utils.showImage(base_img_warp, scale=(0.2, 0.2), timeout=5000)
# cv2.destroyAllWindows()
next_img_warp = cv2.warpPerspective(closestImage['rgb'], mod_inv_h, (img_w, img_h))
print ("Warped next image")
# utils.showImage(next_img_warp, scale=(0.2, 0.2), timeout=5000)
# cv2.destroyAllWindows()
# Put the base image on an enlarged palette
enlarged_base_img = np.zeros((img_h, img_w, 3), np.uint8)
print ("Enlarged Image Shape: ", enlarged_base_img.shape)
print ("Base Image Shape: ", base_img_rgb.shape)
print ("Base Image Warp Shape: ", base_img_warp.shape)
# enlarged_base_img[y:y+base_img_rgb.shape[0],x:x+base_img_rgb.shape[1]] = base_img_rgb
# enlarged_base_img[:base_img_warp.shape[0],:base_img_warp.shape[1]] = base_img_warp
# Create a mask from the warped image for constructing masked composite
(ret,data_map) = cv2.threshold(cv2.cvtColor(next_img_warp, cv2.COLOR_BGR2GRAY),
0, 255, cv2.THRESH_BINARY)
enlarged_base_img = cv2.add(enlarged_base_img, base_img_warp,
mask=np.bitwise_not(data_map),
dtype=cv2.CV_8U)
# Now add the warped image
final_img = cv2.add(enlarged_base_img, next_img_warp,
dtype=cv2.CV_8U)
# utils.showImage(final_img, scale=(0.2, 0.2), timeout=0)
# cv2.destroyAllWindows()
# Crop off the black edges
final_gray = cv2.cvtColor(final_img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(final_gray, 1, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
print ("Found %d contours..." % (len(contours)))
max_area = 0
best_rect = (0,0,0,0)
for cnt in contours:
x,y,w,h = cv2.boundingRect(cnt)
# print "Bounding Rectangle: ", (x,y,w,h)
deltaHeight = h-y
deltaWidth = w-x
area = deltaHeight * deltaWidth
if ( area > max_area and deltaHeight > 0 and deltaWidth > 0):
max_area = area
best_rect = (x,y,w,h)
if ( max_area > 0 ):
print ("Maximum Contour: ", max_area)
print ("Best Rectangle: ", best_rect)
final_img_crop = final_img[best_rect[1]:best_rect[1]+best_rect[3],
best_rect[0]:best_rect[0]+best_rect[2]]
# utils.showImage(final_img_crop, scale=(0.2, 0.2), timeout=0)
# cv2.destroyAllWindows()
final_img = final_img_crop
# Write out the current round
final_filename = "%s/%d.JPG" % (self.output_dir, round)
cv2.imwrite(final_filename, final_img)
return self.stitchImages(final_img, round+1)
else:
return self.stitchImages(base_img_rgb, round+1)
# ----------------------------------------------------------------------------
#if _name_ == '_main_':
# if ( len(args) < 4 ):
# print >> sys.stderr, ("Usage: %s <image_dir> <key_frame> <output>" % args[0])
# sys.exit(-1)
#AlignImagesRansac(sys.args[1:])
I'm working on Lepton 2.5. thermal camera. When I run the code below, the output is on greyscale (attached image 1)..
Maybe somebody can help me to adjust this code so the output will be a RGB color (attached image 2). I really appreciate the assistance given. Sorry if I am not very competent in python or opencv, I try my best.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from uvctypes import *
import time
import cv2
import numpy as np
try:
from queue import Queue
except ImportError:
from Queue import Queue
import platform
BUF_SIZE = 2
q = Queue(BUF_SIZE)
def py_frame_callback(frame, userptr):
array_pointer = cast(frame.contents.data, POINTER(c_uint16 * (frame.contents.width * frame.contents.height)))
data = np.frombuffer(
array_pointer.contents, dtype=np.dtype(np.uint16)
).reshape(
frame.contents.height, frame.contents.width
) # no copy
# data = np.fromiter(
# frame.contents.data, dtype=np.dtype(np.uint8), count=frame.contents.data_bytes
# ).reshape(
# frame.contents.height, frame.contents.width, 2
# ) # copy
if frame.contents.data_bytes != (2 * frame.contents.width * frame.contents.height):
return
if not q.full():
q.put(data)
PTR_PY_FRAME_CALLBACK = CFUNCTYPE(None, POINTER(uvc_frame), c_void_p)(py_frame_callback)
def ktof(val):
return (1.8 * ktoc(val) + 32.0)
def ktoc(val):
return (val - 27315) / 100.0
def raw_to_8bit(data):
cv2.normalize(data, data, 0, 65535, cv2.NORM_MINMAX)
np.right_shift(data, 8, data)
return cv2.cvtColor(np.uint8(data), cv2.COLOR_GRAY2RGB)
def display_temperature(img, val_k, loc, color):
val = ktoc(val_k) #select between ktoc or ktof
cv2.putText(img,"{0:.1f} Celcius".format(val), loc, cv2.FONT_HERSHEY_SIMPLEX, 0.75, color, 2)
x, y = loc
cv2.line(img, (x - 2, y), (x + 2, y), color, 1)
cv2.line(img, (x, y - 2), (x, y + 2), color, 1)
def main():
ctx = POINTER(uvc_context)()
dev = POINTER(uvc_device)()
devh = POINTER(uvc_device_handle)()
ctrl = uvc_stream_ctrl()
res = libuvc.uvc_init(byref(ctx), 0)
if res < 0:
print("uvc_init error")
exit(1)
try:
res = libuvc.uvc_find_device(ctx, byref(dev), PT_USB_VID, PT_USB_PID, 0)
if res < 0:
print("uvc_find_device error")
exit(1)
try:
res = libuvc.uvc_open(dev, byref(devh))
if res < 0:
print("uvc_open error")
exit(1)
print("device opened!")
# device format
print_device_info(devh)
print_device_formats(devh)
frame_formats = uvc_get_frame_formats_by_guid(devh, VS_FMT_GUID_Y16)
if len(frame_formats) == 0:
print("device does not support Y16")
exit(1)
libuvc.uvc_get_stream_ctrl_format_size(devh, byref(ctrl), UVC_FRAME_FORMAT_Y16,
frame_formats[0].wWidth, frame_formats[0].wHeight, int(1e7 / frame_formats[0].dwDefaultFrameInterval)
)
res = libuvc.uvc_start_streaming(devh, byref(ctrl), PTR_PY_FRAME_CALLBACK, None, 0)
if res < 0:
print("uvc_start_streaming failed: {0}".format(res))
exit(1)
try:
while True:
data = q.get(True, 500)
if data is None:
break
data = cv2.resize(data[:,:], (640, 480))
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(data)
img = raw_to_8bit(data)
display_temperature(img, minVal, minLoc, (255, 0, 0))
display_temperature(img, maxVal, maxLoc, (0, 0, 255))
cv2.imshow('Lepton Radiometry', img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
finally:
libuvc.uvc_stop_streaming(devh)
print("done")
finally:
libuvc.uvc_unref_device(dev)
finally:
libuvc.uvc_exit(ctx)
if __name__ == '__main__':
main()
This is the sample output of greyscale image
This is the sample output of RGB image (with another code)
Thanks to Peter Gibson
You can find the answer on
https://learnopencv.com/applycolormap-for-pseudocoloring-in-opencv-c-python/
you just have to take the latest image variable to show and redirect it into
im_color = cv2.applyColorMap(img, cv2.COLORMAP_JET)
and send it to cv2.imshow
I found some example solution a detected common element on the two images.
It's code on Python with OpenCV and I execute on my two examples images:
'''
Feature-based image matching sample.
Note, that you will need the https://github.com/opencv/opencv_contrib repo for SIFT and SURF
USAGE
find_obj.py [--feature=<sift|surf|orb|akaze|brisk>[-flann]] [ <image1> <image2> ]
--feature - Feature to use. Can be sift, surf, orb or brisk. Append '-flann'
to feature name to use Flann-based matcher instead bruteforce.
Press left mouse button on a feature point to see its matching point.
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
from common import anorm, getsize
FLANN_INDEX_KDTREE = 1 # bug: flann enums are missing
FLANN_INDEX_LSH = 6
def init_feature(name):
chunks = name.split('-')
if chunks[0] == 'sift':
detector = cv.xfeatures2d.SIFT_create()
norm = cv.NORM_L2
elif chunks[0] == 'surf':
detector = cv.xfeatures2d.SURF_create(200)
norm = cv.NORM_L2
elif chunks[0] == 'orb':
detector = cv.ORB_create(1400)
norm = cv.NORM_HAMMING
elif chunks[0] == 'akaze':
detector = cv.AKAZE_create()
norm = cv.NORM_HAMMING
elif chunks[0] == 'brisk':
detector = cv.BRISK_create()
norm = cv.NORM_HAMMING
else:
return None, None
if 'flann' in chunks:
if norm == cv.NORM_L2:
flann_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
else:
flann_params= dict(algorithm = FLANN_INDEX_LSH,
table_number = 6, # 12
key_size = 12, # 20
multi_probe_level = 1) #2
matcher = cv.FlannBasedMatcher(flann_params, {}) # bug : need to pass empty dict (#1329)
else:
matcher = cv.BFMatcher(norm)
return detector, matcher
def filter_matches(kp1, kp2, matches, ratio = 0.75):
mkp1, mkp2 = [], []
for m in matches:
if len(m) == 2 and m[0].distance < m[1].distance * ratio:
m = m[0]
mkp1.append( kp1[m.queryIdx] )
mkp2.append( kp2[m.trainIdx] )
p1 = np.float32([kp.pt for kp in mkp1])
p2 = np.float32([kp.pt for kp in mkp2])
kp_pairs = zip(mkp1, mkp2)
return p1, p2, list(kp_pairs)
def explore_match(win, img1, img2, kp_pairs, status = None, H = None):
h1, w1 = img1.shape[:2]
h2, w2 = img2.shape[:2]
vis = np.zeros((max(h1, h2), w1+w2), np.uint8)
vis[:h1, :w1] = img1
vis[:h2, w1:w1+w2] = img2
vis = cv.cvtColor(vis, cv.COLOR_GRAY2BGR)
if H is not None:
corners = np.float32([[0, 0], [w1, 0], [w1, h1], [0, h1]])
corners = np.int32( cv.perspectiveTransform(corners.reshape(1, -1, 2), H).reshape(-1, 2) + (w1, 0) )
cv.polylines(vis, [corners], True, (255, 255, 255))
if status is None:
status = np.ones(len(kp_pairs), np.bool_)
p1, p2 = [], [] # python 2 / python 3 change of zip unpacking
for kpp in kp_pairs:
p1.append(np.int32(kpp[0].pt))
p2.append(np.int32(np.array(kpp[1].pt) + [w1, 0]))
green = (0, 255, 0)
red = (0, 0, 255)
kp_color = (51, 103, 236)
for (x1, y1), (x2, y2), inlier in zip(p1, p2, status):
if inlier:
col = green
cv.circle(vis, (x1, y1), 2, col, -1)
cv.circle(vis, (x2, y2), 2, col, -1)
else:
col = red
r = 2
thickness = 3
cv.line(vis, (x1-r, y1-r), (x1+r, y1+r), col, thickness)
cv.line(vis, (x1-r, y1+r), (x1+r, y1-r), col, thickness)
cv.line(vis, (x2-r, y2-r), (x2+r, y2+r), col, thickness)
cv.line(vis, (x2-r, y2+r), (x2+r, y2-r), col, thickness)
vis0 = vis.copy()
for (x1, y1), (x2, y2), inlier in zip(p1, p2, status):
if inlier:
cv.line(vis, (x1, y1), (x2, y2), green)
cv.imshow(win, vis)
def onmouse(event, x, y, flags, param):
cur_vis = vis
if flags & cv.EVENT_FLAG_LBUTTON:
cur_vis = vis0.copy()
r = 8
m = (anorm(np.array(p1) - (x, y)) < r) | (anorm(np.array(p2) - (x, y)) < r)
idxs = np.where(m)[0]
kp1s, kp2s = [], []
for i in idxs:
(x1, y1), (x2, y2) = p1[i], p2[i]
col = (red, green)[status[i][0]]
cv.line(cur_vis, (x1, y1), (x2, y2), col)
kp1, kp2 = kp_pairs[i]
kp1s.append(kp1)
kp2s.append(kp2)
cur_vis = cv.drawKeypoints(cur_vis, kp1s, None, flags=4, color=kp_color)
cur_vis[:,w1:] = cv.drawKeypoints(cur_vis[:,w1:], kp2s, None, flags=4, color=kp_color)
cv.imshow(win, cur_vis)
cv.setMouseCallback(win, onmouse)
return vis
if __name__ == '__main__':
print(__doc__)
import sys, getopt
opts, args = getopt.getopt(sys.argv[1:], '', ['feature='])
opts = dict(opts)
feature_name = opts.get('--feature', 'brisk')
try:
fn1, fn2 = args
except:
fn1 = '../data/box.png'
fn2 = '../data/box_in_scene.png'
img1 = cv.imread(fn1, 0)
img2 = cv.imread(fn2, 0)
detector, matcher = init_feature(feature_name)
if img1 is None:
print('Failed to load fn1:', fn1)
sys.exit(1)
if img2 is None:
print('Failed to load fn2:', fn2)
sys.exit(1)
if detector is None:
print('unknown feature:', feature_name)
sys.exit(1)
print('using', feature_name)
kp1, desc1 = detector.detectAndCompute(img1, None)
kp2, desc2 = detector.detectAndCompute(img2, None)
print('img1 - %d features, img2 - %d features' % (len(kp1), len(kp2)))
def match_and_draw(win):
print('matching...')
raw_matches = matcher.knnMatch(desc1, trainDescriptors = desc2, k = 2) #2
p1, p2, kp_pairs = filter_matches(kp1, kp2, raw_matches)
if len(p1) >= 4:
H, status = cv.findHomography(p1, p2, cv.RANSAC, 5.0)
print('%d / %d inliers/matched' % (np.sum(status), len(status)))
else:
H, status = None, None
print('%d matches found, not enough for homography estimation' % len(p1))
_vis = explore_match(win, img1, img2, kp_pairs, status, H)
match_and_draw('find_obj')
cv.waitKey()
cv.destroyAllWindows()
Its original images
Its images with some changes
And result in Python Code like this:
python diff_good.py --feature=surf images/org_web.png images/change1.png
Result detected common object
I try to find some solution - how change markered type of common object for example: instead show area with many colors point to some contours, shape (square, rectangle etc.) something like this :
This is some example second images with markered by green rectangles commons element - block
example result images
I want to change this code to get markered only common contours - the area without many points or line like now, because it's not clear to present and understood.
Maybe will be the best solution make third images - result output image with markered only common area like rectangles objects or contours.
But after many hours spend for search solution on google, forums and groups I failed to change this code to act as it needs, maybe here I will find some help, example or suggestions how to modify it.
I found this repo x-img-diff.
They cluster the keypoints into the same boxes and use some other methods to handle the boxes. You can try this way.
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