vendor: OpenCV 5.0.0 snapshot at 40738fb16ceddb5fb3fea747585f7ce6abb0605b

This commit is contained in:
Gitea Mirror Bot
2026-08-22 00:10:33 +08:00
commit f7f077da11
6933 changed files with 2335208 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
# python binary files
*.pyc
__pycache__
# tmp files from examples
/output
*.dat
out.ply
svm_scores.npz
unused_api.txt
+6
View File
@@ -0,0 +1,6 @@
if(INSTALL_PYTHON_EXAMPLES)
file(GLOB install_list *.py )
install(FILES ${install_list}
DESTINATION ${OPENCV_SAMPLES_SRC_INSTALL_PATH}/python
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT samples)
endif()
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/env python
'''
Utility for measuring python opencv API coverage by samples.
'''
# Python 2/3 compatibility
from __future__ import print_function
from glob import glob
import cv2 as cv
import re
if __name__ == '__main__':
cv2_callable = set(['cv.'+name for name in dir(cv) if callable( getattr(cv, name) )])
found = set()
for fn in glob('*.py'):
print(' --- ', fn)
code = open(fn).read()
found |= set(re.findall(r'cv2?\.\w+', code))
cv2_used = found & cv2_callable
cv2_unused = cv2_callable - cv2_used
with open('unused_api.txt', 'w') as f:
f.write('\n'.join(sorted(cv2_unused)))
r = 1.0 * len(cv2_used) / len(cv2_callable)
print('\ncv api coverage: %d / %d (%.1f%%)' % ( len(cv2_used), len(cv2_callable), r*100 ))
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env python
'''
Scans current directory for *.py files and reports
ones with missing __doc__ string.
'''
# Python 2/3 compatibility
from __future__ import print_function
from glob import glob
if __name__ == '__main__':
print('--- undocumented files:')
for fn in glob('*.py'):
loc = {}
try:
try:
execfile(fn, loc) # Python 2
except NameError:
exec(open(fn).read(), loc) # Python 3
except Exception:
pass
if '__doc__' not in loc:
print(fn)
+3
View File
@@ -0,0 +1,3 @@
@echo off
call ..\_winpack_run_python_sample.cmd %*
exit /B
@@ -0,0 +1,116 @@
#!/usr/bin/env python
"""aruco_detect_board_charuco.py
Usage example:
python aruco_detect_board_charuco.py -w=5 -h=7 -sl=0.04 -ml=0.02 -d=10 -c=../data/aruco/tutorial_camera_charuco.yml
-i=../data/aruco/choriginal.jpg
"""
import argparse
import numpy as np
import cv2 as cv
import sys
def read_camera_parameters(filename):
fs = cv.FileStorage(cv.samples.findFile(filename, False), cv.FileStorage_READ)
if fs.isOpened():
cam_matrix = fs.getNode("camera_matrix").mat()
dist_coefficients = fs.getNode("distortion_coefficients").mat()
return True, cam_matrix, dist_coefficients
return False, [], []
def main():
# parse command line options
parser = argparse.ArgumentParser(description="detect markers and corners of charuco board, estimate pose of charuco"
"board", add_help=False)
parser.add_argument("-H", "--help", help="show help", action="store_true", dest="show_help")
parser.add_argument("-v", "--video", help="Input from video or image file, if omitted, input comes from camera",
default="", action="store", dest="v")
parser.add_argument("-i", "--image", help="Input from image file", default="", action="store", dest="img_path")
parser.add_argument("-w", help="Number of squares in X direction", default="3", action="store", dest="w", type=int)
parser.add_argument("-h", help="Number of squares in Y direction", default="3", action="store", dest="h", type=int)
parser.add_argument("-sl", help="Square side length", default="1.", action="store", dest="sl", type=float)
parser.add_argument("-ml", help="Marker side length", default="0.5", action="store", dest="ml", type=float)
parser.add_argument("-d", help="dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2, DICT_4X4_1000=3,"
"DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, DICT_6X6_50=8,"
"DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12, DICT_7X7_100=13,"
"DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL=16,"
"DICT_APRILTAG_16h5=17, DICT_APRILTAG_25h9=18, DICT_APRILTAG_36h10=19, DICT_APRILTAG_36h11=20, DICT_ARUCO_MIP_36h12=21}",
default="0", action="store", dest="d", type=int)
parser.add_argument("-ci", help="Camera id if input doesnt come from video (-v)", default="0", action="store",
dest="ci", type=int)
parser.add_argument("-c", help="Input file with calibrated camera parameters", default="", action="store",
dest="cam_param")
args = parser.parse_args()
show_help = args.show_help
if show_help:
parser.print_help()
sys.exit()
width = args.w
height = args.h
square_len = args.sl
marker_len = args.ml
dict = args.d
video = args.v
camera_id = args.ci
img_path = args.img_path
cam_param = args.cam_param
cam_matrix = []
dist_coefficients = []
if cam_param != "":
_, cam_matrix, dist_coefficients = read_camera_parameters(cam_param)
aruco_dict = cv.aruco.getPredefinedDictionary(dict)
board_size = (width, height)
board = cv.aruco.CharucoBoard(board_size, square_len, marker_len, aruco_dict)
charuco_detector = cv.aruco.CharucoDetector(board)
image = None
input_video = None
wait_time = 10
if video != "":
input_video = cv.VideoCapture(cv.samples.findFileOrKeep(video, False))
image = input_video.retrieve()[1] if input_video.grab() else None
elif img_path == "":
input_video = cv.VideoCapture(camera_id)
image = input_video.retrieve()[1] if input_video.grab() else None
elif img_path != "":
wait_time = 0
image = cv.imread(cv.samples.findFile(img_path, False))
if image is None:
print("Error: unable to open video/image source")
sys.exit(0)
while image is not None:
image_copy = np.copy(image)
charuco_corners, charuco_ids, marker_corners, marker_ids = charuco_detector.detectBoard(image)
if not (marker_ids is None) and len(marker_ids) > 0:
cv.aruco.drawDetectedMarkers(image_copy, marker_corners)
if not (charuco_ids is None) and len(charuco_ids) > 0:
cv.aruco.drawDetectedCornersCharuco(image_copy, charuco_corners, charuco_ids)
if len(cam_matrix) > 0 and len(charuco_ids) >= 4:
try:
obj_points, img_points = board.matchImagePoints(charuco_corners, charuco_ids)
flag, rvec, tvec = cv.solvePnP(obj_points, img_points, cam_matrix, dist_coefficients)
if flag:
cv.drawFrameAxes(image_copy, cam_matrix, dist_coefficients, rvec, tvec, .2)
except cv.error as error_inst:
print("SolvePnP recognize calibration pattern as non-planar pattern. To process this need to use "
"minimum 6 points. The planar pattern may be mistaken for non-planar if the pattern is "
"deformed or incorrect camera parameters are used.")
print(error_inst.err)
cv.imshow("out", image_copy)
key = cv.waitKey(wait_time)
if key == 27:
break
image = input_video.retrieve()[1] if input_video is not None and input_video.grab() else None
if __name__ == "__main__":
main()
+168
View File
@@ -0,0 +1,168 @@
#!/usr/bin/env python
'''
Affine invariant feature-based image matching sample.
This sample is similar to find_obj.py, but uses the affine transformation
space sampling technique, called ASIFT [1]. While the original implementation
is based on SIFT, you can try to use SURF or ORB detectors instead. Homography RANSAC
is used to reject outliers. Threading is used for faster affine sampling.
[1] http://www.ipol.im/pub/algo/my_affine_sift/
USAGE
asift.py [--feature=<sift|surf|orb|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
# built-in modules
import itertools as it
from multiprocessing.pool import ThreadPool
# local modules
from common import Timer
from find_obj import init_feature, filter_matches, explore_match
def affine_skew(tilt, phi, img, mask=None):
'''
affine_skew(tilt, phi, img, mask=None) -> skew_img, skew_mask, Ai
Ai - is an affine transform matrix from skew_img to img
'''
h, w = img.shape[:2]
if mask is None:
mask = np.zeros((h, w), np.uint8)
mask[:] = 255
A = np.float32([[1, 0, 0], [0, 1, 0]])
if phi != 0.0:
phi = np.deg2rad(phi)
s, c = np.sin(phi), np.cos(phi)
A = np.float32([[c,-s], [ s, c]])
corners = [[0, 0], [w, 0], [w, h], [0, h]]
tcorners = np.int32( np.dot(corners, A.T) )
x, y, w, h = cv.boundingRect(tcorners.reshape(1,-1,2))
A = np.hstack([A, [[-x], [-y]]])
img = cv.warpAffine(img, A, (w, h), flags=cv.INTER_LINEAR, borderMode=cv.BORDER_REPLICATE)
if tilt != 1.0:
s = 0.8*np.sqrt(tilt*tilt-1)
img = cv.GaussianBlur(img, (0, 0), sigmaX=s, sigmaY=0.01)
img = cv.resize(img, (0, 0), fx=1.0/tilt, fy=1.0, interpolation=cv.INTER_NEAREST)
A[0] /= tilt
if phi != 0.0 or tilt != 1.0:
h, w = img.shape[:2]
mask = cv.warpAffine(mask, A, (w, h), flags=cv.INTER_NEAREST)
Ai = cv.invertAffineTransform(A)
return img, mask, Ai
def affine_detect(detector, img, mask=None, pool=None):
'''
affine_detect(detector, img, mask=None, pool=None) -> keypoints, descrs
Apply a set of affine transformations to the image, detect keypoints and
reproject them into initial image coordinates.
See http://www.ipol.im/pub/algo/my_affine_sift/ for the details.
ThreadPool object may be passed to speedup the computation.
'''
params = [(1.0, 0.0)]
for t in 2**(0.5*np.arange(1,6)):
for phi in np.arange(0, 180, 72.0 / t):
params.append((t, phi))
def f(p):
t, phi = p
timg, tmask, Ai = affine_skew(t, phi, img)
keypoints, descrs = detector.detectAndCompute(timg, tmask)
for kp in keypoints:
x, y = kp.pt
kp.pt = tuple( np.dot(Ai, (x, y, 1)) )
if descrs is None:
descrs = []
return keypoints, descrs
keypoints, descrs = [], []
if pool is None:
ires = it.imap(f, params)
else:
ires = pool.imap(f, params)
for i, (k, d) in enumerate(ires):
print('affine sampling: %d / %d\r' % (i+1, len(params)), end='')
keypoints.extend(k)
descrs.extend(d)
print()
return keypoints, np.array(descrs)
def main():
import sys, getopt
opts, args = getopt.getopt(sys.argv[1:], '', ['feature='])
opts = dict(opts)
feature_name = opts.get('--feature', 'brisk-flann')
try:
fn1, fn2 = args
except:
fn1 = 'aero1.jpg'
fn2 = 'aero3.jpg'
img1 = cv.imread(cv.samples.findFile(fn1), cv.IMREAD_GRAYSCALE)
img2 = cv.imread(cv.samples.findFile(fn2), cv.IMREAD_GRAYSCALE)
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)
pool=ThreadPool(processes = cv.getNumberOfCPUs())
kp1, desc1 = affine_detect(detector, img1, pool=pool)
kp2, desc2 = affine_detect(detector, img2, pool=pool)
print('img1 - %d features, img2 - %d features' % (len(kp1), len(kp2)))
def match_and_draw(win):
with Timer('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)))
# do not draw outliers (there will be a lot of them)
kp_pairs = [kpp for kpp, flag in zip(kp_pairs, status) if flag]
else:
H, status = None, None
print('%d matches found, not enough for homography estimation' % len(p1))
explore_match(win, img1, img2, kp_pairs, None, H)
match_and_draw('affine find_obj')
cv.waitKey()
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+808
View File
@@ -0,0 +1,808 @@
import numpy as np
import cv2 as cv
import math
import argparse
class AudioDrawing:
'''
Used for drawing audio graphics
'''
def __init__(self, args):
self.inputType = args.inputType
self.draw = args.draw
self.graph = args.graph
self.audio = cv.samples.findFile(args.audio)
self.audioStream = args.audioStream
self.windowType = args.windowType
self.windLen = args.windLen
self.overlap = args.overlap
self.enableGrid = args.enableGrid
self.rows = args.rows
self.cols = args.cols
self.xmarkup = args.xmarkup
self.ymarkup = args.ymarkup
self.zmarkup = args.zmarkup
self.microTime = args.microTime
self.frameSizeTime = args.frameSizeTime
self.updateTime = args.updateTime
self.waitTime = args.waitTime
if self.initAndCheckArgs(args) is False:
exit()
def Draw(self):
if self.draw == "static":
if self.inputType == "file":
samplingRate, inputAudio = self.readAudioFile(self.audio)
elif self.inputType == "microphone":
samplingRate, inputAudio = self.readAudioMicrophone()
duration = len(inputAudio) // samplingRate
# since the dimensional grid is counted in integer seconds,
# if the input audio has an incomplete last second,
# then it is filled with zeros to complete
remainder = len(inputAudio) % samplingRate
if remainder != 0:
sizeToFullSec = samplingRate - remainder
zeroArr = np.zeros(sizeToFullSec)
inputAudio = np.concatenate((inputAudio, zeroArr), axis=0)
duration += 1
print("Update duration of audio to full second with ",
sizeToFullSec, " zero samples")
print("New number of samples ", len(inputAudio))
if duration <= self.xmarkup:
self.xmarkup = duration + 1
if self.graph == "ampl":
imgAmplitude = self.drawAmplitude(inputAudio)
imgAmplitude = self.drawAmplitudeScale(imgAmplitude, inputAudio, samplingRate)
cv.imshow("Display window", imgAmplitude)
cv.waitKey(0)
elif self.graph == "spec":
stft = self.STFT(inputAudio)
imgSpec = self.drawSpectrogram(stft)
imgSpec = self.drawSpectrogramColorbar(imgSpec, inputAudio, samplingRate, stft)
cv.imshow("Display window", imgSpec)
cv.waitKey(0)
elif self.graph == "ampl_and_spec":
imgAmplitude = self.drawAmplitude(inputAudio)
imgAmplitude = self.drawAmplitudeScale(imgAmplitude, inputAudio, samplingRate)
stft = self.STFT(inputAudio)
imgSpec = self.drawSpectrogram(stft)
imgSpec = self.drawSpectrogramColorbar(imgSpec, inputAudio, samplingRate, stft)
imgTotal = self.concatenateImages(imgAmplitude, imgSpec)
cv.imshow("Display window", imgTotal)
cv.waitKey(0)
elif self.draw == "dynamic":
if self.inputType == "file":
self.dynamicFile(self.audio)
elif self.inputType == "microphone":
self.dynamicMicrophone()
def readAudioFile(self, file):
cap = cv.VideoCapture(file)
params = [cv.CAP_PROP_AUDIO_STREAM, self.audioStream,
cv.CAP_PROP_VIDEO_STREAM, -1,
cv.CAP_PROP_AUDIO_DATA_DEPTH, cv.CV_16S]
params = np.asarray(params)
cap.open(file, cv.CAP_ANY, params)
if cap.isOpened() == False:
print("Error : Can't read audio file: '", self.audio, "' with audioStream = ", self.audioStream)
print("Error: problems with audio reading, check input arguments")
exit()
audioBaseIndex = int(cap.get(cv.CAP_PROP_AUDIO_BASE_INDEX))
numberOfChannels = int(cap.get(cv.CAP_PROP_AUDIO_TOTAL_CHANNELS))
print("CAP_PROP_AUDIO_DATA_DEPTH: ", str((int(cap.get(cv.CAP_PROP_AUDIO_DATA_DEPTH)))))
print("CAP_PROP_AUDIO_SAMPLES_PER_SECOND: ", cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
print("CAP_PROP_AUDIO_TOTAL_CHANNELS: ", numberOfChannels)
print("CAP_PROP_AUDIO_TOTAL_STREAMS: ", cap.get(cv.CAP_PROP_AUDIO_TOTAL_STREAMS))
frame = []
frame = np.asarray(frame)
inputAudio = []
while (1):
if (cap.grab()):
frame = []
frame = np.asarray(frame)
frame = cap.retrieve(frame, audioBaseIndex)
for i in range(len(frame[1][0])):
inputAudio.append(frame[1][0][i])
else:
break
inputAudio = np.asarray(inputAudio)
print("Number of samples: ", len(inputAudio))
samplingRate = int(cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
return samplingRate, inputAudio
def readAudioMicrophone(self):
cap = cv.VideoCapture()
params = [cv.CAP_PROP_AUDIO_STREAM, 0, cv.CAP_PROP_VIDEO_STREAM, -1]
params = np.asarray(params)
cap.open(0, cv.CAP_ANY, params)
if cap.isOpened() == False:
print("Error: Can't open microphone")
print("Error: problems with audio reading, check input arguments")
exit()
audioBaseIndex = int(cap.get(cv.CAP_PROP_AUDIO_BASE_INDEX))
numberOfChannels = int(cap.get(cv.CAP_PROP_AUDIO_TOTAL_CHANNELS))
print("CAP_PROP_AUDIO_DATA_DEPTH: ", str((int(cap.get(cv.CAP_PROP_AUDIO_DATA_DEPTH)))))
print("CAP_PROP_AUDIO_SAMPLES_PER_SECOND: ", cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
print("CAP_PROP_AUDIO_TOTAL_CHANNELS: ", numberOfChannels)
print("CAP_PROP_AUDIO_TOTAL_STREAMS: ", cap.get(cv.CAP_PROP_AUDIO_TOTAL_STREAMS))
cvTickFreq = cv.getTickFrequency()
sysTimeCurr = cv.getTickCount()
sysTimePrev = sysTimeCurr
frame = []
frame = np.asarray(frame)
inputAudio = []
while ((sysTimeCurr - sysTimePrev) / cvTickFreq < self.microTime):
if (cap.grab()):
frame = []
frame = np.asarray(frame)
frame = cap.retrieve(frame, audioBaseIndex)
for i in range(len(frame[1][0])):
inputAudio.append(frame[1][0][i])
sysTimeCurr = cv.getTickCount()
else:
print("Error: Grab error")
break
inputAudio = np.asarray(inputAudio)
print("Number of samples: ", len(inputAudio))
samplingRate = int(cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
return samplingRate, inputAudio
def drawAmplitude(self, inputAudio):
color = (247, 111, 87)
thickness = 5
frameVectorRows = 500
middle = frameVectorRows // 2
# usually the input data is too big, so it is necessary
# to reduce size using interpolation of data
frameVectorCols = 40000
if len(inputAudio) < frameVectorCols:
frameVectorCols = len(inputAudio)
img = np.zeros((frameVectorRows, frameVectorCols, 3), np.uint8)
img += 255 # white background
audio = np.array(0)
audio = cv.resize(inputAudio, (1, frameVectorCols), interpolation=cv.INTER_LINEAR)
reshapeAudio = np.reshape(audio, (-1))
# normalization data by maximum element
minCv, maxCv, _, _ = cv.minMaxLoc(reshapeAudio)
maxElem = int(max(abs(minCv), abs(maxCv)))
# if all data values are zero (silence)
if maxElem == 0:
maxElem = 1
for i in range(len(reshapeAudio)):
reshapeAudio[i] = middle - reshapeAudio[i] * middle // maxElem
for i in range(1, frameVectorCols, 1):
cv.line(img, (i - 1, int(reshapeAudio[i - 1])), (i, int(reshapeAudio[i])), color, thickness)
img = cv.resize(img, (900, 400), interpolation=cv.INTER_AREA)
return img
def drawAmplitudeScale(self, inputImg, inputAudio, samplingRate, xmin=None, xmax=None):
# function of layout drawing for graph of volume amplitudes
# x axis for time
# y axis for amplitudes
# parameters for the new image size
preCol = 100
aftCol = 100
preLine = 40
aftLine = 50
frameVectorRows = inputImg.shape[0]
frameVectorCols = inputImg.shape[1]
totalRows = preLine + frameVectorRows + aftLine
totalCols = preCol + frameVectorCols + aftCol
imgTotal = np.zeros((totalRows, totalCols, 3), np.uint8)
imgTotal += 255 # white background
imgTotal[preLine: preLine + frameVectorRows, preCol: preCol + frameVectorCols] = inputImg
# calculating values on x axis
if xmin is None:
xmin = 0
if xmax is None:
xmax = len(inputAudio) / samplingRate
if xmax > self.xmarkup:
xList = np.linspace(xmin, xmax, self.xmarkup).astype(int)
else:
# this case is used to display a dynamic update
tmp = np.arange(xmin, xmax, 1).astype(int) + 1
xList = np.concatenate((np.zeros(self.xmarkup - len(tmp)), tmp[:]), axis=None)
# calculating values on y axis
ymin = np.min(inputAudio)
ymax = np.max(inputAudio)
yList = np.linspace(ymin, ymax, self.ymarkup)
# parameters for layout drawing
textThickness = 1
gridThickness = 1
gridColor = (0, 0, 0)
textColor = (0, 0, 0)
font = cv.FONT_HERSHEY_SIMPLEX
fontScale = 0.5
# horizontal axis under the graph
cv.line(imgTotal, (preCol, totalRows - aftLine),
(preCol + frameVectorCols, totalRows - aftLine),
gridColor, gridThickness)
# vertical axis for amplitude
cv.line(imgTotal, (preCol, preLine), (preCol, preLine + frameVectorRows),
gridColor, gridThickness)
# parameters for layout calculation
serifSize = 10
indentDownX = serifSize * 2
indentDownY = serifSize // 2
indentLeftX = serifSize
indentLeftY = 2 * preCol // 3
# drawing layout for x axis
numX = frameVectorCols // (self.xmarkup - 1)
for i in range(len(xList)):
a1 = preCol + i * numX
a2 = frameVectorRows + preLine
b1 = a1
b2 = a2 + serifSize
if self.enableGrid is True:
d1 = a1
d2 = preLine
cv.line(imgTotal, (a1, a2), (d1, d2), gridColor, gridThickness)
cv.line(imgTotal, (a1, a2), (b1, b2), gridColor, gridThickness)
cv.putText(imgTotal, str(int(xList[i])), (b1 - indentLeftX, b2 + indentDownX),
font, fontScale, textColor, textThickness)
# drawing layout for y axis
numY = frameVectorRows // (self.ymarkup - 1)
for i in range(len(yList)):
a1 = preCol
a2 = totalRows - aftLine - i * numY
b1 = preCol - serifSize
b2 = a2
if self.enableGrid is True:
d1 = preCol + frameVectorCols
d2 = a2
cv.line(imgTotal, (a1, a2), (d1, d2), gridColor, gridThickness)
cv.line(imgTotal, (a1, a2), (b1, b2), gridColor, gridThickness)
cv.putText(imgTotal, str(int(yList[i])), (b1 - indentLeftY, b2 + indentDownY),
font, fontScale, textColor, textThickness)
imgTotal = cv.resize(imgTotal, (self.cols, self.rows), interpolation=cv.INTER_AREA)
return imgTotal
def STFT(self, inputAudio):
"""
The Short-time Fourier transform (STFT), is a Fourier-related transform used to determine
the sinusoidal frequency and phase content of local sections of a signal as it changes over
time.
In practice, the procedure for computing STFTs is to divide a longer time signal into
shorter segments of equal length and then compute the Fourier transform separately on each
shorter segment. This reveals the Fourier spectrum on each shorter segment. One then usually
plots the changing spectra as a function of time, known as a spectrogram or waterfall plot.
https://en.wikipedia.org/wiki/Short-time_Fourier_transform
"""
time_step = self.windLen - self.overlap
if time_step <= 0:
raise ValueError(
"Invalid STFT parameters: overlap must be smaller than window length"
)
stft = []
if self.windowType == "Hann":
# https://en.wikipedia.org/wiki/Window_function#Hann_and_Hamming_windows
Hann_wind = []
for i in range (1 - self.windLen, self.windLen, 2):
Hann_wind.append(i * (0.5 + 0.5 * math.cos(math.pi * i / (self.windLen - 1))))
Hann_wind = np.asarray(Hann_wind)
elif self.windowType == "Hamming":
# https://en.wikipedia.org/wiki/Window_function#Hann_and_Hamming_windows
Hamming_wind = []
for i in range (1 - self.windLen, self.windLen, 2):
Hamming_wind.append(i * (0.53836 - 0.46164 * (math.cos(2 * math.pi * i / (self.windLen - 1)))))
Hamming_wind = np.asarray(Hamming_wind)
for index in np.arange(0, len(inputAudio), time_step).astype(int):
section = inputAudio[index:index + self.windLen]
zeroArray = np.zeros(self.windLen - len(section))
section = np.concatenate((section, zeroArray), axis=None)
if self.windowType == "Hann":
section *= Hann_wind
elif self.windowType == "Hamming":
section *= Hamming_wind
dst = np.empty(0)
dst = cv.dft(section, dst, flags=cv.DFT_COMPLEX_OUTPUT)
reshape_dst = np.reshape(dst, (-1))
# we need only the first part of the spectrum, the second part is symmetrical
complexArr = np.zeros(len(dst) // 4, dtype=complex)
for i in range(len(dst) // 4):
complexArr[i] = complex(reshape_dst[2 * i], reshape_dst[2 * i + 1])
stft.append(np.abs(complexArr))
stft = np.array(stft).transpose()
# convert elements to the decibel scale
np.log10(stft, out=stft, where=(stft != 0.))
return 10 * stft
def drawSpectrogram(self, stft):
frameVectorRows = stft.shape[0]
frameVectorCols = stft.shape[1]
# Normalization of image values from 0 to 255 to get more contrast image
# and this normalization will be taken into account in the scale drawing
colormapImageRows = 255
imgSpec = np.zeros((frameVectorRows, frameVectorCols, 3), np.uint8)
stftMat = np.zeros((frameVectorRows, frameVectorCols), np.float64)
cv.normalize(stft, stftMat, 1.0, 0.0, cv.NORM_INF)
for i in range(frameVectorRows):
for j in range(frameVectorCols):
imgSpec[frameVectorRows - i - 1, j] = int(stftMat[i][j] * colormapImageRows)
imgSpec = cv.applyColorMap(imgSpec, cv.COLORMAP_INFERNO)
imgSpec = cv.resize(imgSpec, (900, 400), interpolation=cv.INTER_LINEAR)
return imgSpec
def drawSpectrogramColorbar(self, inputImg, inputAudio, samplingRate, stft, xmin=None, xmax=None):
# function of layout drawing for the three-dimensional graph of the spectrogram
# x axis for time
# y axis for frequencies
# z axis for magnitudes of frequencies shown by color scale
# parameters for the new image size
preCol = 100
aftCol = 100
preLine = 40
aftLine = 50
colColor = 20
ind_col = 20
frameVectorRows = inputImg.shape[0]
frameVectorCols = inputImg.shape[1]
totalRows = preLine + frameVectorRows + aftLine
totalCols = preCol + frameVectorCols + aftCol + colColor
imgTotal = np.zeros((totalRows, totalCols, 3), np.uint8)
imgTotal += 255 # white background
imgTotal[preLine: preLine + frameVectorRows, preCol: preCol + frameVectorCols] = inputImg
# colorbar image due to drawSpectrogram(..) picture has been normalised from 255 to 0,
# so here colorbar has values from 255 to 0
colorArrSize = 256
imgColorBar = np.zeros((colorArrSize, colColor, 1), np.uint8)
for i in range(colorArrSize):
imgColorBar[i] += colorArrSize - 1 - i
imgColorBar = cv.applyColorMap(imgColorBar, cv.COLORMAP_INFERNO)
imgColorBar = cv.resize(imgColorBar, (colColor, frameVectorRows), interpolation=cv.INTER_AREA) #
imgTotal[preLine: preLine + frameVectorRows,
preCol + frameVectorCols + ind_col:
preCol + frameVectorCols + ind_col + colColor] = imgColorBar
# calculating values on x axis
if xmin is None:
xmin = 0
if xmax is None:
xmax = len(inputAudio) / samplingRate
if xmax > self.xmarkup:
xList = np.linspace(xmin, xmax, self.xmarkup).astype(int)
else:
# this case is used to display a dynamic update
tmpXList = np.arange(xmin, xmax, 1).astype(int) + 1
xList = np.concatenate((np.zeros(self.xmarkup - len(tmpXList)), tmpXList[:]), axis=None)
# calculating values on y axis
# according to the Nyquist sampling theorem,
# signal should posses frequencies equal to half of sampling rate
ymin = 0
ymax = int(samplingRate / 2.)
yList = np.linspace(ymin, ymax, self.ymarkup).astype(int)
# calculating values on z axis
zList = np.linspace(np.min(stft), np.max(stft), self.zmarkup)
# parameters for layout drawing
textThickness = 1
textColor = (0, 0, 0)
gridThickness = 1
gridColor = (0, 0, 0)
font = cv.FONT_HERSHEY_SIMPLEX
fontScale = 0.5
serifSize = 10
indentDownX = serifSize * 2
indentDownY = serifSize // 2
indentLeftX = serifSize
indentLeftY = 2 * preCol // 3
# horizontal axis
cv.line(imgTotal, (preCol, totalRows - aftLine), (preCol + frameVectorCols, totalRows - aftLine),
gridColor, gridThickness)
# vertical axis
cv.line(imgTotal, (preCol, preLine), (preCol, preLine + frameVectorRows),
gridColor, gridThickness)
# drawing layout for x axis
numX = frameVectorCols // (self.xmarkup - 1)
for i in range(len(xList)):
a1 = preCol + i * numX
a2 = frameVectorRows + preLine
b1 = a1
b2 = a2 + serifSize
cv.line(imgTotal, (a1, a2), (b1, b2), gridColor, gridThickness)
cv.putText(imgTotal, str(int(xList[i])), (b1 - indentLeftX, b2 + indentDownX),
font, fontScale, textColor, textThickness)
# drawing layout for y axis
numY = frameVectorRows // (self.ymarkup - 1)
for i in range(len(yList)):
a1 = preCol
a2 = totalRows - aftLine - i * numY
b1 = preCol - serifSize
b2 = a2
cv.line(imgTotal, (a1, a2), (b1, b2), gridColor, gridThickness)
cv.putText(imgTotal, str(int(yList[i])), (b1 - indentLeftY, b2 + indentDownY),
font, fontScale, textColor, textThickness)
# drawing layout for z axis
numZ = frameVectorRows // (self.zmarkup - 1)
for i in range(len(zList)):
a1 = preCol + frameVectorCols + ind_col + colColor
a2 = totalRows - aftLine - i * numZ
b1 = a1 + serifSize
b2 = a2
cv.line(imgTotal, (a1, a2), (b1, b2), gridColor, gridThickness)
cv.putText(imgTotal, str(int(zList[i])), (b1 + 10, b2 + indentDownY),
font, fontScale, textColor, textThickness)
imgTotal = cv.resize(imgTotal, (self.cols, self.rows), interpolation=cv.INTER_AREA)
return imgTotal
def concatenateImages(self, img1, img2):
# first image will be under the second image
totalRows = img1.shape[0] + img2.shape[0]
totalCols = max(img1.shape[1], img2.shape[1])
# if images columns do not match, the difference is filled in white
imgTotal = np.zeros((totalRows, totalCols, 3), np.uint8)
imgTotal += 255
imgTotal[:img1.shape[0], :img1.shape[1]] = img1
imgTotal[img2.shape[0]:, :img2.shape[1]] = img2
return imgTotal
def dynamicFile(self, file):
cap = cv.VideoCapture(file)
params = [cv.CAP_PROP_AUDIO_STREAM, self.audioStream,
cv.CAP_PROP_VIDEO_STREAM, -1,
cv.CAP_PROP_AUDIO_DATA_DEPTH, cv.CV_16S]
params = np.asarray(params)
cap.open(file, cv.CAP_ANY, params)
if cap.isOpened() == False:
print("ERROR! Can't to open file")
return
audioBaseIndex = int(cap.get(cv.CAP_PROP_AUDIO_BASE_INDEX))
numberOfChannels = int(cap.get(cv.CAP_PROP_AUDIO_TOTAL_CHANNELS))
samplingRate = int(cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
print("CAP_PROP_AUDIO_DATA_DEPTH: ", str((int(cap.get(cv.CAP_PROP_AUDIO_DATA_DEPTH)))))
print("CAP_PROP_AUDIO_SAMPLES_PER_SECOND: ", cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
print("CAP_PROP_AUDIO_TOTAL_CHANNELS: ", numberOfChannels)
print("CAP_PROP_AUDIO_TOTAL_STREAMS: ", cap.get(cv.CAP_PROP_AUDIO_TOTAL_STREAMS))
step = int(self.updateTime * samplingRate)
frameSize = int(self.frameSizeTime * samplingRate)
# since the dimensional grid is counted in integer seconds,
# if duration of audio frame is less than xmarkup, to avoid an incorrect display,
# xmarkup will be taken equal to duration
if self.frameSizeTime <= self.xmarkup:
self.xmarkup = self.frameSizeTime
buffer = []
section = np.zeros(frameSize, dtype=np.int16)
currentSamples = 0
while (1):
if (cap.grab()):
frame = []
frame = np.asarray(frame)
frame = cap.retrieve(frame, audioBaseIndex)
for i in range(len(frame[1][0])):
buffer.append(frame[1][0][i])
buffer_size = len(buffer)
if (buffer_size >= step):
section = list(section)
currentSamples += step
del section[0:step]
section.extend(buffer[0:step])
del buffer[0:step]
section = np.asarray(section)
if currentSamples < frameSize:
xmin = 0
xmax = (currentSamples) / samplingRate
else:
xmin = (currentSamples - frameSize) / samplingRate + 1
xmax = (currentSamples) / samplingRate
if self.graph == "ampl":
imgAmplitude = self.drawAmplitude(section)
imgAmplitude = self.drawAmplitudeScale(imgAmplitude, section, samplingRate, xmin, xmax)
cv.imshow("Display amplitude graph", imgAmplitude)
cv.waitKey(self.waitTime)
elif self.graph == "spec":
stft = self.STFT(section)
imgSpec = self.drawSpectrogram(stft)
imgSpec = self.drawSpectrogramColorbar(imgSpec, section, samplingRate, stft, xmin, xmax)
cv.imshow("Display spectrogram", imgSpec)
cv.waitKey(self.waitTime)
elif self.graph == "ampl_and_spec":
imgAmplitude = self.drawAmplitude(section)
stft = self.STFT(section)
imgSpec = self.drawSpectrogram(stft)
imgAmplitude = self.drawAmplitudeScale(imgAmplitude, section, samplingRate, xmin, xmax)
imgSpec = self.drawSpectrogramColorbar(imgSpec, section, samplingRate, stft, xmin, xmax)
imgTotal = self.concatenateImages(imgAmplitude, imgSpec)
cv.imshow("Display amplitude graph and spectrogram", imgTotal)
cv.waitKey(self.waitTime)
else:
break
def dynamicMicrophone(self):
cap = cv.VideoCapture()
params = [cv.CAP_PROP_AUDIO_STREAM, 0, cv.CAP_PROP_VIDEO_STREAM, -1]
params = np.asarray(params)
cap.open(0, cv.CAP_ANY, params)
if cap.isOpened() == False:
print("ERROR! Can't to open file")
return
audioBaseIndex = int(cap.get(cv.CAP_PROP_AUDIO_BASE_INDEX))
numberOfChannels = int(cap.get(cv.CAP_PROP_AUDIO_TOTAL_CHANNELS))
print("CAP_PROP_AUDIO_DATA_DEPTH: ", str((int(cap.get(cv.CAP_PROP_AUDIO_DATA_DEPTH)))))
print("CAP_PROP_AUDIO_SAMPLES_PER_SECOND: ", cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
print("CAP_PROP_AUDIO_TOTAL_CHANNELS: ", numberOfChannels)
print("CAP_PROP_AUDIO_TOTAL_STREAMS: ", cap.get(cv.CAP_PROP_AUDIO_TOTAL_STREAMS))
frame = []
frame = np.asarray(frame)
samplingRate = int(cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
step = int(self.updateTime * samplingRate)
frameSize = int(self.frameSizeTime * samplingRate)
self.xmarkup = self.frameSizeTime
currentSamples = 0
buffer = []
section = np.zeros(frameSize, dtype=np.int16)
cvTickFreq = cv.getTickFrequency()
sysTimeCurr = cv.getTickCount()
sysTimePrev = sysTimeCurr
self.waitTime = self.updateTime * 1000
while ((sysTimeCurr - sysTimePrev) / cvTickFreq < self.microTime):
if (cap.grab()):
frame = []
frame = np.asarray(frame)
frame = cap.retrieve(frame, audioBaseIndex)
for i in range(len(frame[1][0])):
buffer.append(frame[1][0][i])
sysTimeCurr = cv.getTickCount()
buffer_size = len(buffer)
if (buffer_size >= step):
section = list(section)
currentSamples += step
del section[0:step]
section.extend(buffer[0:step])
del buffer[0:step]
section = np.asarray(section)
if currentSamples < frameSize:
xmin = 0
xmax = (currentSamples) / samplingRate
else:
xmin = (currentSamples - frameSize) / samplingRate + 1
xmax = (currentSamples) / samplingRate
if self.graph == "ampl":
imgAmplitude = self.drawAmplitude(section)
imgAmplitude = self.drawAmplitudeScale(imgAmplitude, section, samplingRate, xmin, xmax)
cv.imshow("Display amplitude graph", imgAmplitude)
cv.waitKey(self.waitTime)
elif self.graph == "spec":
stft = self.STFT(section)
imgSpec = self.drawSpectrogram(stft)
imgSpec = self.drawSpectrogramColorbar(imgSpec, section, samplingRate, stft, xmin, xmax)
cv.imshow("Display spectrogram", imgSpec)
cv.waitKey(self.waitTime)
elif self.graph == "ampl_and_spec":
imgAmplitude = self.drawAmplitude(section)
stft = self.STFT(section)
imgSpec = self.drawSpectrogram(stft)
imgAmplitude = self.drawAmplitudeScale(imgAmplitude, section, samplingRate, xmin, xmax)
imgSpec = self.drawSpectrogramColorbar(imgSpec, section, samplingRate, stft, xmin, xmax)
imgTotal = self.concatenateImages(imgAmplitude, imgSpec)
cv.imshow("Display amplitude graph and spectrogram", imgTotal)
cv.waitKey(self.waitTime)
else:
break
def initAndCheckArgs(self, args):
if args.inputType != "file" and args.inputType != "microphone":
print("Error: ", args.inputType, " input method doesnt exist")
return False
if args.draw != "static" and args.draw != "dynamic":
print("Error: ", args.draw, " draw type doesnt exist")
return False
if args.graph != "ampl" and args.graph != "spec" and args.graph != "ampl_and_spec":
print("Error: ", args.graph, " type of graph doesnt exist")
return False
if args.windowType != "Rect" and args.windowType != "Hann" and args.windowType != "Hamming":
print("Error: ", args.windowType, " type of window doesnt exist")
return False
if args.windLen <= 0:
print("Error: windLen = ", args.windLen, " - incorrect value. Must be > 0")
return False
if args.overlap <= 0:
print("Error: overlap = ", args.overlap, " - incorrect value. Must be > 0")
return False
if args.rows <= 0:
print("Error: rows = ", args.rows, " - incorrect value. Must be > 0")
return False
if args.cols <= 0:
print("Error: cols = ", args.cols, " - incorrect value. Must be > 0")
return False
if args.xmarkup < 2:
print("Error: xmarkup = ", args.xmarkup, " - incorrect value. Must be >= 2")
return False
if args.ymarkup < 2:
print("Error: ymarkup = ", args.ymarkup, " - incorrect value. Must be >= 2")
return False
if args.zmarkup < 2:
print("Error: zmarkup = ", args.zmarkup, " - incorrect value. Must be >= 2")
return False
if args.microTime <= 0:
print("Error: microTime = ", args.microTime, " - incorrect value. Must be > 0")
return False
if args.frameSizeTime <= 0:
print("Error: frameSizeTime = ", args.frameSizeTime, " - incorrect value. Must be > 0")
return False
if args.updateTime <= 0:
print("Error: updateTime = ", args.updateTime, " - incorrect value. Must be > 0")
return False
if args.waitTime < 0:
print("Error: waitTime = ", args.waitTime, " - incorrect value. Must be >= 0")
return False
return True
if __name__ == "__main__":
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
description='''this sample draws a volume graph and/or spectrogram of audio/video files and microphone\nDefault usage: ./Spectrogram.exe''')
parser.add_argument("-i", "--inputType", dest="inputType", type=str, default="file", help="file or microphone")
parser.add_argument("-d", "--draw", dest="draw", type=str, default="static",
help="type of drawing: static - for plotting graph(s) across the entire input audio; dynamic - for plotting graph(s) in a time-updating window")
parser.add_argument("-g", "--graph", dest="graph", type=str, default="ampl_and_spec",
help="type of graph: amplitude graph or/and spectrogram. Please use tags below : ampl - draw the amplitude graph; spec - draw the spectrogram; ampl_and_spec - draw the amplitude graph and spectrogram on one image under each other")
parser.add_argument("-a", "--audio", dest="audio", type=str, default='Megamind.avi',
help="name and path to file")
parser.add_argument("-s", "--audioStream", dest="audioStream", type=int, default=1,
help=" CAP_PROP_AUDIO_STREAM value")
parser.add_argument("-t", '--windowType', dest="windowType", type=str, default="Rect",
help="type of window for STFT. Please use tags below : Rect/Hann/Hamming")
parser.add_argument("-l", '--windLen', dest="windLen", type=int, default=256, help="size of window for STFT")
parser.add_argument("-o", '--overlap', dest="overlap", type=int, default=128, help="overlap of windows for STFT")
parser.add_argument("-gd", '--grid', dest="enableGrid", type=bool, default=False, help="grid on amplitude graph(on/off)")
parser.add_argument("-r", '--rows', dest="rows", type=int, default=400, help="rows of output image")
parser.add_argument("-c", '--cols', dest="cols", type=int, default=900, help="cols of output image")
parser.add_argument("-x", '--xmarkup', dest="xmarkup", type=int, default=5,
help="number of x axis divisions (time asix)")
parser.add_argument("-y", '--ymarkup', dest="ymarkup", type=int, default=5,
help="number of y axis divisions (frequency or/and amplitude axis)") # ?
parser.add_argument("-z", '--zmarkup', dest="zmarkup", type=int, default=5,
help="number of z axis divisions (colorbar)") # ?
parser.add_argument("-m", '--microTime', dest="microTime", type=int, default=20,
help="time of recording audio with microphone in seconds")
parser.add_argument("-f", '--frameSizeTime', dest="frameSizeTime", type=int, default=5,
help="size of sliding window in seconds")
parser.add_argument("-u", '--updateTime', dest="updateTime", type=int, default=1,
help="update time of sliding window in seconds")
parser.add_argument("-w", '--waitTime', dest="waitTime", type=int, default=10,
help="parameter to cv.waitKey() for dynamic update, takes values in milliseconds")
args = parser.parse_args()
AudioDrawing(args).Draw()
@@ -0,0 +1,68 @@
'''
Showcases the use of background subtraction from a live video feed,
aswell as pass through of a known foreground parameter
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
def main():
cap = cv.VideoCapture(0)
if not cap.isOpened:
print("Capture source avaialable.")
exit()
# Create background subtractor
mog2_bg_subtractor = cv.createBackgroundSubtractorMOG2(history=300, varThreshold=50, detectShadows=False)
knn_bg_subtractor = cv.createBackgroundSubtractorKNN(history=300, detectShadows=False)
frame_count = 0
# Allows for a frame buffer for the mask to learn pre known foreground
show_count = 10
while True:
ret, frame = cap.read()
if not ret:
break
x = 100 + (frame_count % 10) * 3
frame = cv.resize(frame, (640, 480))
aKnownForegroundMask = np.zeros(frame.shape[:2], dtype=np.uint8)
# Allow for models to "settle"/learn
if frame_count > show_count:
cv.rectangle(aKnownForegroundMask, (x,200), (x+50,300), 255, -1)
cv.rectangle(aKnownForegroundMask, (540,180), (640,480), 255, -1)
#MOG2 Subtraction
mog2_with_mask = mog2_bg_subtractor.apply(frame,knownForegroundMask=aKnownForegroundMask)
mog2_without_mask = mog2_bg_subtractor.apply(frame)
#KNN Subtraction
knn_with_mask = knn_bg_subtractor.apply(frame,knownForegroundMask=aKnownForegroundMask)
knn_without_mask = knn_bg_subtractor.apply(frame)
# Display the 3 parameter apply and the 4 parameter apply for both subtractors
cv.imshow("MOG2 With a Foreground Mask", mog2_with_mask)
cv.imshow("MOG2 Without a Foreground Mask", mog2_without_mask)
cv.imshow("KNN With a Foreground Mask", knn_with_mask)
cv.imshow("KNN Without a Foreground Mask", knn_without_mask)
key = cv.waitKey(30)
if key == 27: # ESC
break
frame_count += 1
cap.release()
cv.destroyAllWindows()
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+209
View File
@@ -0,0 +1,209 @@
#!/usr/bin/env python
'''
camera calibration for distorted images with chess board samples
reads distorted images, calculates the calibration and write undistorted images
usage:
calibrate.py [--debug <output path>] [-w <width>] [-h <height>] [-t <pattern type>] [--square_size=<square size>]
[--marker_size=<aruco marker size>] [--aruco_dict=<aruco dictionary name>] [<image mask>]
usage example:
calibrate.py -w 4 -h 6 -t chessboard --square_size=50 ../data/left*.jpg
default values:
--debug: ./output/
-w: 4
-h: 6
-t: chessboard
--square_size: 10
--marker_size: 5
--aruco_dict: DICT_4X4_50
--threads: 4
<image mask> defaults to ../data/left*.jpg
NOTE: Chessboard size is defined in inner corners. Charuco board size is defined in units.
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
# local modules
from common import splitfn
# built-in modules
import os
def main():
import sys
import getopt
from glob import glob
args, img_names = getopt.getopt(sys.argv[1:], 'w:h:t:', ['debug=','square_size=', 'marker_size=',
'aruco_dict=', 'threads=', ])
args = dict(args)
args.setdefault('--debug', './output/')
args.setdefault('-w', 4)
args.setdefault('-h', 6)
args.setdefault('-t', 'chessboard')
args.setdefault('--square_size', 10)
args.setdefault('--marker_size', 5)
args.setdefault('--aruco_dict', 'DICT_4X4_50')
args.setdefault('--threads', 4)
if not img_names:
img_mask = '../data/left??.jpg' # default
img_names = glob(img_mask)
debug_dir = args.get('--debug')
if debug_dir and not os.path.isdir(debug_dir):
os.mkdir(debug_dir)
height = int(args.get('-h'))
width = int(args.get('-w'))
pattern_type = str(args.get('-t'))
square_size = float(args.get('--square_size'))
marker_size = float(args.get('--marker_size'))
aruco_dict_name = str(args.get('--aruco_dict'))
pattern_size = (width, height)
if pattern_type == 'chessboard':
pattern_points = np.zeros((np.prod(pattern_size), 3), np.float32)
pattern_points[:, :2] = np.indices(pattern_size).T.reshape(-1, 2)
pattern_points *= square_size
obj_points = []
img_points = []
h, w = cv.imread(img_names[0], cv.IMREAD_GRAYSCALE).shape[:2] # TODO: use imquery call to retrieve results
aruco_dicts = {
'DICT_4X4_50': cv.aruco.DICT_4X4_50,
'DICT_4X4_100': cv.aruco.DICT_4X4_100,
'DICT_4X4_250': cv.aruco.DICT_4X4_250,
'DICT_4X4_1000': cv.aruco.DICT_4X4_1000,
'DICT_5X5_50': cv.aruco.DICT_5X5_50,
'DICT_5X5_100': cv.aruco.DICT_5X5_100,
'DICT_5X5_250': cv.aruco.DICT_5X5_250,
'DICT_5X5_1000': cv.aruco.DICT_5X5_1000,
'DICT_6X6_50': cv.aruco.DICT_6X6_50,
'DICT_6X6_100': cv.aruco.DICT_6X6_100,
'DICT_6X6_250': cv.aruco.DICT_6X6_250,
'DICT_6X6_1000': cv.aruco.DICT_6X6_1000,
'DICT_7X7_50': cv.aruco.DICT_7X7_50,
'DICT_7X7_100': cv.aruco.DICT_7X7_100,
'DICT_7X7_250': cv.aruco.DICT_7X7_250,
'DICT_7X7_1000': cv.aruco.DICT_7X7_1000,
'DICT_ARUCO_ORIGINAL': cv.aruco.DICT_ARUCO_ORIGINAL,
'DICT_APRILTAG_16h5': cv.aruco.DICT_APRILTAG_16h5,
'DICT_APRILTAG_25h9': cv.aruco.DICT_APRILTAG_25h9,
'DICT_APRILTAG_36h10': cv.aruco.DICT_APRILTAG_36h10,
'DICT_APRILTAG_36h11': cv.aruco.DICT_APRILTAG_36h11,
'DICT_ARUCO_MIP_36h12': cv.aruco.DICT_ARUCO_MIP_36h12
}
if (aruco_dict_name not in set(aruco_dicts.keys())):
print("unknown aruco dictionary name")
return None
aruco_dict = cv.aruco.getPredefinedDictionary(aruco_dicts[aruco_dict_name])
board = cv.aruco.CharucoBoard(pattern_size, square_size, marker_size, aruco_dict)
charuco_detector = cv.aruco.CharucoDetector(board)
def processImage(fn):
print('processing %s... ' % fn)
img = cv.imread(fn, cv.IMREAD_GRAYSCALE)
if img is None:
print("Failed to load", fn)
return None
assert w == img.shape[1] and h == img.shape[0], ("size: %d x %d ... " % (img.shape[1], img.shape[0]))
found = False
corners = 0
if pattern_type == 'chessboard':
found, corners = cv.findChessboardCorners(img, pattern_size)
if found:
term = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_COUNT, 30, 0.1)
cv.cornerSubPix(img, corners, (5, 5), (-1, -1), term)
frame_img_points = corners.reshape(-1, 2)
frame_obj_points = pattern_points
elif pattern_type == 'charucoboard':
corners, charucoIds, _, _ = charuco_detector.detectBoard(img)
if (len(corners) > 0):
frame_obj_points, frame_img_points = board.matchImagePoints(corners, charucoIds)
found = True
else:
found = False
else:
print("unknown pattern type", pattern_type)
return None
if debug_dir:
vis = cv.cvtColor(img, cv.COLOR_GRAY2BGR)
if pattern_type == 'chessboard':
cv.drawChessboardCorners(vis, pattern_size, corners, found)
elif pattern_type == 'charucoboard':
cv.aruco.drawDetectedCornersCharuco(vis, corners, charucoIds=charucoIds)
_path, name, _ext = splitfn(fn)
outfile = os.path.join(debug_dir, name + '_board.png')
cv.imwrite(outfile, vis)
if not found:
print('pattern not found')
return None
print(' %s... OK' % fn)
return (frame_img_points, frame_obj_points)
threads_num = int(args.get('--threads'))
if threads_num <= 1:
chessboards = [processImage(fn) for fn in img_names]
else:
print("Run with %d threads..." % threads_num)
from multiprocessing.dummy import Pool as ThreadPool
pool = ThreadPool(threads_num)
chessboards = pool.map(processImage, img_names)
chessboards = [x for x in chessboards if x is not None]
for (corners, pattern_points) in chessboards:
img_points.append(corners)
obj_points.append(pattern_points)
# calculate camera distortion
rms, camera_matrix, dist_coefs, _rvecs, _tvecs = cv.calibrateCamera(obj_points, img_points, (w, h), None, None)
print("\nRMS:", rms)
print("camera matrix:\n", camera_matrix)
print("distortion coefficients: ", dist_coefs.ravel())
# undistort the image with the calibration
print('')
for fn in img_names if debug_dir else []:
_path, name, _ext = splitfn(fn)
img_found = os.path.join(debug_dir, name + '_board.png')
outfile = os.path.join(debug_dir, name + '_undistorted.png')
img = cv.imread(img_found)
if img is None:
continue
h, w = img.shape[:2]
newcameramtx, roi = cv.getOptimalNewCameraMatrix(camera_matrix, dist_coefs, (w, h), 1, (w, h))
dst = cv.undistort(img, camera_matrix, dist_coefs, None, newcameramtx)
# crop and save the image
x, y, w, h = roi
dst = dst[y:y+h, x:x+w]
print('Undistorted image written to: %s' % outfile)
cv.imwrite(outfile, dst)
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+240
View File
@@ -0,0 +1,240 @@
#!/usr/bin/env python
'''
Plot camera calibration extrinsics.
usage:
camera_calibration_show_extrinsics.py [--calibration <input path>] [--cam_width] [--cam_height] [--scale_focal] [--patternCentric ]
default values:
--calibration : left_intrinsics.yml
--cam_width : 0.064/2
--cam_height : 0.048/2
--scale_focal : 40
--patternCentric : True
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
from numpy import linspace
def inverse_homogeneoux_matrix(M):
R = M[0:3, 0:3]
T = M[0:3, 3]
M_inv = np.identity(4)
M_inv[0:3, 0:3] = R.T
M_inv[0:3, 3] = -(R.T).dot(T)
return M_inv
def transform_to_matplotlib_frame(cMo, X, inverse=False):
M = np.identity(4)
M[1,1] = 0
M[1,2] = 1
M[2,1] = -1
M[2,2] = 0
if inverse:
return M.dot(inverse_homogeneoux_matrix(cMo).dot(X))
else:
return M.dot(cMo.dot(X))
def create_camera_model(camera_matrix, width, height, scale_focal, draw_frame_axis=False):
fx = camera_matrix[0,0]
fy = camera_matrix[1,1]
focal = 2 / (fx + fy)
f_scale = scale_focal * focal
# draw image plane
X_img_plane = np.ones((4,5))
X_img_plane[0:3,0] = [-width, height, f_scale]
X_img_plane[0:3,1] = [width, height, f_scale]
X_img_plane[0:3,2] = [width, -height, f_scale]
X_img_plane[0:3,3] = [-width, -height, f_scale]
X_img_plane[0:3,4] = [-width, height, f_scale]
# draw triangle above the image plane
X_triangle = np.ones((4,3))
X_triangle[0:3,0] = [-width, -height, f_scale]
X_triangle[0:3,1] = [0, -2*height, f_scale]
X_triangle[0:3,2] = [width, -height, f_scale]
# draw camera
X_center1 = np.ones((4,2))
X_center1[0:3,0] = [0, 0, 0]
X_center1[0:3,1] = [-width, height, f_scale]
X_center2 = np.ones((4,2))
X_center2[0:3,0] = [0, 0, 0]
X_center2[0:3,1] = [width, height, f_scale]
X_center3 = np.ones((4,2))
X_center3[0:3,0] = [0, 0, 0]
X_center3[0:3,1] = [width, -height, f_scale]
X_center4 = np.ones((4,2))
X_center4[0:3,0] = [0, 0, 0]
X_center4[0:3,1] = [-width, -height, f_scale]
# draw camera frame axis
X_frame1 = np.ones((4,2))
X_frame1[0:3,0] = [0, 0, 0]
X_frame1[0:3,1] = [f_scale/2, 0, 0]
X_frame2 = np.ones((4,2))
X_frame2[0:3,0] = [0, 0, 0]
X_frame2[0:3,1] = [0, f_scale/2, 0]
X_frame3 = np.ones((4,2))
X_frame3[0:3,0] = [0, 0, 0]
X_frame3[0:3,1] = [0, 0, f_scale/2]
if draw_frame_axis:
return [X_img_plane, X_triangle, X_center1, X_center2, X_center3, X_center4, X_frame1, X_frame2, X_frame3]
else:
return [X_img_plane, X_triangle, X_center1, X_center2, X_center3, X_center4]
def create_board_model(extrinsics, board_width, board_height, square_size, draw_frame_axis=False):
width = board_width*square_size
height = board_height*square_size
# draw calibration board
X_board = np.ones((4,5))
#X_board_cam = np.ones((extrinsics.shape[0],4,5))
X_board[0:3,0] = [0,0,0]
X_board[0:3,1] = [width,0,0]
X_board[0:3,2] = [width,height,0]
X_board[0:3,3] = [0,height,0]
X_board[0:3,4] = [0,0,0]
# draw board frame axis
X_frame1 = np.ones((4,2))
X_frame1[0:3,0] = [0, 0, 0]
X_frame1[0:3,1] = [height/2, 0, 0]
X_frame2 = np.ones((4,2))
X_frame2[0:3,0] = [0, 0, 0]
X_frame2[0:3,1] = [0, height/2, 0]
X_frame3 = np.ones((4,2))
X_frame3[0:3,0] = [0, 0, 0]
X_frame3[0:3,1] = [0, 0, height/2]
if draw_frame_axis:
return [X_board, X_frame1, X_frame2, X_frame3]
else:
return [X_board]
def draw_camera_boards(ax, camera_matrix, cam_width, cam_height, scale_focal,
extrinsics, board_width, board_height, square_size,
patternCentric):
from matplotlib import cm
min_values = np.zeros((3,1))
min_values = np.inf
max_values = np.zeros((3,1))
max_values = -np.inf
if patternCentric:
X_moving = create_camera_model(camera_matrix, cam_width, cam_height, scale_focal)
X_static = create_board_model(extrinsics, board_width, board_height, square_size)
else:
X_static = create_camera_model(camera_matrix, cam_width, cam_height, scale_focal, True)
X_moving = create_board_model(extrinsics, board_width, board_height, square_size)
cm_subsection = linspace(0.0, 1.0, extrinsics.shape[0])
colors = [ cm.jet(x) for x in cm_subsection ]
for i in range(len(X_static)):
X = np.zeros(X_static[i].shape)
for j in range(X_static[i].shape[1]):
X[:,j] = transform_to_matplotlib_frame(np.eye(4), X_static[i][:,j])
ax.plot3D(X[0,:], X[1,:], X[2,:], color='r')
min_values = np.minimum(min_values, X[0:3,:].min(1))
max_values = np.maximum(max_values, X[0:3,:].max(1))
for idx in range(extrinsics.shape[0]):
R, _ = cv.Rodrigues(extrinsics[idx,0:3])
cMo = np.eye(4,4)
cMo[0:3,0:3] = R
cMo[0:3,3] = extrinsics[idx,3:6]
for i in range(len(X_moving)):
X = np.zeros(X_moving[i].shape)
for j in range(X_moving[i].shape[1]):
X[0:4,j] = transform_to_matplotlib_frame(cMo, X_moving[i][0:4,j], patternCentric)
ax.plot3D(X[0,:], X[1,:], X[2,:], color=colors[idx])
min_values = np.minimum(min_values, X[0:3,:].min(1))
max_values = np.maximum(max_values, X[0:3,:].max(1))
return min_values, max_values
def main():
import argparse
parser = argparse.ArgumentParser(description='Plot camera calibration extrinsics.',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--calibration', type=str, default='left_intrinsics.yml',
help='YAML camera calibration file.')
parser.add_argument('--cam_width', type=float, default=0.064/2,
help='Width/2 of the displayed camera.')
parser.add_argument('--cam_height', type=float, default=0.048/2,
help='Height/2 of the displayed camera.')
parser.add_argument('--scale_focal', type=float, default=40,
help='Value to scale the focal length.')
parser.add_argument('--patternCentric', action='store_true',
help='The calibration board is static and the camera is moving.')
args = parser.parse_args()
fs = cv.FileStorage(cv.samples.findFile(args.calibration), cv.FILE_STORAGE_READ)
board_width = int(fs.getNode('board_width').real())
board_height = int(fs.getNode('board_height').real())
square_size = fs.getNode('square_size').real()
camera_matrix = fs.getNode('camera_matrix').mat()
extrinsics = fs.getNode('extrinsic_parameters').mat()
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # pylint: disable=unused-variable
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect("auto")
cam_width = args.cam_width
cam_height = args.cam_height
scale_focal = args.scale_focal
min_values, max_values = draw_camera_boards(ax, camera_matrix, cam_width, cam_height,
scale_focal, extrinsics, board_width,
board_height, square_size, args.patternCentric)
X_min = min_values[0]
X_max = max_values[0]
Y_min = min_values[1]
Y_max = max_values[1]
Z_min = min_values[2]
Z_max = max_values[2]
max_range = np.array([X_max-X_min, Y_max-Y_min, Z_max-Z_min]).max() / 2.0
mid_x = (X_max+X_min) * 0.5
mid_y = (Y_max+Y_min) * 0.5
mid_z = (Z_max+Z_min) * 0.5
ax.set_xlim(mid_x - max_range, mid_x + max_range)
ax.set_ylim(mid_y - max_range, mid_y + max_range)
ax.set_zlim(mid_z - max_range, mid_z + max_range)
ax.set_xlabel('x')
ax.set_ylabel('z')
ax.set_zlabel('-y')
ax.set_title('Extrinsic Parameters Visualization')
plt.show()
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+185
View File
@@ -0,0 +1,185 @@
import cv2 as cv
import numpy as np
import argparse
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
from dnn.common import *
def get_args_parser(func_args):
backends = ("default", "openvino", "opencv", "vkcom", "cuda", "webnn")
targets = ("cpu", "opencl", "opencl_fp16", "vpu", "vulkan", "cuda", "cuda_fp16")
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('--zoo', default=os.path.join(os.path.dirname(os.path.abspath(__file__)), '../dnn', 'models.yml'),
help='An optional path to file with preprocessing parameters.')
parser.add_argument('--input', default='mcc_ccm_test.jpg', help='Path to input image for computing CCM')
parser.add_argument('--query', default='baboon.jpg', help='Path to query image to apply color correction')
parser.add_argument('--ccm_file', help='Path to YAML file containing pre-computed CCM parameters')
parser.add_argument('--chart_type', type=int, default=0,
help='chartType: 0-Standard, 1-DigitalSG, 2-Vinyl, default:0')
parser.add_argument('--num_charts', type=int, default=1,
help='Maximum number of charts in the image')
parser.add_argument('--backend', default="default", type=str, choices=backends,
help="Choose one of computation backends: "
"default: automatically (by default), "
"openvino: Intel's Deep Learning Inference Engine (https://software.intel.com/openvino-toolkit), "
"opencv: OpenCV implementation, "
"vkcom: VKCOM, "
"cuda: CUDA, "
"webnn: WebNN")
parser.add_argument('--target', default="cpu", type=str, choices=targets,
help="Choose one of target computation devices: "
"cpu: CPU target (by default), "
"opencl: OpenCL, "
"opencl_fp16: OpenCL fp16 (half-float precision), "
"vpu: VPU, "
"vulkan: Vulkan, "
"cuda: CUDA, "
"cuda_fp16: CUDA fp16 (half-float preprocess)")
args, _ = parser.parse_known_args()
add_preproc_args(args.zoo, parser, 'mcc', 'mcc')
parser = argparse.ArgumentParser(parents=[parser],
description='''
To run:
Default (compute new CCM):
python color_correction_model.py --input=path/to/your/input/image --query=path/to/query/image
DNN model:
python color_correction_model.py mcc --input=path/to/your/input/image --query=path/to/query/image
Using pre-computed CCM:
python color_correction_model.py --ccm_file=path/to/ccm_output.yaml --query=path/to/query/image
Model path can also be specified using --model argument. And config path can be specified using --config.
''', formatter_class=argparse.RawTextHelpFormatter)
return parser.parse_args(func_args)
def process_frame(frame, detector, num_charts):
if not detector.process(frame, num_charts):
return None
checkers = detector.getListColorChecker()
src = checkers[0].getChartsRGB(False)
return src
def main(func_args=None):
args = get_args_parser(func_args)
if not (0 <= args.chart_type <= 2):
raise ValueError("chartType must be 0, 1, or 2")
# Validate arguments based on whether using pre-computed CCM
if args.ccm_file:
if not args.query:
print("[ERROR] Query image path must be provided when using pre-computed CCM.")
return -1
else:
if not args.input:
print("[ERROR] Input image path must be provided when computing new CCM.")
return -1
# Read query image
query_image = None
if args.query:
query_image = cv.imread(findFile(args.query))
if query_image is None:
print("[ERROR] Unable to read query image.")
return -1
if os.getenv('OPENCV_SAMPLES_DATA_PATH') is not None:
try:
args.model = findModel(args.model, args.sha1)
args.config = findModel(args.config, args.config_sha1)
except:
print("[WARN] Model file not provided, using default detector. Pass model using --model and config using --config to use dnn based detector.\n\n")
args.model = None
args.config = None
else:
args.model = None
args.config = None
print("[WARN] Model file not provided, using default detector. Pass model using --model and config using --config to use dnn based detector. Or, set OPENCV_SAMPLES_DATA_PATH environment variable.\n\n")
# Create color correction model
model = cv.ccm.ColorCorrectionModel()
if args.ccm_file:
# Load CCM from YAML file
fs = cv.FileStorage(args.ccm_file, cv.FileStorage_READ)
if not fs.isOpened():
print(f"[ERROR] Unable to open CCM file: {args.ccm_file}")
return -1
model.read(fs.getNode("ColorCorrectionModel"))
fs.release()
print(f"Loaded CCM from file: {args.ccm_file}")
else:
# Read input image for computing new CCM
image = cv.imread(findFile(args.input))
if image is None:
print("[ERROR] Unable to read input image.")
return -1
# Create color checker detector
if args.model and args.config:
# Load the DNN from TensorFlow model
engine = cv.dnn.ENGINE_AUTO
if args.backend != "default" or args.target != "cpu":
engine = cv.dnn.ENGINE_CLASSIC
net = cv.dnn.readNetFromTensorflow(args.model, args.config, engine)
net.setPreferableBackend(get_backend_id(args.backend))
net.setPreferableTarget(get_target_id(args.target))
detector = cv.mcc_CCheckerDetector.create(net)
print("Detecting checkers using neural network.")
else:
detector = cv.mcc_CCheckerDetector.create()
print("Detecting checkers using default method (no DNN).")
detector.setColorChartType(args.chart_type)
# Process image to detect color checker
src = process_frame(image, detector, args.num_charts)
if src is None:
print("No chart detected in the input image!")
return -1
print("Actual colors:", src)
# Convert to double and normalize
src = src.astype(np.float64) / 255.0
# Create and configure color correction model
model = cv.ccm.ColorCorrectionModel(src, cv.ccm.COLORCHECKER_MACBETH)
model.setCcmType(cv.ccm.CCM_LINEAR)
model.setDistance(cv.ccm.DISTANCE_CIE2000)
model.setLinearization(cv.ccm.LINEARIZATION_GAMMA)
model.setLinearizationGamma(2.2)
# Compute color correction matrix
ccm = model.compute()
print("Computed CCM Matrix:\n", ccm)
print("Loss:", model.getLoss())
# Save model parameters to YAML file
fs = cv.FileStorage("ccm_output.yaml", cv.FileStorage_WRITE)
model.write(fs)
fs.release()
print("Model parameters saved to ccm_output.yaml")
# Set query image for correction if not provided
if query_image is None:
print("[WARN] No query image provided, applying color correction on input image")
query_image = image.copy()
# Apply correction to query image
calibrated_image = np.empty_like(query_image)
model.correctImage(query_image, calibrated_image)
cv.imshow("Original Image", query_image)
cv.imshow("Corrected Image", calibrated_image)
cv.waitKey(0)
return 0
if __name__ == "__main__":
main()
+224
View File
@@ -0,0 +1,224 @@
#!/usr/bin/env python
'''
This module contains some common routines used by other samples.
'''
from functools import reduce
import numpy as np
import cv2 as cv
# built-in modules
import os
import itertools as it
from contextlib import contextmanager
image_extensions = ['.bmp', '.jpg', '.jpeg', '.png', '.tif', '.tiff', '.pbm', '.pgm', '.ppm']
class Bunch(object):
def __init__(self, **kw):
self.__dict__.update(kw)
def __str__(self):
return str(self.__dict__)
def splitfn(fn):
path, fn = os.path.split(fn)
name, ext = os.path.splitext(fn)
return path, name, ext
def anorm2(a):
return (a*a).sum(-1)
def anorm(a):
return np.sqrt( anorm2(a) )
def homotrans(H, x, y):
xs = H[0, 0]*x + H[0, 1]*y + H[0, 2]
ys = H[1, 0]*x + H[1, 1]*y + H[1, 2]
s = H[2, 0]*x + H[2, 1]*y + H[2, 2]
return xs/s, ys/s
def to_rect(a):
a = np.ravel(a)
if len(a) == 2:
a = (0, 0, a[0], a[1])
return np.array(a, np.float64).reshape(2, 2)
def rect2rect_mtx(src, dst):
src, dst = to_rect(src), to_rect(dst)
cx, cy = (dst[1] - dst[0]) / (src[1] - src[0])
tx, ty = dst[0] - src[0] * (cx, cy)
M = np.float64([[ cx, 0, tx],
[ 0, cy, ty],
[ 0, 0, 1]])
return M
def lookat(eye, target, up = (0, 0, 1)):
fwd = np.asarray(target, np.float64) - eye
fwd /= anorm(fwd)
right = np.cross(fwd, up)
right /= anorm(right)
down = np.cross(fwd, right)
R = np.float64([right, down, fwd])
tvec = -np.dot(R, eye)
return R, tvec
def mtx2rvec(R):
w, u, vt = cv.SVDecomp(R - np.eye(3))
p = vt[0] + u[:,0]*w[0] # same as np.dot(R, vt[0])
c = np.dot(vt[0], p)
s = np.dot(vt[1], p)
axis = np.cross(vt[0], vt[1])
return axis * np.arctan2(s, c)
def draw_str(dst, target, s):
x, y = target
cv.putText(dst, s, (x+1, y+1), cv.FONT_HERSHEY_PLAIN, 1.0, (0, 0, 0), thickness = 2, lineType=cv.LINE_AA)
cv.putText(dst, s, (x, y), cv.FONT_HERSHEY_PLAIN, 1.0, (255, 255, 255), lineType=cv.LINE_AA)
class Sketcher:
def __init__(self, windowname, dests, colors_func):
self.prev_pt = None
self.windowname = windowname
self.dests = dests
self.colors_func = colors_func
self.dirty = False
self.show()
cv.setMouseCallback(self.windowname, self.on_mouse)
def show(self):
cv.imshow(self.windowname, self.dests[0])
def on_mouse(self, event, x, y, flags, param):
pt = (x, y)
if event == cv.EVENT_LBUTTONDOWN:
self.prev_pt = pt
elif event == cv.EVENT_LBUTTONUP:
self.prev_pt = None
if self.prev_pt and flags & cv.EVENT_FLAG_LBUTTON:
for dst, color in zip(self.dests, self.colors_func()):
cv.line(dst, self.prev_pt, pt, color, 5)
self.dirty = True
self.prev_pt = pt
self.show()
# palette data from matplotlib/_cm.py
_jet_data = {'red': ((0., 0, 0), (0.35, 0, 0), (0.66, 1, 1), (0.89,1, 1),
(1, 0.5, 0.5)),
'green': ((0., 0, 0), (0.125,0, 0), (0.375,1, 1), (0.64,1, 1),
(0.91,0,0), (1, 0, 0)),
'blue': ((0., 0.5, 0.5), (0.11, 1, 1), (0.34, 1, 1), (0.65,0, 0),
(1, 0, 0))}
cmap_data = { 'jet' : _jet_data }
def make_cmap(name, n=256):
data = cmap_data[name]
xs = np.linspace(0.0, 1.0, n)
channels = []
eps = 1e-6
for ch_name in ['blue', 'green', 'red']:
ch_data = data[ch_name]
xp, yp = [], []
for x, y1, y2 in ch_data:
xp += [x, x+eps]
yp += [y1, y2]
ch = np.interp(xs, xp, yp)
channels.append(ch)
return np.uint8(np.array(channels).T*255)
def nothing(*arg, **kw):
pass
def clock():
return cv.getTickCount() / cv.getTickFrequency()
@contextmanager
def Timer(msg):
print(msg, '...',)
start = clock()
try:
yield
finally:
print("%.2f ms" % ((clock()-start)*1000))
class StatValue:
def __init__(self, smooth_coef = 0.5):
self.value = None
self.smooth_coef = smooth_coef
def update(self, v):
if self.value is None:
self.value = v
else:
c = self.smooth_coef
self.value = c * self.value + (1.0-c) * v
class RectSelector:
def __init__(self, win, callback):
self.win = win
self.callback = callback
cv.setMouseCallback(win, self.onmouse)
self.drag_start = None
self.drag_rect = None
def onmouse(self, event, x, y, flags, param):
x, y = np.int16([x, y]) # BUG
if event == cv.EVENT_LBUTTONDOWN:
self.drag_start = (x, y)
return
if self.drag_start:
if flags & cv.EVENT_FLAG_LBUTTON:
xo, yo = self.drag_start
x0, y0 = np.minimum([xo, yo], [x, y])
x1, y1 = np.maximum([xo, yo], [x, y])
self.drag_rect = None
if x1-x0 > 0 and y1-y0 > 0:
self.drag_rect = (x0, y0, x1, y1)
else:
rect = self.drag_rect
self.drag_start = None
self.drag_rect = None
if rect:
self.callback(rect)
def draw(self, vis):
if not self.drag_rect:
return False
x0, y0, x1, y1 = self.drag_rect
cv.rectangle(vis, (x0, y0), (x1, y1), (0, 255, 0), 2)
return True
@property
def dragging(self):
return self.drag_rect is not None
def grouper(n, iterable, fillvalue=None):
'''grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx'''
args = [iter(iterable)] * n
output = it.zip_longest(fillvalue=fillvalue, *args)
return output
def mosaic(w, imgs):
'''Make a grid from images.
w -- number of grid columns
imgs -- images (must have same size and format)
'''
imgs = iter(imgs)
img0 = next(imgs)
pad = np.zeros_like(img0)
imgs = it.chain([img0], imgs)
rows = grouper(w, imgs, pad)
return np.vstack(list(map(np.hstack, rows)))
def getsize(img):
h, w = img.shape[:2]
return w, h
def mdot(*args):
return reduce(np.dot, args)
def draw_keypoints(vis, keypoints, color = (0, 255, 255)):
for kp in keypoints:
x, y = kp.pt
cv.circle(vis, (int(x), int(y)), 2, color)
+179
View File
@@ -0,0 +1,179 @@
#!/usr/bin/env python
'''
Sample-launcher application.
'''
import sys
# local modules
from common import splitfn
# built-in modules
import webbrowser
from glob import glob
from subprocess import Popen
import tkinter as tk
from tkinter.scrolledtext import ScrolledText
#from IPython.Shell import IPShellEmbed
#ipshell = IPShellEmbed()
exclude_list = ['demo', 'common']
class LinkManager:
def __init__(self, text, url_callback = None):
self.text = text
self.text.tag_config("link", foreground="blue", underline=1)
self.text.tag_bind("link", "<Enter>", self._enter)
self.text.tag_bind("link", "<Leave>", self._leave)
self.text.tag_bind("link", "<Button-1>", self._click)
self.url_callback = url_callback
self.reset()
def reset(self):
self.links = {}
def add(self, action):
# add an action to the manager. returns tags to use in
# associated text widget
tag = "link-%d" % len(self.links)
self.links[tag] = action
return "link", tag
def _enter(self, event):
self.text.config(cursor="hand2")
def _leave(self, event):
self.text.config(cursor="")
def _click(self, event):
for tag in self.text.tag_names(tk.CURRENT):
if tag.startswith("link-"):
proc = self.links[tag]
if callable(proc):
proc()
else:
if self.url_callback:
self.url_callback(proc)
class App:
def __init__(self):
root = tk.Tk()
root.title('OpenCV Demo')
self.win = win = tk.PanedWindow(root, orient=tk.HORIZONTAL, sashrelief=tk.RAISED, sashwidth=4)
self.win.pack(fill=tk.BOTH, expand=1)
left = tk.Frame(win)
right = tk.Frame(win)
win.add(left)
win.add(right)
scrollbar = tk.Scrollbar(left, orient=tk.VERTICAL)
self.demos_lb = demos_lb = tk.Listbox(left, yscrollcommand=scrollbar.set)
scrollbar.config(command=demos_lb.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
demos_lb.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
self.samples = {}
for fn in glob('*.py'):
name = splitfn(fn)[1]
if fn[0] != '_' and name not in exclude_list:
self.samples[name] = fn
for name in sorted(self.samples):
demos_lb.insert(tk.END, name)
demos_lb.bind('<<ListboxSelect>>', self.on_demo_select)
self.cmd_entry = cmd_entry = tk.Entry(right)
cmd_entry.bind('<Return>', self.on_run)
run_btn = tk.Button(right, command=self.on_run, text='Run', width=8)
self.text = text = ScrolledText(right, font=('arial', 12, 'normal'), width = 30, wrap='word')
self.linker = _linker = LinkManager(text, self.on_link)
self.text.tag_config("header1", font=('arial', 14, 'bold'))
self.text.tag_config("header2", font=('arial', 12, 'bold'))
text.config(state='disabled')
text.pack(fill='both', expand=1, side=tk.BOTTOM)
cmd_entry.pack(fill='x', side='left' , expand=1)
run_btn.pack()
def on_link(self, url):
print(url)
webbrowser.open(url)
def on_demo_select(self, evt):
selection = self.demos_lb.curselection()
if not selection:
return
name = self.demos_lb.get(selection[0])
fn = self.samples[name]
descr = ""
try:
module_globals = {}
module_locals = {}
with open(fn, 'r') as f:
module_code = f.read()
exec(compile(module_code, fn, 'exec'), module_globals, module_locals)
descr = module_locals.get('__doc__', 'no-description')
except Exception as e:
descr = str(e)
self.linker.reset()
self.text.config(state='normal')
self.text.delete(1.0, tk.END)
self.format_text(descr)
self.text.config(state='disabled')
self.cmd_entry.delete(0, tk.END)
self.cmd_entry.insert(0, fn)
def format_text(self, s):
text = self.text
lines = s.splitlines()
for i, s in enumerate(lines):
s = s.rstrip()
if i == 0 and not s:
continue
if s and s == '='*len(s):
text.tag_add('header1', 'end-2l', 'end-1l')
elif s and s == '-'*len(s):
text.tag_add('header2', 'end-2l', 'end-1l')
else:
text.insert('end', s+'\n')
def add_link(start, end, url):
for tag in self.linker.add(url):
text.tag_add(tag, start, end)
self.match_text(r'http://\S+', add_link)
def match_text(self, pattern, tag_proc, regexp=True):
text = self.text
text.mark_set('matchPos', '1.0')
count = tk.IntVar()
while True:
match_index = text.search(pattern, 'matchPos', count=count, regexp=regexp, stopindex='end')
if not match_index:
break
end_index = text.index( "%s+%sc" % (match_index, count.get()) )
text.mark_set('matchPos', end_index)
if callable(tag_proc):
tag_proc(match_index, end_index, text.get(match_index, end_index))
else:
text.tag_add(tag_proc, match_index, end_index)
def on_run(self, *args):
cmd = self.cmd_entry.get()
print('running:', cmd)
Popen(sys.executable + ' ' + cmd, shell=True)
def run(self):
tk.mainloop()
if __name__ == '__main__':
App().run()
+191
View File
@@ -0,0 +1,191 @@
#!/usr/bin/env python
'''
This program demonstrates OpenCV drawing and text output functions by drawing different shapes and text strings
Usage :
python3 drawing.py
Press any button to exit
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
# Drawing Lines
def lines():
for i in range(NUMBER*2):
pt1, pt2 = [], []
pt1.append(np.random.randint(x1, x2))
pt1.append(np.random.randint(y1, y2))
pt2.append(np.random.randint(x1, x2))
pt2.append(np.random.randint(y1, y2))
color = "%06x" % np.random.randint(0, 0xFFFFFF)
color = tuple(int(color[i:i+2], 16) for i in (0, 2 ,4))
arrowed = np.random.randint(0, 6)
if (arrowed<3):
cv.line(image, tuple(pt1), tuple(pt2), color, np.random.randint(1, 10), lineType)
else:
cv.arrowedLine(image, tuple(pt1), tuple(pt2), color, np.random.randint(1, 10), lineType)
cv.imshow(wndname, image)
if cv.waitKey(DELAY)>=0:
return
# Drawing Rectangle
def rectangle():
for i in range(NUMBER*2):
pt1, pt2 = [], []
pt1.append(np.random.randint(x1, x2))
pt1.append(np.random.randint(y1, y2))
pt2.append(np.random.randint(x1, x2))
pt2.append(np.random.randint(y1, y2))
color = "%06x" % np.random.randint(0, 0xFFFFFF)
color = tuple(int(color[i:i+2], 16) for i in (0, 2 ,4))
thickness = np.random.randint(-3, 10)
marker = np.random.randint(0, 10)
marker_size = np.random.randint(30, 80)
if (marker > 5):
cv.rectangle(image, tuple(pt1), tuple(pt2), color, max(thickness, -1), lineType)
else:
cv.drawMarker(image, tuple(pt1), color, marker, marker_size)
cv.imshow(wndname, image)
if cv.waitKey(DELAY)>=0:
return
# Drawing ellipse
def ellipse():
for i in range(NUMBER*2):
center = []
center.append(np.random.randint(x1, x2))
center.append(np.random.randint(y1, y2))
axes = []
axes.append(np.random.randint(0, 200))
axes.append(np.random.randint(0, 200))
angle = np.random.randint(0, 180)
color = "%06x" % np.random.randint(0, 0xFFFFFF)
color = tuple(int(color[i:i+2], 16) for i in (0, 2 ,4))
thickness = np.random.randint(-1, 9)
cv.ellipse(image, tuple(center), tuple(axes), angle, angle-100, angle + 200, color, thickness, lineType)
cv.imshow(wndname, image)
if cv.waitKey(DELAY)>=0:
return
# Drawing Polygonal Curves
def polygonal():
for i in range(NUMBER):
pt = [(0, 0)]*6
pt = np.resize(pt, (2, 3, 2))
pt[0][0][0] = np.random.randint(x1, x2)
pt[0][0][1] = np.random.randint(y1, y2)
pt[0][1][0] = np.random.randint(x1, x2)
pt[0][1][1] = np.random.randint(y1, y2)
pt[0][2][0] = np.random.randint(x1, x2)
pt[0][2][1] = np.random.randint(y1, y2)
pt[1][0][0] = np.random.randint(x1, x2)
pt[1][0][1] = np.random.randint(y1, y2)
pt[1][1][0] = np.random.randint(x1, x2)
pt[1][1][1] = np.random.randint(y1, y2)
pt[1][2][0] = np.random.randint(x1, x2)
pt[1][2][1] = np.random.randint(y1, y2)
color = "%06x" % np.random.randint(0, 0xFFFFFF)
color = tuple(int(color[i:i+2], 16) for i in (0, 2 ,4))
alist = []
for k in pt[0]:
alist.append(k)
for k in pt[1]:
alist.append(k)
ppt = np.array(alist)
cv.polylines(image, [ppt], True, color, thickness = np.random.randint(1, 10), lineType = lineType)
cv.imshow(wndname, image)
if cv.waitKey(DELAY) >= 0:
return
# fills an area bounded by several polygonal contours
def fill():
for i in range(NUMBER):
pt = [(0, 0)]*6
pt = np.resize(pt, (2, 3, 2))
pt[0][0][0] = np.random.randint(x1, x2)
pt[0][0][1] = np.random.randint(y1, y2)
pt[0][1][0] = np.random.randint(x1, x2)
pt[0][1][1] = np.random.randint(y1, y2)
pt[0][2][0] = np.random.randint(x1, x2)
pt[0][2][1] = np.random.randint(y1, y2)
pt[1][0][0] = np.random.randint(x1, x2)
pt[1][0][1] = np.random.randint(y1, y2)
pt[1][1][0] = np.random.randint(x1, x2)
pt[1][1][1] = np.random.randint(y1, y2)
pt[1][2][0] = np.random.randint(x1, x2)
pt[1][2][1] = np.random.randint(y1, y2)
color = "%06x" % np.random.randint(0, 0xFFFFFF)
color = tuple(int(color[i:i+2], 16) for i in (0, 2 ,4))
alist = []
for k in pt[0]:
alist.append(k)
for k in pt[1]:
alist.append(k)
ppt = np.array(alist)
cv.fillPoly(image, [ppt], color, lineType)
cv.imshow(wndname, image)
if cv.waitKey(DELAY) >= 0:
return
# Drawing Circles
def circles():
for i in range(NUMBER):
center = []
center.append(np.random.randint(x1, x2))
center.append(np.random.randint(y1, y2))
color = "%06x" % np.random.randint(0, 0xFFFFFF)
color = tuple(int(color[i:i+2], 16) for i in (0, 2 ,4))
cv.circle(image, tuple(center), np.random.randint(0, 300), color, np.random.randint(-1, 9), lineType)
cv.imshow(wndname, image)
if cv.waitKey(DELAY) >= 0:
return
# Draws a text string
def string():
for i in range(NUMBER):
org = []
org.append(np.random.randint(x1, x2))
org.append(np.random.randint(y1, y2))
color = "%06x" % np.random.randint(0, 0xFFFFFF)
color = tuple(int(color[i:i+2], 16) for i in (0, 2 ,4))
cv.putText(image, "Testing text rendering", tuple(org), np.random.randint(0, 8), np.random.randint(0, 100)*0.05+0.1, color, np.random.randint(1, 10), lineType)
cv.imshow(wndname, image)
if cv.waitKey(DELAY) >= 0:
return
def string1():
textsize = cv.getTextSize("OpenCV forever!", cv.FONT_HERSHEY_COMPLEX, 3, 5)
org = (int((width - textsize[0][0])/2), int((height - textsize[0][1])/2))
for i in range(0, 255, 2):
image2 = np.array(image) - i
cv.putText(image2, "OpenCV forever!", org, cv.FONT_HERSHEY_COMPLEX, 3, (i, i, 255), 5, lineType)
cv.imshow(wndname, image2)
if cv.waitKey(DELAY) >= 0:
return
if __name__ == '__main__':
print(__doc__)
wndname = "Drawing Demo"
NUMBER = 100
DELAY = 5
width, height = 1000, 700
lineType = cv.LINE_AA # change it to LINE_8 to see non-antialiased graphics
x1, x2, y1, y2 = -width/2, width*3/2, -height/2, height*3/2
image = np.zeros((height, width, 3), dtype = np.uint8)
cv.imshow(wndname, image)
cv.waitKey(DELAY)
lines()
rectangle()
ellipse()
polygonal()
fill()
circles()
string()
string1()
cv.waitKey(0)
cv.destroyAllWindows()
+133
View File
@@ -0,0 +1,133 @@
import numpy as np, cv2 as cv, time, sys, os
def getEpipolarError(F, pts1_, pts2_, inliers):
pts1 = np.concatenate((pts1_.T, np.ones((1, pts1_.shape[0]))))[:,inliers]
pts2 = np.concatenate((pts2_.T, np.ones((1, pts2_.shape[0]))))[:,inliers]
lines2 = np.dot(F , pts1)
lines1 = np.dot(F.T, pts2)
return np.median((np.abs(np.sum(pts1 * lines1, axis=0)) / np.sqrt(lines1[0,:]**2 + lines1[1,:]**2) +
np.abs(np.sum(pts2 * lines2, axis=0)) / np.sqrt(lines2[0,:]**2 + lines2[1,:]**2))/2)
if __name__ == '__main__':
if len(sys.argv) < 3:
print("Path to data file and directory to image files are missing!\nData file must have"
" format:\n--------------\n image_name_1\nimage_name_2\nk11 k12 k13\n0 k22 k23\n"
"0 0 1\n--------------\nIf image_name_{1,2} are not in the same directory as "
"the data file then add argument with directory to image files.\nFor example: "
"python essential_mat_reconstr.py essential_mat_data.txt ./")
exit(1)
else:
data_file = sys.argv[1]
image_dir = sys.argv[2]
if not os.path.isfile(data_file):
print('Incorrect path to data file!')
exit(1)
with open(data_file, 'r') as f:
image1 = cv.imread(image_dir+f.readline()[:-1]) # remove '\n'
image2 = cv.imread(image_dir+f.readline()[:-1])
K = np.array([[float(x) for x in f.readline().split(' ')],
[float(x) for x in f.readline().split(' ')],
[float(x) for x in f.readline().split(' ')]])
if image1 is None or image2 is None:
print('Incorrect directory to images!')
exit(1)
if K.shape != (3,3):
print('Intrinsic matrix has incorrect format!')
exit(1)
print('find keypoints and compute descriptors')
detector = cv.SIFT_create(nfeatures=20000)
keypoints1, descriptors1 = detector.detectAndCompute(cv.cvtColor(image1, cv.COLOR_BGR2GRAY), None)
keypoints2, descriptors2 = detector.detectAndCompute(cv.cvtColor(image2, cv.COLOR_BGR2GRAY), None)
matcher = cv.FlannBasedMatcher(dict(algorithm=0, trees=5), dict(checks=32))
print('match with FLANN, size of descriptors', descriptors1.shape, descriptors2.shape)
matches_vector = matcher.knnMatch(descriptors1, descriptors2, k=2)
print('find good keypoints')
pts1 = []; pts2 = []
for m in matches_vector:
# compare best and second match using Lowe ratio test
if m[0].distance / m[1].distance < 0.75:
pts1.append(keypoints1[m[0].queryIdx].pt)
pts2.append(keypoints2[m[0].trainIdx].pt)
pts1 = np.array(pts1); pts2 = np.array(pts2)
print('points size', pts1.shape[0])
print('Essential matrix RANSAC')
start = time.time()
E, inliers = cv.findEssentialMat(pts1, pts2, K, cv.RANSAC, 0.999, 1.0)
print('RANSAC time', time.time() - start, 'seconds')
print('Median error to epipolar lines', getEpipolarError
(np.dot(np.linalg.inv(K).T, np.dot(E, np.linalg.inv(K))), pts1, pts2, inliers.squeeze()),
'number of inliers', inliers.sum())
print('Decompose essential matrix')
R1, R2, t = cv.decomposeEssentialMat(E)
# Assume relative pose. Fix the first camera
P1 = np.concatenate((K, np.zeros((3,1))), axis=1) # K [I | 0]
P2s = [np.dot(K, np.concatenate((R1, t), axis=1)), # K[R1 | t]
np.dot(K, np.concatenate((R1, -t), axis=1)), # K[R1 | -t]
np.dot(K, np.concatenate((R2, t), axis=1)), # K[R2 | t]
np.dot(K, np.concatenate((R2, -t), axis=1))] # K[R2 | -t]
obj_pts_per_cam = []
# enumerate over all P2 projection matrices
for cam_idx, P2 in enumerate(P2s):
obj_pts = []
for i, (pt1, pt2) in enumerate(zip(pts1, pts2)):
if not inliers[i]:
continue
# find object point by triangulation of image points by projection matrices
obj_pt = cv.triangulatePoints(P1, P2, pt1, pt2)
obj_pt /= obj_pt[3]
# check if reprojected point has positive depth
if obj_pt[2] > 0:
obj_pts.append([obj_pt[0], obj_pt[1], obj_pt[2]])
obj_pts_per_cam.append(obj_pts)
best_cam_idx = np.array([len(obj_pts_per_cam[0]),len(obj_pts_per_cam[1]),
len(obj_pts_per_cam[2]),len(obj_pts_per_cam[3])]).argmax()
max_pts = len(obj_pts_per_cam[best_cam_idx])
print('Number of object points', max_pts)
# filter object points to have reasonable depth
MAX_DEPTH = 6.
obj_pts = []
for pt in obj_pts_per_cam[best_cam_idx]:
if pt[2] < MAX_DEPTH:
obj_pts.append(pt)
obj_pts = np.array(obj_pts).reshape(len(obj_pts), 3)
# visualize image points
for i, (pt1, pt2) in enumerate(zip(pts1, pts2)):
if inliers[i]:
cv.circle(image1, (int(pt1[0]), int(pt1[1])), 7, (255,0,0), -1)
cv.circle(image2, (int(pt2[0]), int(pt2[1])), 7, (255,0,0), -1)
# concatenate two images
image1 = np.concatenate((image1, image2), axis=1)
# resize concatenated image
new_img_size = 1200. * 800.
image1 = cv.resize(image1, (int(np.sqrt(image1.shape[1] * new_img_size / image1.shape[0])),
int(np.sqrt (image1.shape[0] * new_img_size / image1.shape[1]))))
# plot object points
color = [1.0, 0.0, 0.0]
colors = np.tile(color, (obj_pts.shape[0], 1))
obj_pts = np.concatenate((obj_pts, colors), axis=1)
obj_pts= np.float32(obj_pts)
cv.viz3d.showPoints("window", "points", obj_pts)
cv.viz3d.setGridVisible("window", True)
# save figures
cv.imshow("matches", image1)
cv.imwrite('matches_E.png', image1)
cv.waitKey(0)
+88
View File
@@ -0,0 +1,88 @@
#!/usr/bin/env python
'''
Floodfill sample.
Usage:
floodfill.py [<image>]
Click on the image to set seed point
Keys:
f - toggle floating range
c - toggle 4/8 connectivity
ESC - exit
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
import sys
class App():
def update(self, dummy=None):
if self.seed_pt is None:
cv.imshow('floodfill', self.img)
return
flooded = self.img.copy()
self.mask[:] = 0
lo = cv.getTrackbarPos('lo', 'floodfill')
hi = cv.getTrackbarPos('hi', 'floodfill')
flags = self.connectivity
if self.fixed_range:
flags |= cv.FLOODFILL_FIXED_RANGE
cv.floodFill(flooded, self.mask, self.seed_pt, (255, 255, 255), (lo,)*3, (hi,)*3, flags)
cv.circle(flooded, self.seed_pt, 2, (0, 0, 255), -1)
cv.imshow('floodfill', flooded)
def onmouse(self, event, x, y, flags, param):
if flags & cv.EVENT_FLAG_LBUTTON:
self.seed_pt = x, y
self.update()
def run(self):
try:
fn = sys.argv[1]
except:
fn = 'fruits.jpg'
self.img = cv.imread(cv.samples.findFile(fn))
if self.img is None:
print('Failed to load image file:', fn)
sys.exit(1)
h, w = self.img.shape[:2]
self.mask = np.zeros((h+2, w+2), np.uint8)
self.seed_pt = None
self.fixed_range = True
self.connectivity = 4
self.update()
cv.setMouseCallback('floodfill', self.onmouse)
cv.createTrackbar('lo', 'floodfill', 20, 255, self.update)
cv.createTrackbar('hi', 'floodfill', 20, 255, self.update)
while True:
ch = cv.waitKey()
if ch == 27:
break
if ch == ord('f'):
self.fixed_range = not self.fixed_range
print('using %s range' % ('floating', 'fixed')[self.fixed_range])
self.update()
if ch == ord('c'):
self.connectivity = 12-self.connectivity
print('connectivity =', self.connectivity)
self.update()
print('Done')
if __name__ == '__main__':
print(__doc__)
App().run()
cv.destroyAllWindows()
+183
View File
@@ -0,0 +1,183 @@
#!/usr/bin/env python
'''
===============================================================================
Interactive Image Segmentation using GrabCut algorithm.
This sample shows interactive image segmentation using grabcut algorithm.
USAGE:
python grabcut.py <filename>
README FIRST:
Two windows will show up, one for input and one for output.
At first, in input window, draw a rectangle around the object using the
right mouse button. Then press 'n' to segment the object (once or a few times)
For any finer touch-ups, you can press any of the keys below and draw lines on
the areas you want. Then again press 'n' to update the output.
Key '0' - To select areas of sure background
Key '1' - To select areas of sure foreground
Key '2' - To select areas of probable background
Key '3' - To select areas of probable foreground
Key 'n' - To update the segmentation
Key 'r' - To reset the setup
Key 's' - To save the results
===============================================================================
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
import sys
class App():
BLUE = [255,0,0] # rectangle color
RED = [0,0,255] # PR BG
GREEN = [0,255,0] # PR FG
BLACK = [0,0,0] # sure BG
WHITE = [255,255,255] # sure FG
DRAW_BG = {'color' : BLACK, 'val' : 0}
DRAW_FG = {'color' : WHITE, 'val' : 1}
DRAW_PR_BG = {'color' : RED, 'val' : 2}
DRAW_PR_FG = {'color' : GREEN, 'val' : 3}
# setting up flags
rect = (0,0,1,1)
drawing = False # flag for drawing curves
rectangle = False # flag for drawing rect
rect_over = False # flag to check if rect drawn
rect_or_mask = 100 # flag for selecting rect or mask mode
value = DRAW_FG # drawing initialized to FG
thickness = 3 # brush thickness
def onmouse(self, event, x, y, flags, param):
# Draw Rectangle
if event == cv.EVENT_RBUTTONDOWN:
self.rectangle = True
self.ix, self.iy = x,y
elif event == cv.EVENT_MOUSEMOVE:
if self.rectangle == True:
self.img = self.img2.copy()
cv.rectangle(self.img, (self.ix, self.iy), (x, y), self.BLUE, 2)
self.rect = (min(self.ix, x), min(self.iy, y), abs(self.ix - x), abs(self.iy - y))
self.rect_or_mask = 0
elif event == cv.EVENT_RBUTTONUP:
self.rectangle = False
self.rect_over = True
cv.rectangle(self.img, (self.ix, self.iy), (x, y), self.BLUE, 2)
self.rect = (min(self.ix, x), min(self.iy, y), abs(self.ix - x), abs(self.iy - y))
self.rect_or_mask = 0
print(" Now press the key 'n' a few times until no further change \n")
# draw touchup curves
if event == cv.EVENT_LBUTTONDOWN:
if self.rect_over == False:
print("first draw rectangle \n")
else:
self.drawing = True
cv.circle(self.img, (x,y), self.thickness, self.value['color'], -1)
cv.circle(self.mask, (x,y), self.thickness, self.value['val'], -1)
elif event == cv.EVENT_MOUSEMOVE:
if self.drawing == True:
cv.circle(self.img, (x, y), self.thickness, self.value['color'], -1)
cv.circle(self.mask, (x, y), self.thickness, self.value['val'], -1)
elif event == cv.EVENT_LBUTTONUP:
if self.drawing == True:
self.drawing = False
cv.circle(self.img, (x, y), self.thickness, self.value['color'], -1)
cv.circle(self.mask, (x, y), self.thickness, self.value['val'], -1)
def run(self):
# Loading images
if len(sys.argv) == 2:
filename = sys.argv[1] # for drawing purposes
else:
print("No input image given, so loading default image, lena.jpg \n")
print("Correct Usage: python grabcut.py <filename> \n")
filename = 'lena.jpg'
self.img = cv.imread(cv.samples.findFile(filename))
self.img2 = self.img.copy() # a copy of original image
self.mask = np.zeros(self.img.shape[:2], dtype = np.uint8) # mask initialized to PR_BG
self.output = np.zeros(self.img.shape, np.uint8) # output image to be shown
# input and output windows
cv.namedWindow('output')
cv.namedWindow('input')
cv.setMouseCallback('input', self.onmouse)
cv.moveWindow('input', self.img.shape[1]+10,90)
print(" Instructions: \n")
print(" Draw a rectangle around the object using right mouse button \n")
while(1):
cv.imshow('output', self.output)
cv.imshow('input', self.img)
k = cv.waitKey(1)
# key bindings
if k == 27: # esc to exit
break
elif k == ord('0'): # BG drawing
print(" mark background regions with left mouse button \n")
self.value = self.DRAW_BG
elif k == ord('1'): # FG drawing
print(" mark foreground regions with left mouse button \n")
self.value = self.DRAW_FG
elif k == ord('2'): # PR_BG drawing
self.value = self.DRAW_PR_BG
elif k == ord('3'): # PR_FG drawing
self.value = self.DRAW_PR_FG
elif k == ord('s'): # save image
bar = np.zeros((self.img.shape[0], 5, 3), np.uint8)
res = np.hstack((self.img2, bar, self.img, bar, self.output))
cv.imwrite('grabcut_output.png', res)
print(" Result saved as image \n")
elif k == ord('r'): # reset everything
print("resetting \n")
self.rect = (0,0,1,1)
self.drawing = False
self.rectangle = False
self.rect_or_mask = 100
self.rect_over = False
self.value = self.DRAW_FG
self.img = self.img2.copy()
self.mask = np.zeros(self.img.shape[:2], dtype = np.uint8) # mask initialized to PR_BG
self.output = np.zeros(self.img.shape, np.uint8) # output image to be shown
elif k == ord('n'): # segment the image
print(""" For finer touchups, mark foreground and background after pressing keys 0-3
and again press 'n' \n""")
try:
bgdmodel = np.zeros((1, 65), np.float64)
fgdmodel = np.zeros((1, 65), np.float64)
if (self.rect_or_mask == 0): # grabcut with rect
cv.grabCut(self.img2, self.mask, self.rect, bgdmodel, fgdmodel, 1, cv.GC_INIT_WITH_RECT)
self.rect_or_mask = 1
elif (self.rect_or_mask == 1): # grabcut with mask
cv.grabCut(self.img2, self.mask, self.rect, bgdmodel, fgdmodel, 1, cv.GC_INIT_WITH_MASK)
except:
import traceback
traceback.print_exc()
mask2 = np.where((self.mask==1) + (self.mask==3), 255, 0).astype('uint8')
self.output = cv.bitwise_and(self.img2, self.img2, mask=mask2)
print('Done')
if __name__ == '__main__':
print(__doc__)
App().run()
cv.destroyAllWindows()
+74
View File
@@ -0,0 +1,74 @@
#!/usr/bin/env python
''' An example of Laplacian Pyramid construction and merging.
Level : Intermediate
Usage : python lappyr.py [<video source>]
References:
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.54.299
Alexander Mordvintsev 6/10/12
'''
import numpy as np
import cv2 as cv
import video
from common import nothing, getsize
def build_lappyr(img, leveln=6, dtype=np.int16):
img = dtype(img)
levels = []
for _i in range(leveln-1):
next_img = cv.pyrDown(img)
img1 = cv.pyrUp(next_img, dstsize=getsize(img))
levels.append(img-img1)
img = next_img
levels.append(img)
return levels
def merge_lappyr(levels):
img = levels[-1]
for lev_img in levels[-2::-1]:
img = cv.pyrUp(img, dstsize=getsize(lev_img))
img += lev_img
return np.uint8(np.clip(img, 0, 255))
def main():
import sys
try:
fn = sys.argv[1]
except:
fn = 0
cap = video.create_capture(fn)
leveln = 6
cv.namedWindow('level control')
for i in range(leveln):
cv.createTrackbar('%d'%i, 'level control', 5, 50, nothing)
while True:
_ret, frame = cap.read()
pyr = build_lappyr(frame, leveln)
for i in range(leveln):
v = int(cv.getTrackbarPos('%d'%i, 'level control') / 5)
pyr[i] *= v
res = merge_lappyr(pyr)
cv.imshow('laplacian pyramid filter', res)
if cv.waitKey(1) == 27:
break
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+155
View File
@@ -0,0 +1,155 @@
import cv2 as cv
import numpy as np
import argparse
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
from dnn.common import *
def get_args_parser(func_args):
backends = ("default", "openvino", "opencv", "vkcom", "cuda")
targets = ("cpu", "opencl", "opencl_fp16", "ncs2_vpu", "hddl_vpu", "vulkan", "cuda", "cuda_fp16")
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('--zoo', default=os.path.join(os.path.dirname(os.path.abspath(__file__)), '../dnn', 'models.yml'),
help='An optional path to file with preprocessing parameters.')
parser.add_argument('--input', help='Path to input image or video file. Skip this argument to capture frames from a camera.', default=0, required=False)
parser.add_argument('--method', help='choose method: dexined or canny', default='canny', required=False)
parser.add_argument('--chart_type', type=int, default=0,
help='chartType: 0-Standard, 1-DigitalSG, 2-Vinyl, default:0')
parser.add_argument('--num_charts', type=int, default=1,
help='Maximum number of charts in the image')
parser.add_argument('--backend', default="default", type=str, choices=backends,
help="Choose one of computation backends: "
"default: automatically (by default), "
"openvino: Intel's Deep Learning Inference Engine (https://software.intel.com/openvino-toolkit), "
"opencv: OpenCV implementation, "
"vkcom: VKCOM, "
"cuda: CUDA, "
"webnn: WebNN")
parser.add_argument('--target', default="cpu", type=str, choices=targets,
help="Choose one of target computation devices: "
"cpu: CPU target (by default), "
"opencl: OpenCL, "
"opencl_fp16: OpenCL fp16 (half-float precision), "
"ncs2_vpu: NCS2 VPU, "
"hddl_vpu: HDDL VPU, "
"vulkan: Vulkan, "
"cuda: CUDA, "
"cuda_fp16: CUDA fp16 (half-float preprocess)")
args, _ = parser.parse_known_args()
add_preproc_args(args.zoo, parser, 'mcc', 'mcc')
parser = argparse.ArgumentParser(parents=[parser],
description='''
To run:
Default:
python macbeth_chart_detection.py --input=path/to/your/input/image/or/video (don't give --input flag if want to use device camera)
DNN model:
python macbeth_chart_detection.py mcc --input=path/to/your/input/image/or/video
Model path can also be specified using --model argument. And config path can be specified using --config.
''', formatter_class=argparse.RawTextHelpFormatter)
return parser.parse_args(func_args)
def process_frame(frame, detector, num_charts):
image_copy = frame.copy()
if not detector.process(frame, num_charts):
return None, None
checkers = detector.getListColorChecker()
detector.draw(checkers, frame)
src = checkers[0].getChartsRGB(False)
tgt = detector.getRefColors()
cv.imshow("image result | Press ESC to quit", frame)
cv.imshow("original", image_copy)
return src, tgt
def main(func_args=None):
args = get_args_parser(func_args)
if not (0 <= args.chart_type <= 2):
raise ValueError("chartType must be 0, 1, or 2")
if os.getenv('OPENCV_SAMPLES_DATA_PATH') is not None:
try:
args.model = findModel(args.model, args.sha1)
args.config = findModel(args.config, args.config_sha1)
except:
print("[WARN] Model file not provided, using default detector. Pass model using --model and config using --config to use dnn based detector.\n\n")
args.model = None
args.config = None
else:
args.model = None
args.config = None
print("[WARN] Model file not provided, using default detector. Pass model using --model and config using --config to use dnn based detector. Or, set OPENCV_SAMPLES_DATA_PATH environment variable.\n\n")
if args.model and args.config:
# Load the DNN from TensorFlow model
engine = cv.dnn.ENGINE_AUTO
if args.backend != "default" or args.target != "cpu":
engine = cv.dnn.ENGINE_CLASSIC
net = cv.dnn.readNetFromTensorflow(args.model, args.config, engine)
net.setPreferableBackend(get_backend_id(args.backend))
net.setPreferableTarget(get_target_id(args.target))
detector = cv.mcc_CCheckerDetector.create(net)
print("Detecting checkers using neural network.")
else:
detector = cv.mcc_CCheckerDetector.create()
print("Detecting checkers using default method (no DNN).")
detector.setColorChartType(args.chart_type)
is_video = True
if args.input:
image = cv.imread(findFile(args.input))
if image is not None:
is_video = False
else:
cap = cv.VideoCapture(findFile(args.input))
else:
cap = cv.VideoCapture(0)
if is_video:
print("To print the actual colors and reference colors for current frame press SPACEBAR. To resume press SPACEBAR again")
while True:
ret, frame = cap.read()
if not ret:
break
src, tgt = process_frame(frame, detector, args.num_charts)
key = cv.waitKey(10) & 0xFF
if key == ord(' '):
if src is None or tgt is None:
print("No color chart detected!!")
else:
print("Actual colors: ", src)
print("Reference colors: ", tgt)
print("Press spacebar to resume.")
cv.waitKey(0)
print("Resumed! Processing continues...")
elif key == 27:
exit(0)
if src is not None or tgt is not None:
print("Actual colors: ", src)
print("Reference colors: ", tgt)
else:
src, tgt = process_frame(image, detector, args.num_charts)
if src is None or tgt is None:
print("No color chart detected!!")
else:
print("Actual colors: ", src)
print("Reference colors: ", tgt)
cv.waitKey(0)
cv.destroyAllWindows()
if __name__ == "__main__":
main()
+89
View File
@@ -0,0 +1,89 @@
#!/usr/bin/env python
'''
Morphology operations.
Usage:
morphology.py [<image>]
Keys:
1 - change operation
2 - change structure element shape
ESC - exit
'''
import numpy as np
import cv2 as cv
def main():
import sys
from itertools import cycle
from common import draw_str
try:
fn = sys.argv[1]
except:
fn = 'baboon.jpg'
img = cv.imread(cv.samples.findFile(fn))
if img is None:
print('Failed to load image file:', fn)
sys.exit(1)
cv.imshow('original', img)
modes = cycle(['erode/dilate', 'open/close', 'blackhat/tophat', 'gradient'])
str_modes = cycle(['ellipse', 'rect', 'cross', 'diamond'])
cur_mode = next(modes)
cur_str_mode = next(str_modes)
def update(dummy=None):
try: # do not get trackbar position while trackbar is not created
sz = cv.getTrackbarPos('op/size', 'morphology')
iters = cv.getTrackbarPos('iters', 'morphology')
except:
return
opers = cur_mode.split('/')
if len(opers) > 1:
sz = sz - 10
op = opers[sz > 0]
sz = abs(sz)
else:
op = opers[0]
sz = sz*2+1
str_name = 'MORPH_' + cur_str_mode.upper()
oper_name = 'MORPH_' + op.upper()
st = cv.getStructuringElement(getattr(cv, str_name), (sz, sz))
res = cv.morphologyEx(img, getattr(cv, oper_name), st, iterations=iters)
draw_str(res, (10, 20), 'mode: ' + cur_mode)
draw_str(res, (10, 40), 'operation: ' + oper_name)
draw_str(res, (10, 60), 'structure: ' + str_name)
draw_str(res, (10, 80), 'ksize: %d iters: %d' % (sz, iters))
cv.imshow('morphology', res)
cv.namedWindow('morphology')
cv.createTrackbar('op/size', 'morphology', 12, 20, update)
cv.createTrackbar('iters', 'morphology', 1, 10, update)
update()
while True:
ch = cv.waitKey()
if ch == 27:
break
if ch == ord('1'):
cur_mode = next(modes)
if ch == ord('2'):
cur_str_mode = next(str_modes)
update()
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+88
View File
@@ -0,0 +1,88 @@
#!/usr/bin/env python
'''
mouse_and_match.py [-i path | --input path: default ../data/]
Demonstrate using a mouse to interact with an image:
Read in the images in a directory one by one
Allow the user to select parts of an image with a mouse
When they let go of the mouse, it correlates (using matchTemplate) that patch with the image.
SPACE for next image
ESC to exit
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
# built-in modules
import os
import sys
import glob
import argparse
from math import *
class App():
drag_start = None
sel = (0,0,0,0)
def onmouse(self, event, x, y, flags, param):
if event == cv.EVENT_LBUTTONDOWN:
self.drag_start = x, y
self.sel = (0,0,0,0)
elif event == cv.EVENT_LBUTTONUP:
if self.sel[2] > self.sel[0] and self.sel[3] > self.sel[1]:
patch = self.gray[self.sel[1]:self.sel[3], self.sel[0]:self.sel[2]]
result = cv.matchTemplate(self.gray, patch, cv.TM_CCOEFF_NORMED)
result = np.abs(result)**3
_val, result = cv.threshold(result, 0.01, 0, cv.THRESH_TOZERO)
result8 = cv.normalize(result, None, 0, 255, cv.NORM_MINMAX, cv.CV_8U)
cv.imshow("result", result8)
self.drag_start = None
elif self.drag_start:
#print flags
if flags & cv.EVENT_FLAG_LBUTTON:
minpos = min(self.drag_start[0], x), min(self.drag_start[1], y)
maxpos = max(self.drag_start[0], x), max(self.drag_start[1], y)
self.sel = (minpos[0], minpos[1], maxpos[0], maxpos[1])
img = cv.cvtColor(self.gray, cv.COLOR_GRAY2BGR)
cv.rectangle(img, (self.sel[0], self.sel[1]), (self.sel[2], self.sel[3]), (0,255,255), 1)
cv.imshow("gray", img)
else:
print("selection is complete")
self.drag_start = None
def run(self):
parser = argparse.ArgumentParser(description='Demonstrate mouse interaction with images')
parser.add_argument("-i","--input", default='../data/', help="Input directory.")
args = parser.parse_args()
path = args.input
cv.namedWindow("gray",1)
cv.setMouseCallback("gray", self.onmouse)
'''Loop through all the images in the directory'''
for infile in glob.glob( os.path.join(path, '*.*') ):
ext = os.path.splitext(infile)[1][1:] #get the filename extension
if ext == "png" or ext == "jpg" or ext == "bmp" or ext == "tiff" or ext == "pbm":
print(infile)
img = cv.imread(infile, cv.IMREAD_COLOR)
if img is None:
continue
self.sel = (0,0,0,0)
self.drag_start = None
self.gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
cv.imshow("gray", self.gray)
if cv.waitKey() == 27:
break
print('Done')
if __name__ == '__main__':
print(__doc__)
App().run()
cv.destroyAllWindows()
+68
View File
@@ -0,0 +1,68 @@
#!/usr/bin/env python
import numpy as np
import cv2 as cv
import argparse
import sys
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
'--algo',
help="""DEPTH - works with depth,
RGB - works with images,
RGB_DEPTH - works with all,
SCALE - works with depth and calculate Rt with scale,
default - runs all algos""",
default="")
parser.add_argument(
'-src_d',
'--source_depth_frame',
default="")
parser.add_argument(
'-dst_d',
'--destination_depth_frame',
default="")
parser.add_argument(
'-src_rgb',
'--source_rgb_frame',
default="")
parser.add_argument(
'-dst_rgb',
'--destination_rgb_frame',
default="")
args = parser.parse_args()
if args.algo == "RGB_DEPTH" or args.algo == "DEPTH" or args.algo == "":
source_depth_frame = cv.samples.findFile(args.source_depth_frame)
destination_depth_frame = cv.samples.findFile(args.destination_depth_frame)
depth1 = cv.imread(source_depth_frame, cv.IMREAD_ANYDEPTH).astype(np.float32)
depth2 = cv.imread(destination_depth_frame, cv.IMREAD_ANYDEPTH).astype(np.float32)
if args.algo == "RGB_DEPTH" or args.algo == "RGB" or args.algo == "":
source_rgb_frame = cv.samples.findFile(args.source_rgb_frame)
destination_rgb_frame = cv.samples.findFile(args.destination_rgb_frame)
rgb1 = cv.imread(source_rgb_frame, cv.IMREAD_COLOR)
rgb2 = cv.imread(destination_rgb_frame, cv.IMREAD_COLOR)
if args.algo == "DEPTH" or args.algo == "":
odometry = cv.Odometry(cv.DEPTH)
Rt = np.zeros((4, 4))
odometry.compute(depth1, depth2, Rt)
print("Rt:\n {}".format(Rt))
if args.algo == "RGB" or args.algo == "":
odometry = cv.Odometry(cv.RGB)
Rt = np.zeros((4, 4))
odometry.compute(rgb1, rgb2, Rt)
print("Rt:\n {}".format(Rt))
if args.algo == "RGB_DEPTH" or args.algo == "":
odometry = cv.Odometry(cv.RGB_DEPTH)
Rt = np.zeros((4, 4))
odometry.compute(depth1, rgb1, depth2, rgb2, Rt)
print("Rt:\n {}".format(Rt))
if __name__ == '__main__':
main()
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env python
'''
prints OpenCV version
Usage:
opencv_version.py [<params>]
params:
--build: print complete build info
--help: print this help
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
def main():
import sys
try:
param = sys.argv[1]
except IndexError:
param = ""
if "--build" == param:
print(cv.getBuildInformation())
elif "--help" == param:
print("\t--build\n\t\tprint complete build info")
print("\t--help\n\t\tprint this help")
else:
print("Welcome to OpenCV")
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+181
View File
@@ -0,0 +1,181 @@
#!/usr/bin/env python
'''
Multitarget planar tracking
==================
Example of using "features" framework for interactive video homography matching.
ORB features and FLANN matcher are used. This sample provides PlaneTracker class
and an example of its usage.
video: http://www.youtube.com/watch?v=pzVbhxx6aog
Usage
-----
plane_tracker.py [<video source>]
Keys:
SPACE - pause video
c - clear targets
Select a textured planar object to track by drawing a box with a mouse.
'''
import numpy as np
import cv2 as cv
# built-in modules
from collections import namedtuple
# local modules
import video
import common
from video import presets
FLANN_INDEX_KDTREE = 1
FLANN_INDEX_LSH = 6
flann_params= dict(algorithm = FLANN_INDEX_LSH,
table_number = 6, # 12
key_size = 12, # 20
multi_probe_level = 1) #2
MIN_MATCH_COUNT = 10
'''
image - image to track
rect - tracked rectangle (x1, y1, x2, y2)
keypoints - keypoints detected inside rect
descrs - their descriptors
data - some user-provided data
'''
PlanarTarget = namedtuple('PlaneTarget', 'image, rect, keypoints, descrs, data')
'''
target - reference to PlanarTarget
p0 - matched points coords in target image
p1 - matched points coords in input frame
H - homography matrix from p0 to p1
quad - target boundary quad in input frame
'''
TrackedTarget = namedtuple('TrackedTarget', 'target, p0, p1, H, quad')
class PlaneTracker:
def __init__(self):
self.detector = cv.ORB_create( nfeatures = 1000 )
self.matcher = cv.FlannBasedMatcher(flann_params, {}) # bug : need to pass empty dict (#1329)
self.targets = []
self.frame_points = []
def add_target(self, image, rect, data=None):
'''Add a new tracking target.'''
x0, y0, x1, y1 = rect
raw_points, raw_descrs = self.detect_features(image)
points, descs = [], []
for kp, desc in zip(raw_points, raw_descrs):
x, y = kp.pt
if x0 <= x <= x1 and y0 <= y <= y1:
points.append(kp)
descs.append(desc)
descs = np.uint8(descs)
self.matcher.add([descs])
target = PlanarTarget(image = image, rect=rect, keypoints = points, descrs=descs, data=data)
self.targets.append(target)
def clear(self):
'''Remove all targets'''
self.targets = []
self.matcher.clear()
def track(self, frame):
'''Returns a list of detected TrackedTarget objects'''
self.frame_points, frame_descrs = self.detect_features(frame)
if len(self.frame_points) < MIN_MATCH_COUNT:
return []
matches = self.matcher.knnMatch(frame_descrs, k = 2)
matches = [m[0] for m in matches if len(m) == 2 and m[0].distance < m[1].distance * 0.75]
if len(matches) < MIN_MATCH_COUNT:
return []
matches_by_id = [[] for _ in range(len(self.targets))]
for m in matches:
matches_by_id[m.imgIdx].append(m)
tracked = []
for imgIdx, matches in enumerate(matches_by_id):
if len(matches) < MIN_MATCH_COUNT:
continue
target = self.targets[imgIdx]
p0 = [target.keypoints[m.trainIdx].pt for m in matches]
p1 = [self.frame_points[m.queryIdx].pt for m in matches]
p0, p1 = np.float32((p0, p1))
H, status = cv.findHomography(p0, p1, cv.RANSAC, 3.0)
status = status.ravel() != 0
if status.sum() < MIN_MATCH_COUNT:
continue
p0, p1 = p0[status], p1[status]
x0, y0, x1, y1 = target.rect
quad = np.float32([[x0, y0], [x1, y0], [x1, y1], [x0, y1]])
quad = cv.perspectiveTransform(quad.reshape(1, -1, 2), H).reshape(-1, 2)
track = TrackedTarget(target=target, p0=p0, p1=p1, H=H, quad=quad)
tracked.append(track)
tracked.sort(key = lambda t: len(t.p0), reverse=True)
return tracked
def detect_features(self, frame):
'''detect_features(self, frame) -> keypoints, descrs'''
keypoints, descrs = self.detector.detectAndCompute(frame, None)
if descrs is None: # detectAndCompute returns descs=None if not keypoints found
descrs = []
return keypoints, descrs
class App:
def __init__(self, src):
self.cap = video.create_capture(src, presets['book'])
self.frame = None
self.paused = False
self.tracker = PlaneTracker()
cv.namedWindow('plane')
self.rect_sel = common.RectSelector('plane', self.on_rect)
def on_rect(self, rect):
self.tracker.add_target(self.frame, rect)
def run(self):
while True:
playing = not self.paused and not self.rect_sel.dragging
if playing or self.frame is None:
ret, frame = self.cap.read()
if not ret:
break
self.frame = frame.copy()
vis = self.frame.copy()
if playing:
tracked = self.tracker.track(self.frame)
for tr in tracked:
cv.polylines(vis, [np.int32(tr.quad)], True, (255, 255, 255), 2)
for (x, y) in np.int32(tr.p1):
cv.circle(vis, (x, y), 2, (255, 255, 255))
self.rect_sel.draw(vis)
cv.imshow('plane', vis)
ch = cv.waitKey(1)
if ch == ord(' '):
self.paused = not self.paused
if ch == ord('c'):
self.tracker.clear()
if ch == 27:
break
if __name__ == '__main__':
print(__doc__)
import sys
try:
video_src = sys.argv[1]
except:
video_src = 0
App(video_src).run()
+23
View File
@@ -0,0 +1,23 @@
import numpy as np
import cv2 as cv
vertices, _ = cv.loadPointCloud("../data/teapot.obj")
vertices = np.squeeze(vertices, axis=1)
print(vertices)
color = [1.0, 1.0, 0.0]
colors = np.tile(color, (vertices.shape[0], 1))
obj_pts = np.concatenate((vertices, colors), axis=1)
obj_pts= np.float32(obj_pts)
cv.viz3d.showPoints("window", "points", obj_pts)
cv.viz3d.setGridVisible("window", True)
cv.waitKey(0)
vertices, indices = cv.loadMesh("../data/teapot.obj")
vertices = np.squeeze(vertices, axis=1)
cv.viz3d.showMesh("window", "mesh", vertices, indices)
cv.waitKey(0)
+253
View File
@@ -0,0 +1,253 @@
#!/usr/bin/env python
'''
This program detects the QR-codes using OpenCV Library.
Usage:
qrcode.py
'''
import numpy as np
import cv2 as cv
import argparse
class QrSample:
def __init__(self, args):
self.fname = ''
self.fext = ''
self.fsaveid = 0
self.input = args.input
self.detect = args.detect
self.out = args.out
self.multi = args.multi
self.saveDetections = args.save_detections
self.saveAll = args.save_all
self.arucoBased = args.aruco_based
def getQRModeString(self):
msg1 = "multi " if self.multi else ""
msg2 = "detector" if self.detect else "decoder"
msg = "QR {:s}{:s}".format(msg1, msg2)
return msg
def drawFPS(self, result, fps):
message = '{:.2f} FPS({:s})'.format(fps, self.getQRModeString())
cv.putText(result, message, (20, 20), 1,
cv.FONT_HERSHEY_DUPLEX, (0, 0, 255))
def drawQRCodeContours(self, image, cnt):
if cnt.size != 0:
rows, cols, _ = image.shape
show_radius = 2.813 * ((rows / cols) if rows > cols else (cols / rows))
contour_radius = show_radius * 0.4
cv.drawContours(image, [cnt], 0, (0, 255, 0), int(round(contour_radius)))
tpl = cnt.reshape((-1, 2))
for x in tuple(tpl.tolist()):
color = (255, 0, 0)
cv.circle(image, tuple(x), int(round(contour_radius)), color, -1)
def drawQRCodeResults(self, result, points, decode_info, fps):
n = len(points)
if isinstance(decode_info, str):
decode_info = [decode_info]
if n > 0:
for i in range(n):
cnt = np.array(points[i]).reshape((-1, 1, 2)).astype(np.int32)
self.drawQRCodeContours(result, cnt)
msg = 'QR[{:d}]@{} : '.format(i, *(cnt.reshape(1, -1).tolist()))
print(msg, end="")
if len(decode_info) > i:
if decode_info[i]:
print("'", decode_info[i], "'")
else:
print("Can't decode QR code")
else:
print("Decode information is not available (disabled)")
else:
print("QRCode not detected!")
self.drawFPS(result, fps)
def runQR(self, qrCode, inputimg):
if not self.multi:
if not self.detect:
decode_info, points, _ = qrCode.detectAndDecode(inputimg)
dec_info = decode_info
else:
_, points = qrCode.detect(inputimg)
dec_info = []
else:
if not self.detect:
_, decode_info, points, _ = qrCode.detectAndDecodeMulti(
inputimg)
dec_info = decode_info
else:
_, points = qrCode.detectMulti(inputimg)
dec_info = []
if points is None:
points = []
return points, dec_info
def DetectQRFrmImage(self, inputfile):
inputimg = cv.imread(inputfile, cv.IMREAD_COLOR)
if inputimg is None:
print('ERROR: Can not read image: {}'.format(inputfile))
return
print('Run {:s} on image [{:d}x{:d}]'.format(
self.getQRModeString(), inputimg.shape[1], inputimg.shape[0]))
if self.arucoBased:
qrCode = cv.QRCodeDetectorAruco()
else:
qrCode = cv.QRCodeDetector()
count = 10
timer = cv.TickMeter()
for _ in range(count):
timer.start()
points, decode_info = self.runQR(qrCode, inputimg)
timer.stop()
fps = count / timer.getTimeSec()
print('FPS: {}'.format(fps))
result = inputimg
self.drawQRCodeResults(result, points, decode_info, fps)
cv.imshow("QR", result)
cv.waitKey(1)
if self.out != '':
outfile = self.fname + self.fext
print("Saving Result: {}".format(outfile))
cv.imwrite(outfile, result)
print("Press any key to exit ...")
cv.waitKey(0)
print("Exit")
def processQRCodeDetection(self, qrcode, frame):
if len(frame.shape) == 2:
result = cv.cvtColor(frame, cv.COLOR_GRAY2BGR)
else:
result = frame
print('Run {:s} on video frame [{:d}x{:d}]'.format(
self.getQRModeString(), frame.shape[1], frame.shape[0]))
timer = cv.TickMeter()
timer.start()
points, decode_info = self.runQR(qrcode, frame)
timer.stop()
fps = 1 / timer.getTimeSec()
self.drawQRCodeResults(result, points, decode_info, fps)
return fps, result, points
def DetectQRFrmCamera(self):
cap = cv.VideoCapture(0)
if not cap.isOpened():
print("Cannot open the camera")
return
print("Press 'm' to switch between detectAndDecode and detectAndDecodeMulti")
print("Press 'd' to switch between decoder and detector")
print("Press ' ' (space) to save result into images")
print("Press 'ESC' to exit")
if self.arucoBased:
qrcode = cv.QRCodeDetectorAruco()
else:
qrcode = cv.QRCodeDetector()
while True:
ret, frame = cap.read()
if not ret:
print("End of video stream")
break
forcesave = self.saveAll
result = frame
try:
fps, result, corners = self.processQRCodeDetection(qrcode, frame)
print('FPS: {:.2f}'.format(fps))
forcesave |= self.saveDetections and (len(corners) != 0)
except cv.error as e:
print("Error exception: ", e)
forcesave = True
cv.imshow("QR code", result)
code = cv.waitKey(1)
if code < 0 and (not forcesave):
continue
if code == ord(' ') or forcesave:
fsuffix = '-{:05d}'.format(self.fsaveid)
self.fsaveid += 1
fname_in = self.fname + fsuffix + "_input.png"
print("Saving QR code detection result: '{}' ...".format(fname_in))
cv.imwrite(fname_in, frame)
print("Saved")
if code == ord('m'):
self.multi = not self.multi
msg = 'Switching QR code mode ==> {:s}'.format(
"detectAndDecodeMulti" if self.multi else "detectAndDecode")
print(msg)
if code == ord('d'):
self.detect = not self.detect
msg = 'Switching QR code mode ==> {:s}'.format(
"detect" if self.detect else "decode")
print(msg)
if code == 27:
print("'ESC' is pressed. Exiting...")
break
print("Exit.")
def main():
parser = argparse.ArgumentParser(
description='This program detects the QR-codes input images using OpenCV Library.')
parser.add_argument(
'-i',
'--input',
help="input image path (for example, 'opencv_extra/testdata/cv/qrcode/multiple/*_qrcodes.png)",
default="",
metavar="")
parser.add_argument(
'--aruco_based',
help="use aruco-based detector",
action='store_true')
parser.add_argument(
'-d',
'--detect',
help="detect QR code only (skip decoding) (default: False)",
action='store_true')
parser.add_argument(
'-m',
'--multi',
help="enable multiple qr-codes detection",
action='store_true')
parser.add_argument(
'-o',
'--out',
help="path to result file (default: qr_code.png)",
default="qr_code.png",
metavar="")
parser.add_argument(
'--save_detections',
help="save all QR detections (video mode only)",
action='store_true')
parser.add_argument(
'--save_all',
help="save all processed frames (video mode only)",
action='store_true')
args = parser.parse_args()
qrinst = QrSample(args)
if args.out != '':
index = args.out.rfind('.')
if index != -1:
qrinst.fname = args.out[:index]
qrinst.fext = args.out[index:]
else:
qrinst.fname = args.out
qrinst.fext = ".png"
if args.input != '':
qrinst.DetectQRFrmImage(args.input)
else:
qrinst.DetectQRFrmCamera()
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+120
View File
@@ -0,0 +1,120 @@
#!/usr/bin/env python
'''
Camshift tracker
================
This is a demo that shows mean-shift based tracking
You select a color objects such as your face and it tracks it.
This reads from video camera (0 by default, or the camera number the user enters)
[1] http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.14.7673
Usage:
------
camshift.py [<video source>]
To initialize tracking, select the object with mouse
Keys:
-----
ESC - exit
b - toggle back-projected probability visualization
'''
import numpy as np
import cv2 as cv
# local module
import video
from video import presets
class App(object):
def __init__(self, video_src):
self.cam = video.create_capture(video_src, presets['cube'])
_ret, self.frame = self.cam.read()
cv.namedWindow('camshift')
cv.setMouseCallback('camshift', self.onmouse)
self.selection = None
self.drag_start = None
self.show_backproj = False
self.track_window = None
def onmouse(self, event, x, y, flags, param):
if event == cv.EVENT_LBUTTONDOWN:
self.drag_start = (x, y)
self.track_window = None
if self.drag_start:
xmin = min(x, self.drag_start[0])
ymin = min(y, self.drag_start[1])
xmax = max(x, self.drag_start[0])
ymax = max(y, self.drag_start[1])
self.selection = (xmin, ymin, xmax, ymax)
if event == cv.EVENT_LBUTTONUP:
self.drag_start = None
self.track_window = (xmin, ymin, xmax - xmin, ymax - ymin)
def show_hist(self):
bin_count = self.hist.shape[0]
bin_w = 24
img = np.zeros((256, bin_count*bin_w, 3), np.uint8)
for i in range(bin_count):
h = int(self.hist[i])
cv.rectangle(img, (i*bin_w+2, 255), ((i+1)*bin_w-2, 255-h), (int(180.0*i/bin_count), 255, 255), -1)
img = cv.cvtColor(img, cv.COLOR_HSV2BGR)
cv.imshow('hist', img)
def run(self):
while True:
_ret, self.frame = self.cam.read()
vis = self.frame.copy()
hsv = cv.cvtColor(self.frame, cv.COLOR_BGR2HSV)
mask = cv.inRange(hsv, np.array((0., 60., 32.)), np.array((180., 255., 255.)))
if self.selection:
x0, y0, x1, y1 = self.selection
hsv_roi = hsv[y0:y1, x0:x1]
mask_roi = mask[y0:y1, x0:x1]
hist = cv.calcHist( [hsv_roi], [0], mask_roi, [16], [0, 180] )
cv.normalize(hist, hist, 0, 255, cv.NORM_MINMAX)
self.hist = hist.reshape(-1)
self.show_hist()
vis_roi = vis[y0:y1, x0:x1]
cv.bitwise_not(vis_roi, vis_roi)
vis[mask == 0] = 0
if self.track_window and self.track_window[2] > 0 and self.track_window[3] > 0:
self.selection = None
prob = cv.calcBackProject([hsv], [0], self.hist, [0, 180], 1)
prob &= mask
term_crit = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1 )
track_box, self.track_window = cv.CamShift(prob, self.track_window, term_crit)
if self.show_backproj:
vis[:] = prob[...,np.newaxis]
try:
cv.ellipse(vis, track_box, (0, 0, 255), 2)
except:
print(track_box)
cv.imshow('camshift', vis)
ch = cv.waitKey(5)
if ch == 27:
break
if ch == ord('b'):
self.show_backproj = not self.show_backproj
cv.destroyAllWindows()
if __name__ == '__main__':
print(__doc__)
import sys
try:
video_src = sys.argv[1]
except:
video_src = 0
App(video_src).run()
+83
View File
@@ -0,0 +1,83 @@
#!/usr/bin/env python3
# This file is part of OpenCV project.
# It is subject to the license terms in the LICENSE file found in the top-level directory
# of this distribution and at http://opencv.org/license.html
import argparse
import sys
import cv2 as cv
USAGE = """\
Chromatic Aberration Correction Sample
Usage:
chromatic_aberration_correction.py <input_image> <calibration_file> [--bayer <code>] [--output <path>]
Arguments:
input_image Path to the input image. Can be:
• a 3-channel BGR image, or
• a 1-channel raw Bayer image (see bayer_pattern)
calibration_file OpenCV YAML/XML file with chromatic aberration calibration:
image_width, image_height, red_channel/coeffs_x, coeffs_y,
blue_channel/coeffs_x, coeffs_y.
output (optional) Path to save the corrected image. Default: corrected.png
bayer (optional) integer code for demosaicing a 1-channel raw image
If omitted or <0, input is assumed 3-channel BGR.
Example:
python chromatic_aberration_correction.py input.png calib.yaml --bayer 46 --output corrected.png
"""
def main(argv=None):
parser = argparse.ArgumentParser(
description="Chromatic Aberration Correction Sample",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=USAGE
)
parser.add_argument("input", help="Input image (BGR or Bayer)")
parser.add_argument("calibration", help="Calibration file (YAML/XML)")
parser.add_argument("--output", default="corrected.png", help="Output image file")
parser.add_argument("--bayer", type=int, default=-1, help="Bayer pattern code for demosaic")
parser.add_argument("--no-gui", action="store_true", help="Do not open image windows")
args = parser.parse_args(argv)
img = cv.imread(args.input, cv.IMREAD_UNCHANGED)
if img is None:
print(f"ERROR: Could not load input image: {args.input}", file=sys.stderr)
return 1
fs = cv.FileStorage(args.calibration, cv.FileStorage_READ)
if not fs.isOpened():
print(f"Could not calibration coefficients from {args.calibration}")
return 1
try:
coeffMat, size, degree = cv.loadChromaticAberrationParams(fs.root())
corrected = cv.correctChromaticAberration(img, coeffMat, size, degree, args.bayer)
if corrected is None:
print("ERROR: cv.correctChromaticAberration returned None", file=sys.stderr)
return 1
if not args.no_gui:
cv.namedWindow("Original", cv.WINDOW_AUTOSIZE)
cv.namedWindow("Corrected", cv.WINDOW_AUTOSIZE)
cv.imshow("Original", img)
cv.imshow("Corrected", corrected)
print("Press any key to continue...")
cv.waitKey(0)
cv.destroyAllWindows()
if not cv.imwrite(args.output, corrected):
print(f"WARNING: Could not write output image: {args.output}", file=sys.stderr)
else:
print(f"Saved corrected image to: {args.output}")
except cv.error as e:
print(f"OpenCV error: {e}", file=sys.stderr)
return 1
return 0
if __name__ == "__main__":
sys.exit(main())
+66
View File
@@ -0,0 +1,66 @@
#!/usr/bin/env python
'''
This program illustrates the use of findContours and drawContours.
The original image is put up along with the image of drawn contours.
Usage:
contours.py
A trackbar is put up which controls the contour level from -3 to 3
'''
import numpy as np
import cv2 as cv
def make_image():
img = np.zeros((500, 500), np.uint8)
black, white = 0, 255
for i in range(6):
dx = int((i%2)*250 - 30)
dy = int((i/2.)*150)
if i == 0:
for j in range(11):
angle = (j+5)*np.pi/21
c, s = np.cos(angle), np.sin(angle)
x1, y1 = np.int32([dx+100+j*10-80*c, dy+100-90*s])
x2, y2 = np.int32([dx+100+j*10-30*c, dy+100-30*s])
cv.line(img, (x1, y1), (x2, y2), white)
cv.ellipse( img, (dx+150, dy+100), (100,70), 0, 0, 360, white, -1 )
cv.ellipse( img, (dx+115, dy+70), (30,20), 0, 0, 360, black, -1 )
cv.ellipse( img, (dx+185, dy+70), (30,20), 0, 0, 360, black, -1 )
cv.ellipse( img, (dx+115, dy+70), (15,15), 0, 0, 360, white, -1 )
cv.ellipse( img, (dx+185, dy+70), (15,15), 0, 0, 360, white, -1 )
cv.ellipse( img, (dx+115, dy+70), (5,5), 0, 0, 360, black, -1 )
cv.ellipse( img, (dx+185, dy+70), (5,5), 0, 0, 360, black, -1 )
cv.ellipse( img, (dx+150, dy+100), (10,5), 0, 0, 360, black, -1 )
cv.ellipse( img, (dx+150, dy+150), (40,10), 0, 0, 360, black, -1 )
cv.ellipse( img, (dx+27, dy+100), (20,35), 0, 0, 360, white, -1 )
cv.ellipse( img, (dx+273, dy+100), (20,35), 0, 0, 360, white, -1 )
return img
def main():
img = make_image()
h, w = img.shape[:2]
contours0, hierarchy = cv.findContours( img.copy(), cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
contours = [cv.approxPolyDP(cnt, 3, True) for cnt in contours0]
def update(levels):
vis = np.zeros((h, w, 3), np.uint8)
levels = levels - 3
cv.drawContours( vis, contours, (-1, 2)[levels <= 0], (128,255,255),
3, cv.LINE_AA, hierarchy, abs(levels) )
cv.imshow('contours', vis)
update(3)
cv.createTrackbar( "levels+3", "contours", 3, 7, update )
cv.imshow('image', img)
cv.waitKey()
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+120
View File
@@ -0,0 +1,120 @@
#!/usr/bin/env python
'''
sample for discrete fourier transform (dft)
USAGE:
dft.py <image_file>
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
import sys
def shift_dft(src, dst=None):
'''
Rearrange the quadrants of Fourier image so that the origin is at
the image center. Swaps quadrant 1 with 3, and 2 with 4.
src and dst arrays must be equal size & type
'''
if dst is None:
dst = np.empty(src.shape, src.dtype)
elif src.shape != dst.shape:
raise ValueError("src and dst must have equal sizes")
elif src.dtype != dst.dtype:
raise TypeError("src and dst must have equal types")
if src is dst:
ret = np.empty(src.shape, src.dtype)
else:
ret = dst
h, w = src.shape[:2]
cx1 = cx2 = w // 2
cy1 = cy2 = h // 2
# if the size is odd, then adjust the bottom/right quadrants
if w % 2 != 0:
cx2 += 1
if h % 2 != 0:
cy2 += 1
# swap quadrants
# swap q1 and q3
ret[h-cy1:, w-cx1:] = src[0:cy1 , 0:cx1 ] # q1 -> q3
ret[0:cy2 , 0:cx2 ] = src[h-cy2:, w-cx2:] # q3 -> q1
# swap q2 and q4
ret[0:cy2 , w-cx2:] = src[h-cy2:, 0:cx2 ] # q2 -> q4
ret[h-cy1:, 0:cx1 ] = src[0:cy1 , w-cx1:] # q4 -> q2
if src is dst:
dst[:,:] = ret
return dst
def main():
if len(sys.argv) > 1:
fname = sys.argv[1]
else:
fname = 'baboon.jpg'
print("usage : python dft.py <image_file>")
im = cv.imread(cv.samples.findFile(fname))
# convert to grayscale
im = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
h, w = im.shape[:2]
realInput = im.astype(np.float64)
# perform an optimally sized dft
dft_M = cv.getOptimalDFTSize(w)
dft_N = cv.getOptimalDFTSize(h)
# copy A to dft_A and pad dft_A with zeros
dft_A = np.zeros((dft_N, dft_M, 2), dtype=np.float64)
dft_A[:h, :w, 0] = realInput
# no need to pad bottom part of dft_A with zeros because of
# use of nonzeroRows parameter in cv.dft()
cv.dft(dft_A, dst=dft_A, nonzeroRows=h)
cv.imshow("win", im)
# Split fourier into real and imaginary parts
image_Re, image_Im = cv.split(dft_A)
# Compute the magnitude of the spectrum Mag = sqrt(Re^2 + Im^2)
magnitude = cv.sqrt(image_Re**2.0 + image_Im**2.0)
# Compute log(1 + Mag)
log_spectrum = cv.log(1.0 + magnitude)
# Rearrange the quadrants of Fourier image so that the origin is at
# the image center
shift_dft(log_spectrum, log_spectrum)
# normalize and display the results as rgb
cv.normalize(log_spectrum, log_spectrum, 0.0, 1.0, cv.NORM_MINMAX)
cv.imshow("magnitude", log_spectrum)
cv.waitKey(0)
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+122
View File
@@ -0,0 +1,122 @@
#!/usr/bin/env python
'''
example to show optical flow estimation using DISOpticalFlow
USAGE: dis_opt_flow.py [<video_source>]
Keys:
1 - toggle HSV flow visualization
2 - toggle glitch
3 - toggle spatial propagation of flow vectors
4 - toggle temporal propagation of flow vectors
ESC - exit
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
import video
def draw_flow(img, flow, step=16):
h, w = img.shape[:2]
y, x = np.mgrid[step/2:h:step, step/2:w:step].reshape(2,-1).astype(int)
fx, fy = flow[y,x].T
lines = np.vstack([x, y, x+fx, y+fy]).T.reshape(-1, 2, 2)
lines = np.int32(lines + 0.5)
vis = cv.cvtColor(img, cv.COLOR_GRAY2BGR)
cv.polylines(vis, lines, 0, (0, 255, 0))
for (x1, y1), (_x2, _y2) in lines:
cv.circle(vis, (x1, y1), 1, (0, 255, 0), -1)
return vis
def draw_hsv(flow):
h, w = flow.shape[:2]
fx, fy = flow[:,:,0], flow[:,:,1]
ang = np.arctan2(fy, fx) + np.pi
v = np.sqrt(fx*fx+fy*fy)
hsv = np.zeros((h, w, 3), np.uint8)
hsv[...,0] = ang*(180/np.pi/2)
hsv[...,1] = 255
hsv[...,2] = np.minimum(v*4, 255)
bgr = cv.cvtColor(hsv, cv.COLOR_HSV2BGR)
return bgr
def warp_flow(img, flow):
h, w = flow.shape[:2]
flow = -flow
flow[:,:,0] += np.arange(w)
flow[:,:,1] += np.arange(h)[:,np.newaxis]
res = cv.remap(img, flow, None, cv.INTER_LINEAR)
return res
def main():
import sys
print(__doc__)
try:
fn = sys.argv[1]
except IndexError:
fn = 0
cam = video.create_capture(fn)
_ret, prev = cam.read()
prevgray = cv.cvtColor(prev, cv.COLOR_BGR2GRAY)
show_hsv = False
show_glitch = False
use_spatial_propagation = False
use_temporal_propagation = True
cur_glitch = prev.copy()
inst = cv.DISOpticalFlow.create(cv.DISOPTICAL_FLOW_PRESET_MEDIUM)
inst.setUseSpatialPropagation(use_spatial_propagation)
flow = None
while True:
_ret, img = cam.read()
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
if flow is not None and use_temporal_propagation:
#warp previous flow to get an initial approximation for the current flow:
flow = inst.calc(prevgray, gray, warp_flow(flow,flow))
else:
flow = inst.calc(prevgray, gray, None)
prevgray = gray
cv.imshow('flow', draw_flow(gray, flow))
if show_hsv:
cv.imshow('flow HSV', draw_hsv(flow))
if show_glitch:
cur_glitch = warp_flow(cur_glitch, flow)
cv.imshow('glitch', cur_glitch)
ch = 0xFF & cv.waitKey(5)
if ch == 27:
break
if ch == ord('1'):
show_hsv = not show_hsv
print('HSV flow visualization is', ['off', 'on'][show_hsv])
if ch == ord('2'):
show_glitch = not show_glitch
if show_glitch:
cur_glitch = img.copy()
print('glitch is', ['off', 'on'][show_glitch])
if ch == ord('3'):
use_spatial_propagation = not use_spatial_propagation
inst.setUseSpatialPropagation(use_spatial_propagation)
print('spatial propagation is', ['off', 'on'][use_spatial_propagation])
if ch == ord('4'):
use_temporal_propagation = not use_temporal_propagation
print('temporal propagation is', ['off', 'on'][use_temporal_propagation])
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+78
View File
@@ -0,0 +1,78 @@
#!/usr/bin/env python
'''
Distance transform sample.
Usage:
distrans.py [<image>]
Keys:
ESC - exit
v - toggle voronoi mode
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
from common import make_cmap
def main():
import sys
try:
fn = sys.argv[1]
except:
fn = 'fruits.jpg'
fn = cv.samples.findFile(fn)
img = cv.imread(fn, cv.IMREAD_GRAYSCALE)
if img is None:
print('Failed to load fn:', fn)
sys.exit(1)
cm = make_cmap('jet')
need_update = True
voronoi = False
def update(dummy=None):
global need_update
need_update = False
thrs = cv.getTrackbarPos('threshold', 'distrans')
mark = cv.Canny(img, thrs, 3*thrs)
dist, labels = cv.distanceTransformWithLabels(~mark, cv.DIST_L2, 5)
if voronoi:
vis = cm[np.uint8(labels)]
else:
vis = cm[np.uint8(dist*2)]
vis[mark != 0] = 255
cv.imshow('distrans', vis)
def invalidate(dummy=None):
global need_update
need_update = True
cv.namedWindow('distrans')
cv.createTrackbar('threshold', 'distrans', 60, 255, invalidate)
update()
while True:
ch = cv.waitKey(50)
if ch == 27:
break
if ch == ord('v'):
voronoi = not voronoi
print('showing', ['distance', 'voronoi'][voronoi])
update()
if need_update:
update()
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+94
View File
@@ -0,0 +1,94 @@
#!/usr/bin/env python
'''
Robust line fitting.
==================
Example of using cv.fitLine function for fitting line
to points in presence of outliers.
Usage
-----
fitline.py
Switch through different M-estimator functions and see,
how well the robust functions fit the line even
in case of ~50% of outliers.
Keys
----
SPACE - generate random points
f - change distance function
ESC - exit
'''
import numpy as np
import cv2 as cv
# built-in modules
import itertools as it
# local modules
from common import draw_str
w, h = 512, 256
def toint(p):
return tuple(map(int, p))
def sample_line(p1, p2, n, noise=0.0):
p1 = np.float32(p1)
t = np.random.rand(n,1)
return p1 + (p2-p1)*t + np.random.normal(size=(n, 2))*noise
dist_func_names = it.cycle('DIST_L2 DIST_L1 DIST_L12 DIST_FAIR DIST_WELSCH DIST_HUBER'.split())
cur_func_name = next(dist_func_names)
def update(_=None):
noise = cv.getTrackbarPos('noise', 'fit line')
n = cv.getTrackbarPos('point n', 'fit line')
r = cv.getTrackbarPos('outlier %', 'fit line') / 100.0
outn = int(n*r)
p0, p1 = (90, 80), (w-90, h-80)
img = np.zeros((h, w, 3), np.uint8)
cv.line(img, toint(p0), toint(p1), (0, 255, 0))
if n > 0:
line_points = sample_line(p0, p1, n-outn, noise)
outliers = np.random.rand(outn, 2) * (w, h)
points = np.vstack([line_points, outliers])
for p in line_points:
cv.circle(img, toint(p), 2, (255, 255, 255), -1)
for p in outliers:
cv.circle(img, toint(p), 2, (64, 64, 255), -1)
func = getattr(cv, cur_func_name)
vx, vy, cx, cy = cv.fitLine(np.float32(points), func, 0, 0.01, 0.01)
cv.line(img, (int(cx-vx*w), int(cy-vy*w)), (int(cx+vx*w), int(cy+vy*w)), (0, 0, 255))
draw_str(img, (20, 20), cur_func_name)
cv.imshow('fit line', img)
def main():
cv.namedWindow('fit line')
cv.createTrackbar('noise', 'fit line', 3, 50, update)
cv.createTrackbar('point n', 'fit line', 100, 500, update)
cv.createTrackbar('outlier %', 'fit line', 30, 100, update)
while True:
update()
ch = cv.waitKey(0)
if ch == ord('f'):
global cur_func_name
cur_func_name = next(dist_func_names)
if ch == 27:
break
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/python
'''
This example illustrates how to use cv.HoughCircles() function.
Usage:
houghcircles.py [<image_name>]
image argument defaults to board.jpg
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
import sys
def main():
try:
fn = sys.argv[1]
except IndexError:
fn = 'board.jpg'
src = cv.imread(cv.samples.findFile(fn))
img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
img = cv.medianBlur(img, 5)
cimg = src.copy() # numpy function
circles = cv.HoughCircles(img, cv.HOUGH_GRADIENT, 1, 10, np.array([]), 200, 30, 5, 30)
if circles is not None: # Check if circles have been found and only then iterate over these and add them to the image
circles = np.uint16(np.around(circles))
_a, b, _c = circles.shape
for i in range(b):
cv.circle(cimg, (circles[0][i][0], circles[0][i][1]), circles[0][i][2], (0, 0, 255), 3, cv.LINE_AA)
cv.circle(cimg, (circles[0][i][0], circles[0][i][1]), 2, (0, 255, 0), 3, cv.LINE_AA) # draw center of circle
cv.imshow("detected circles", cimg)
cv.imshow("source", src)
cv.waitKey(0)
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+60
View File
@@ -0,0 +1,60 @@
#!/usr/bin/python
'''
This example illustrates how to use Hough Transform to find lines
Usage:
houghlines.py [<image_name>]
image argument defaults to pic1.png
'''
# Python 2/3 compatibility
from __future__ import print_function
import cv2 as cv
import numpy as np
import sys
import math
def main():
try:
fn = sys.argv[1]
except IndexError:
fn = 'pic1.png'
src = cv.imread(cv.samples.findFile(fn))
dst = cv.Canny(src, 50, 200)
cdst = cv.cvtColor(dst, cv.COLOR_GRAY2BGR)
if True: # HoughLinesP
lines = cv.HoughLinesP(dst, 1, math.pi/180.0, 40, np.array([]), 50, 10)
a, b, _c = lines.shape
for i in range(a):
cv.line(cdst, (lines[i][0][0], lines[i][0][1]), (lines[i][0][2], lines[i][0][3]), (0, 0, 255), 3, cv.LINE_AA)
else: # HoughLines
lines = cv.HoughLines(dst, 1, math.pi/180.0, 50, np.array([]), 0, 0)
if lines is not None:
a, b, _c = lines.shape
for i in range(a):
rho = lines[i][0][0]
theta = lines[i][0][1]
a = math.cos(theta)
b = math.sin(theta)
x0, y0 = a*rho, b*rho
pt1 = ( int(x0+1000*(-b)), int(y0+1000*(a)) )
pt2 = ( int(x0-1000*(-b)), int(y0-1000*(a)) )
cv.line(cdst, pt1, pt2, (0, 0, 255), 3, cv.LINE_AA)
cv.imshow("detected lines", cdst)
cv.imshow("source", src)
cv.waitKey(0)
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+98
View File
@@ -0,0 +1,98 @@
#!/usr/bin/env python
"""
Tracking of rotating point.
Point moves in a circle and is characterized by a 1D state.
state_k+1 = state_k + speed + process_noise N(0, 1e-5)
The speed is constant.
Both state and measurements vectors are 1D (a point angle),
Measurement is the real state + gaussian noise N(0, 1e-1).
The real and the measured points are connected with red line segment,
the real and the estimated points are connected with yellow line segment,
the real and the corrected estimated points are connected with green line segment.
(if Kalman filter works correctly,
the yellow segment should be shorter than the red one and
the green segment should be shorter than the yellow one).
Pressing any key (except ESC) will reset the tracking.
Pressing ESC will stop the program.
"""
import numpy as np
import cv2 as cv
from math import cos, sin, sqrt, pi
def main():
img_height = 500
img_width = 500
kalman = cv.KalmanFilter(2, 1, 0)
code = -1
num_circle_steps = 12
while True:
img = np.zeros((img_height, img_width, 3), np.uint8)
state = np.array([[0.0],[(2 * pi) / num_circle_steps]]) # start state
kalman.transitionMatrix = np.array([[1., 1.], [0., 1.]]) # F. input
kalman.measurementMatrix = 1. * np.eye(1, 2) # H. input
kalman.processNoiseCov = 1e-5 * np.eye(2) # Q. input
kalman.measurementNoiseCov = 1e-1 * np.ones((1, 1)) # R. input
kalman.errorCovPost = 1. * np.eye(2, 2) # P._k|k KF state var
kalman.statePost = 0.1 * np.random.randn(2, 1) # x^_k|k KF state var
while True:
def calc_point(angle):
return (np.around(img_width / 2. + img_width / 3.0 * cos(angle), 0).astype(int),
np.around(img_height / 2. - img_width / 3.0 * sin(angle), 1).astype(int))
img = img * 1e-3
state_angle = state[0, 0]
state_pt = calc_point(state_angle)
# advance Kalman filter to next timestep
# updates statePre, statePost, errorCovPre, errorCovPost
# k-> k+1, x'(k) = A*x(k)
# P'(k) = temp1*At + Q
prediction = kalman.predict()
predict_pt = calc_point(prediction[0, 0]) # equivalent to calc_point(kalman.statePre[0,0])
# generate measurement
measurement = kalman.measurementNoiseCov * np.random.randn(1, 1)
measurement = np.dot(kalman.measurementMatrix, state) + measurement
measurement_angle = measurement[0, 0]
measurement_pt = calc_point(measurement_angle)
# correct the state estimates based on measurements
# updates statePost & errorCovPost
kalman.correct(measurement)
improved_pt = calc_point(kalman.statePost[0, 0])
# plot points
cv.drawMarker(img, measurement_pt, (0, 0, 255), cv.MARKER_SQUARE, 5, 2)
cv.drawMarker(img, predict_pt, (0, 255, 255), cv.MARKER_SQUARE, 5, 2)
cv.drawMarker(img, improved_pt, (0, 255, 0), cv.MARKER_SQUARE, 5, 2)
cv.drawMarker(img, state_pt, (255, 255, 255), cv.MARKER_STAR, 10, 1)
# forecast one step
cv.drawMarker(img, calc_point(np.dot(kalman.transitionMatrix, kalman.statePost)[0, 0]),
(255, 255, 0), cv.MARKER_SQUARE, 12, 1)
cv.line(img, state_pt, measurement_pt, (0, 0, 255), 1, cv.LINE_AA, 0) # red measurement error
cv.line(img, state_pt, predict_pt, (0, 255, 255), 1, cv.LINE_AA, 0) # yellow pre-meas error
cv.line(img, state_pt, improved_pt, (0, 255, 0), 1, cv.LINE_AA, 0) # green post-meas error
# update the real process
process_noise = sqrt(kalman.processNoiseCov[0, 0]) * np.random.randn(2, 1)
state = np.dot(kalman.transitionMatrix, state) + process_noise # x_k+1 = F x_k + w_k
cv.imshow("Kalman", img)
code = cv.waitKey(1000)
if code != -1:
break
if code in [27, ord('q'), ord('Q')]:
break
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env python
'''
K-means clusterization sample.
Usage:
kmeans.py
Keyboard shortcuts:
ESC - exit
space - generate new distribution
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
from gaussian_mix import make_gaussians
def main():
cluster_n = 5
img_size = 512
# generating bright palette
colors = np.zeros((1, cluster_n, 3), np.uint8)
colors[0,:] = 255
colors[0,:,0] = np.arange(0, 180, 180.0/cluster_n)
colors = cv.cvtColor(colors, cv.COLOR_HSV2BGR)[0]
while True:
print('sampling distributions...')
points, _ = make_gaussians(cluster_n, img_size)
term_crit = (cv.TERM_CRITERIA_EPS, 30, 0.1)
_ret, labels, _centers = cv.kmeans(points, cluster_n, None, term_crit, 10, 0)
img = np.zeros((img_size, img_size, 3), np.uint8)
for (x, y), label in zip(np.int32(points), labels.ravel()):
c = list(map(int, colors[label]))
cv.circle(img, (x, y), 1, c, -1)
cv.imshow('kmeans', img)
ch = cv.waitKey(0)
if ch == 27:
break
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+69
View File
@@ -0,0 +1,69 @@
#!/usr/bin/env python
'''
This program demonstrates Laplace point/edge detection using
OpenCV function Laplacian()
It captures from the camera of your choice: 0, 1, ... default 0
Usage:
python laplace.py <ddepth> <smoothType> <sigma>
If no arguments given default arguments will be used.
Keyboard Shortcuts:
Press space bar to exit the program.
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
import sys
def main():
# Declare the variables we are going to use
ddepth = cv.CV_16S
smoothType = "MedianBlur"
sigma = 3
if len(sys.argv)==4:
ddepth = sys.argv[1]
smoothType = sys.argv[2]
sigma = sys.argv[3]
# Taking input from the camera
cap=cv.VideoCapture(0)
# Create Window and Trackbar
cv.namedWindow("Laplace of Image", cv.WINDOW_AUTOSIZE)
cv.createTrackbar("Kernel Size Bar", "Laplace of Image", sigma, 15, lambda x:x)
# Printing frame width, height and FPS
print("=="*40)
print("Frame Width: ", cap.get(cv.CAP_PROP_FRAME_WIDTH), "Frame Height: ", cap.get(cv.CAP_PROP_FRAME_HEIGHT), "FPS: ", cap.get(cv.CAP_PROP_FPS))
while True:
# Reading input from the camera
ret, frame = cap.read()
if ret == False:
print("Can't open camera/video stream")
break
# Taking input/position from the trackbar
sigma = cv.getTrackbarPos("Kernel Size Bar", "Laplace of Image")
# Setting kernel size
ksize = (sigma*5)|1
# Removing noise by blurring with a filter
if smoothType == "GAUSSIAN":
smoothed = cv.GaussianBlur(frame, (ksize, ksize), sigma, sigma)
if smoothType == "BLUR":
smoothed = cv.blur(frame, (ksize, ksize))
if smoothType == "MedianBlur":
smoothed = cv.medianBlur(frame, ksize)
# Apply Laplace function
laplace = cv.Laplacian(smoothed, ddepth, 5)
# Converting back to uint8
result = cv.convertScaleAbs(laplace, (sigma+1)*0.25)
# Display Output
cv.imshow("Laplace of Image", result)
k = cv.waitKey(30)
if k == 27:
return
if __name__ == "__main__":
print(__doc__)
main()
cv.destroyAllWindows()
+106
View File
@@ -0,0 +1,106 @@
#!/usr/bin/env python
'''
Lucas-Kanade tracker
====================
Lucas-Kanade sparse optical flow demo. Uses goodFeaturesToTrack
for track initialization and back-tracking for match verification
between frames.
Usage
-----
lk_track.py [<video_source>]
Keys
----
ESC - exit
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
import video
from common import anorm2, draw_str
lk_params = dict( winSize = (15, 15),
maxLevel = 2,
criteria = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 0.03))
feature_params = dict( maxCorners = 500,
qualityLevel = 0.3,
minDistance = 7,
blockSize = 7 )
class App:
def __init__(self, video_src):
self.track_len = 10
self.detect_interval = 5
self.tracks = []
self.cam = video.create_capture(video_src)
self.frame_idx = 0
def run(self):
while True:
_ret, frame = self.cam.read()
frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
vis = frame.copy()
if len(self.tracks) > 0:
img0, img1 = self.prev_gray, frame_gray
p0 = np.float32([tr[-1] for tr in self.tracks]).reshape(-1, 1, 2)
p1, _st, _err = cv.calcOpticalFlowPyrLK(img0, img1, p0, None, **lk_params)
p0r, _st, _err = cv.calcOpticalFlowPyrLK(img1, img0, p1, None, **lk_params)
d = abs(p0-p0r).reshape(-1, 2).max(-1)
good = d < 1
new_tracks = []
for tr, (x, y), good_flag in zip(self.tracks, p1.reshape(-1, 2), good):
if not good_flag:
continue
tr.append((x, y))
if len(tr) > self.track_len:
del tr[0]
new_tracks.append(tr)
cv.circle(vis, (int(x), int(y)), 2, (0, 255, 0), -1)
self.tracks = new_tracks
cv.polylines(vis, [np.int32(tr) for tr in self.tracks], False, (0, 255, 0))
draw_str(vis, (20, 20), 'track count: %d' % len(self.tracks))
if self.frame_idx % self.detect_interval == 0:
mask = np.zeros_like(frame_gray)
mask[:] = 255
for x, y in [np.int32(tr[-1]) for tr in self.tracks]:
cv.circle(mask, (x, y), 5, 0, -1)
p = cv.goodFeaturesToTrack(frame_gray, mask = mask, **feature_params)
if p is not None:
for x, y in np.float32(p).reshape(-1, 2):
self.tracks.append([(x, y)])
self.frame_idx += 1
self.prev_gray = frame_gray
cv.imshow('lk_track', vis)
ch = cv.waitKey(1)
if ch == 27:
break
def main():
import sys
try:
video_src = sys.argv[1]
except:
video_src = 0
App(video_src).run()
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/env python
'''
MSER detector demo
==================
Usage:
------
mser.py [<video source>]
Keys:
-----
ESC - exit
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
import video
import sys
def main():
try:
video_src = sys.argv[1]
except:
video_src = 0
cam = video.create_capture(video_src)
mser = cv.MSER_create()
while True:
ret, img = cam.read()
if ret == 0:
break
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
vis = img.copy()
regions, _ = mser.detectRegions(gray)
hulls = [cv.convexHull(p.reshape(-1, 1, 2)) for p in regions]
cv.polylines(vis, hulls, 1, (0, 255, 0))
cv.imshow('img', vis)
if cv.waitKey(5) == 27:
break
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+104
View File
@@ -0,0 +1,104 @@
#!/usr/bin/env python
'''
example to show optical flow
USAGE: opt_flow.py [<video_source>]
Keys:
1 - toggle HSV flow visualization
2 - toggle glitch
Keys:
ESC - exit
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
import video
def draw_flow(img, flow, step=16):
h, w = img.shape[:2]
y, x = np.mgrid[step/2:h:step, step/2:w:step].reshape(2,-1).astype(int)
fx, fy = flow[y,x].T
lines = np.vstack([x, y, x+fx, y+fy]).T.reshape(-1, 2, 2)
lines = np.int32(lines + 0.5)
vis = cv.cvtColor(img, cv.COLOR_GRAY2BGR)
cv.polylines(vis, lines, 0, (0, 255, 0))
for (x1, y1), (_x2, _y2) in lines:
cv.circle(vis, (x1, y1), 1, (0, 255, 0), -1)
return vis
def draw_hsv(flow):
h, w = flow.shape[:2]
fx, fy = flow[:,:,0], flow[:,:,1]
ang = np.arctan2(fy, fx) + np.pi
v = np.sqrt(fx*fx+fy*fy)
hsv = np.zeros((h, w, 3), np.uint8)
hsv[...,0] = ang*(180/np.pi/2)
hsv[...,1] = 255
hsv[...,2] = np.minimum(v*4, 255)
bgr = cv.cvtColor(hsv, cv.COLOR_HSV2BGR)
return bgr
def warp_flow(img, flow):
h, w = flow.shape[:2]
flow = -flow
flow[:,:,0] += np.arange(w)
flow[:,:,1] += np.arange(h)[:,np.newaxis]
res = cv.remap(img, flow, None, cv.INTER_LINEAR)
return res
def main():
import sys
try:
fn = sys.argv[1]
except IndexError:
fn = 0
cam = video.create_capture(fn)
_ret, prev = cam.read()
prevgray = cv.cvtColor(prev, cv.COLOR_BGR2GRAY)
show_hsv = False
show_glitch = False
cur_glitch = prev.copy()
while True:
_ret, img = cam.read()
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
flow = cv.calcOpticalFlowFarneback(prevgray, gray, None, 0.5, 3, 15, 3, 5, 1.2, 0)
prevgray = gray
cv.imshow('flow', draw_flow(gray, flow))
if show_hsv:
cv.imshow('flow HSV', draw_hsv(flow))
if show_glitch:
cur_glitch = warp_flow(cur_glitch, flow)
cv.imshow('glitch', cur_glitch)
ch = cv.waitKey(5)
if ch == 27:
break
if ch == ord('1'):
show_hsv = not show_hsv
print('HSV flow visualization is', ['off', 'on'][show_hsv])
if ch == ord('2'):
show_glitch = not show_glitch
if show_glitch:
cur_glitch = img.copy()
print('glitch is', ['off', 'on'][show_glitch])
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env python
'''
Simple "Square Detector" program.
Loads several images sequentially and tries to find squares in each image.
'''
import numpy as np
import cv2 as cv
def angle_cos(p0, p1, p2):
d1, d2 = (p0-p1).astype('float'), (p2-p1).astype('float')
return abs( np.dot(d1, d2) / np.sqrt( np.dot(d1, d1)*np.dot(d2, d2) ) )
def find_squares(img):
img = cv.GaussianBlur(img, (5, 5), 0)
squares = []
for gray in cv.split(img):
for thrs in range(0, 255, 26):
if thrs == 0:
bin = cv.Canny(gray, 0, 50, apertureSize=5)
bin = cv.dilate(bin, None)
else:
_retval, bin = cv.threshold(gray, thrs, 255, cv.THRESH_BINARY)
contours, _hierarchy = cv.findContours(bin, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
for cnt in contours:
cnt_len = cv.arcLength(cnt, True)
cnt = cv.approxPolyDP(cnt, 0.02*cnt_len, True)
if len(cnt) == 4 and cv.contourArea(cnt) > 1000 and cv.isContourConvex(cnt):
cnt = cnt.reshape(-1, 2)
max_cos = np.max([angle_cos( cnt[i], cnt[(i+1) % 4], cnt[(i+2) % 4] ) for i in range(4)])
if max_cos < 0.1:
squares.append(cnt)
return squares
def main():
from glob import glob
for fn in glob('../data/pic*.png'):
img = cv.imread(fn)
squares = find_squares(img)
cv.drawContours( img, squares, -1, (0, 255, 0), 3 )
cv.imshow('squares', img)
ch = cv.waitKey()
if ch == 27:
break
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+64
View File
@@ -0,0 +1,64 @@
#!/usr/bin/env python
'''
Stitching sample
================
Show how to use Stitcher API from python in a simple way to stitch panoramas
or scans.
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
import argparse
import sys
modes = (cv.Stitcher_PANORAMA, cv.Stitcher_SCANS)
parser = argparse.ArgumentParser(prog='stitching.py', description='Stitching sample.')
parser.add_argument('--mode',
type = int, choices = modes, default = cv.Stitcher_PANORAMA,
help = 'Determines configuration of stitcher. The default is `PANORAMA` (%d), '
'mode suitable for creating photo panoramas. Option `SCANS` (%d) is suitable '
'for stitching materials under affine transformation, such as scans.' % modes)
parser.add_argument('--output', default = 'result.jpg',
help = 'Resulting image. The default is `result.jpg`.')
parser.add_argument('img', nargs='+', help = 'input images')
__doc__ += '\n' + parser.format_help()
def main():
args = parser.parse_args()
# read input images
imgs = []
for img_name in args.img:
img = cv.imread(cv.samples.findFile(img_name))
if img is None:
print("can't read image " + img_name)
sys.exit(-1)
imgs.append(img)
#![stitching]
stitcher = cv.Stitcher.create(args.mode)
status, pano = stitcher.stitch(imgs)
if status != cv.Stitcher_OK:
print("Can't stitch images, error code = %d" % status)
sys.exit(-1)
#![stitching]
cv.imwrite(args.output, pano)
print("stitching completed successfully. %s saved!" % args.output)
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env python
'''
Texture flow direction estimation.
Sample shows how cv.cornerEigenValsAndVecs function can be used
to estimate image texture flow direction.
Usage:
texture_flow.py [<image>]
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
def main():
import sys
try:
fn = sys.argv[1]
except:
fn = 'starry_night.jpg'
img = cv.imread(cv.samples.findFile(fn))
if img is None:
print('Failed to load image file:', fn)
sys.exit(1)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
h, w = img.shape[:2]
eigen = cv.cornerEigenValsAndVecs(gray, 15, 3)
eigen = eigen.reshape(h, w, 3, 2) # [[e1, e2], v1, v2]
flow = eigen[:,:,2]
vis = img.copy()
vis[:] = (192 + np.uint32(vis)) / 2
d = 12
points = np.dstack( np.mgrid[d/2:w:d, d/2:h:d] ).reshape(-1, 2)
for x, y in np.int32(points):
vx, vy = np.int32(flow[y, x]*d)
cv.line(vis, (x-vx, y-vy), (x+vx, y+vy), (0, 0, 0), 1, cv.LINE_AA)
cv.imshow('input', img)
cv.imshow('flow', vis)
cv.waitKey()
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+85
View File
@@ -0,0 +1,85 @@
#!/usr/bin/env python
'''
Watershed segmentation
=========
This program demonstrates the watershed segmentation algorithm
in OpenCV: watershed().
Usage
-----
watershed.py [image filename]
Keys
----
1-7 - switch marker color
SPACE - update segmentation
r - reset
a - toggle autoupdate
ESC - exit
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
from common import Sketcher
class App:
def __init__(self, fn):
self.img = cv.imread(fn)
if self.img is None:
raise Exception('Failed to load image file: %s' % fn)
h, w = self.img.shape[:2]
self.markers = np.zeros((h, w), np.int32)
self.markers_vis = self.img.copy()
self.cur_marker = 1
self.colors = np.int32( list(np.ndindex(2, 2, 2)) ) * 255
self.auto_update = True
self.sketch = Sketcher('img', [self.markers_vis, self.markers], self.get_colors)
def get_colors(self):
return list(map(int, self.colors[self.cur_marker])), self.cur_marker
def watershed(self):
m = self.markers.copy()
cv.watershed(self.img, m)
overlay = self.colors[np.maximum(m, 0)]
vis = cv.addWeighted(self.img, 0.5, overlay, 0.5, 0.0, dtype=cv.CV_8UC3)
cv.imshow('watershed', vis)
def run(self):
while cv.getWindowProperty('img', 0) != -1 or cv.getWindowProperty('watershed', 0) != -1:
ch = cv.waitKey(50)
if ch == 27:
break
if ch >= ord('1') and ch <= ord('7'):
self.cur_marker = ch - ord('0')
print('marker: ', self.cur_marker)
if ch == ord(' ') or (self.sketch.dirty and self.auto_update):
self.watershed()
self.sketch.dirty = False
if ch in [ord('a'), ord('A')]:
self.auto_update = not self.auto_update
print('auto_update if', ['off', 'on'][self.auto_update])
if ch in [ord('r'), ord('R')]:
self.markers[:] = 0
self.markers_vis[:] = self.img
self.sketch.show()
cv.destroyAllWindows()
if __name__ == '__main__':
print(__doc__)
import sys
try:
fn = sys.argv[1]
except:
fn = 'fruits.jpg'
App(cv.samples.findFile(fn)).run()
+85
View File
@@ -0,0 +1,85 @@
#!/usr/bin/env python
'''
Simple example of stereo image matching and point cloud generation.
Resulting .ply file cam be easily viewed using MeshLab ( http://meshlab.sourceforge.net/ )
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
ply_header = '''ply
format ascii 1.0
element vertex %(vert_num)d
property float x
property float y
property float z
property uchar red
property uchar green
property uchar blue
end_header
'''
def write_ply(fn, verts, colors):
verts = verts.reshape(-1, 3)
colors = colors.reshape(-1, 3)
verts = np.hstack([verts, colors])
with open(fn, 'wb') as f:
f.write((ply_header % dict(vert_num=len(verts))).encode('utf-8'))
np.savetxt(f, verts, fmt='%f %f %f %d %d %d ')
def main():
print('loading images...')
imgL = cv.pyrDown(cv.imread(cv.samples.findFile('aloeL.jpg'))) # downscale images for faster processing
imgR = cv.pyrDown(cv.imread(cv.samples.findFile('aloeR.jpg')))
# disparity range is tuned for 'aloe' image pair
window_size = 3
min_disp = 16
num_disp = 112-min_disp
stereo = cv.StereoSGBM_create(minDisparity = min_disp,
numDisparities = num_disp,
blockSize = 16,
P1 = 8*3*window_size**2,
P2 = 32*3*window_size**2,
disp12MaxDiff = 1,
uniquenessRatio = 10,
speckleWindowSize = 100,
speckleRange = 32
)
print('computing disparity...')
disp = stereo.compute(imgL, imgR).astype(np.float32) / 16.0
print('generating 3d point cloud...',)
h, w = imgL.shape[:2]
f = 0.8*w # guess for focal length
Q = np.float32([[1, 0, 0, -0.5*w],
[0,-1, 0, 0.5*h], # turn points 180 deg around x-axis,
[0, 0, 0, -f], # so that y-axis looks up
[0, 0, 1, 0]])
points = cv.reprojectImageTo3D(disp, Q)
colors = cv.cvtColor(imgL, cv.COLOR_BGR2RGB)
mask = disp > disp.min()
out_points = points[mask]
out_colors = colors[mask]
out_fn = 'out.ply'
write_ply(out_fn, out_points, out_colors)
print('%s saved' % out_fn)
cv.imshow('left', imgL)
cv.imshow('disparity', (disp-min_disp)/num_disp)
cv.waitKey()
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+521
View File
@@ -0,0 +1,521 @@
"""
Stitching sample (advanced)
===========================
Show how to use Stitcher API from python.
"""
# Python 2/3 compatibility
from __future__ import print_function
import argparse
from collections import OrderedDict
import cv2 as cv
import numpy as np
EXPOS_COMP_CHOICES = OrderedDict()
EXPOS_COMP_CHOICES['gain_blocks'] = cv.detail.ExposureCompensator_GAIN_BLOCKS
EXPOS_COMP_CHOICES['gain'] = cv.detail.ExposureCompensator_GAIN
EXPOS_COMP_CHOICES['channel'] = cv.detail.ExposureCompensator_CHANNELS
EXPOS_COMP_CHOICES['channel_blocks'] = cv.detail.ExposureCompensator_CHANNELS_BLOCKS
EXPOS_COMP_CHOICES['no'] = cv.detail.ExposureCompensator_NO
BA_COST_CHOICES = OrderedDict()
BA_COST_CHOICES['ray'] = cv.detail_BundleAdjusterRay
BA_COST_CHOICES['reproj'] = cv.detail_BundleAdjusterReproj
BA_COST_CHOICES['affine'] = cv.detail_BundleAdjusterAffinePartial
BA_COST_CHOICES['no'] = cv.detail_NoBundleAdjuster
FEATURES_FIND_CHOICES = OrderedDict()
try:
cv.xfeatures2d_SURF.create() # check if the function can be called
FEATURES_FIND_CHOICES['surf'] = cv.xfeatures2d_SURF.create
except (AttributeError, cv.error) as e:
print("SURF not available")
# if SURF not available, ORB is default
FEATURES_FIND_CHOICES['orb'] = cv.ORB.create
try:
FEATURES_FIND_CHOICES['sift'] = cv.SIFT_create
except AttributeError:
print("SIFT not available")
try:
cv.xfeatures2d_BRISK.create() # check if the function can be called
FEATURES_FIND_CHOICES['brisk'] = cv.xfeatures2d_BRISK.create
except AttributeError:
print("BRISK not available")
try:
cv.xfeatures2d_AKAZE.create() # check if the function can be called
FEATURES_FIND_CHOICES['akaze'] = cv.xfeatures2d_AKAZE.create
except AttributeError:
print("AKAZE not available")
SEAM_FIND_CHOICES = OrderedDict()
SEAM_FIND_CHOICES['gc_color'] = cv.detail_GraphCutSeamFinder('COST_COLOR')
SEAM_FIND_CHOICES['gc_colorgrad'] = cv.detail_GraphCutSeamFinder('COST_COLOR_GRAD')
SEAM_FIND_CHOICES['dp_color'] = cv.detail_DpSeamFinder('COLOR')
SEAM_FIND_CHOICES['dp_colorgrad'] = cv.detail_DpSeamFinder('COLOR_GRAD')
SEAM_FIND_CHOICES['voronoi'] = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_VORONOI_SEAM)
SEAM_FIND_CHOICES['no'] = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_NO)
ESTIMATOR_CHOICES = OrderedDict()
ESTIMATOR_CHOICES['homography'] = cv.detail_HomographyBasedEstimator
ESTIMATOR_CHOICES['affine'] = cv.detail_AffineBasedEstimator
WARP_CHOICES = (
'spherical',
'plane',
'affine',
'cylindrical',
'fisheye',
'stereographic',
'compressedPlaneA2B1',
'compressedPlaneA1.5B1',
'compressedPlanePortraitA2B1',
'compressedPlanePortraitA1.5B1',
'paniniA2B1',
'paniniA1.5B1',
'paniniPortraitA2B1',
'paniniPortraitA1.5B1',
'mercator',
'transverseMercator',
)
WAVE_CORRECT_CHOICES = OrderedDict()
WAVE_CORRECT_CHOICES['horiz'] = cv.detail.WAVE_CORRECT_HORIZ
WAVE_CORRECT_CHOICES['no'] = None
WAVE_CORRECT_CHOICES['vert'] = cv.detail.WAVE_CORRECT_VERT
BLEND_CHOICES = ('multiband', 'feather', 'no',)
parser = argparse.ArgumentParser(
prog="stitching_detailed.py", description="Rotation model images stitcher"
)
parser.add_argument(
'img_names', nargs='+',
help="Files to stitch", type=str
)
parser.add_argument(
'--try_cuda',
action='store_true',
help="Try to use CUDA. The default value is no. All default values are for CPU mode.",
)
parser.add_argument(
'--work_megapix', action='store', default=0.6,
help="Resolution for image registration step. The default is 0.6 Mpx",
type=float, dest='work_megapix'
)
parser.add_argument(
'--features', action='store', default=list(FEATURES_FIND_CHOICES.keys())[0],
help="Type of features used for images matching. The default is '%s'." % list(FEATURES_FIND_CHOICES.keys())[0],
choices=FEATURES_FIND_CHOICES.keys(),
type=str, dest='features'
)
parser.add_argument(
'--matcher', action='store', default='homography',
help="Matcher used for pairwise image matching. The default is 'homography'.",
choices=('homography', 'affine'),
type=str, dest='matcher'
)
parser.add_argument(
'--estimator', action='store', default=list(ESTIMATOR_CHOICES.keys())[0],
help="Type of estimator used for transformation estimation. The default is '%s'." % list(ESTIMATOR_CHOICES.keys())[0],
choices=ESTIMATOR_CHOICES.keys(),
type=str, dest='estimator'
)
parser.add_argument(
'--match_conf', action='store',
help="Confidence for feature matching step. The default is 0.3 for ORB and 0.65 for other feature types.",
type=float, dest='match_conf'
)
parser.add_argument(
'--conf_thresh', action='store', default=1.0,
help="Threshold for two images are from the same panorama confidence.The default is 1.0.",
type=float, dest='conf_thresh'
)
parser.add_argument(
'--ba', action='store', default=list(BA_COST_CHOICES.keys())[0],
help="Bundle adjustment cost function. The default is '%s'." % list(BA_COST_CHOICES.keys())[0],
choices=BA_COST_CHOICES.keys(),
type=str, dest='ba'
)
parser.add_argument(
'--ba_refine_mask', action='store', default='xxxxx',
help="Set refinement mask for bundle adjustment. It looks like 'x_xxx', "
"where 'x' means refine respective parameter and '_' means don't refine, "
"and has the following format:<fx><skew><ppx><aspect><ppy>. "
"The default mask is 'xxxxx'. "
"If bundle adjustment doesn't support estimation of selected parameter then "
"the respective flag is ignored.",
type=str, dest='ba_refine_mask'
)
parser.add_argument(
'--wave_correct', action='store', default=list(WAVE_CORRECT_CHOICES.keys())[0],
help="Perform wave effect correction. The default is '%s'" % list(WAVE_CORRECT_CHOICES.keys())[0],
choices=WAVE_CORRECT_CHOICES.keys(),
type=str, dest='wave_correct'
)
parser.add_argument(
'--save_graph', action='store', default=None,
help="Save matches graph represented in DOT language to <file_name> file.",
type=str, dest='save_graph'
)
parser.add_argument(
'--warp', action='store', default=WARP_CHOICES[0],
help="Warp surface type. The default is '%s'." % WARP_CHOICES[0],
choices=WARP_CHOICES,
type=str, dest='warp'
)
parser.add_argument(
'--seam_megapix', action='store', default=0.1,
help="Resolution for seam estimation step. The default is 0.1 Mpx.",
type=float, dest='seam_megapix'
)
parser.add_argument(
'--seam', action='store', default=list(SEAM_FIND_CHOICES.keys())[0],
help="Seam estimation method. The default is '%s'." % list(SEAM_FIND_CHOICES.keys())[0],
choices=SEAM_FIND_CHOICES.keys(),
type=str, dest='seam'
)
parser.add_argument(
'--compose_megapix', action='store', default=-1,
help="Resolution for compositing step. Use -1 for original resolution. The default is -1",
type=float, dest='compose_megapix'
)
parser.add_argument(
'--expos_comp', action='store', default=list(EXPOS_COMP_CHOICES.keys())[0],
help="Exposure compensation method. The default is '%s'." % list(EXPOS_COMP_CHOICES.keys())[0],
choices=EXPOS_COMP_CHOICES.keys(),
type=str, dest='expos_comp'
)
parser.add_argument(
'--expos_comp_nr_feeds', action='store', default=1,
help="Number of exposure compensation feed.",
type=np.int32, dest='expos_comp_nr_feeds'
)
parser.add_argument(
'--expos_comp_nr_filtering', action='store', default=2,
help="Number of filtering iterations of the exposure compensation gains.",
type=float, dest='expos_comp_nr_filtering'
)
parser.add_argument(
'--expos_comp_block_size', action='store', default=32,
help="BLock size in pixels used by the exposure compensator. The default is 32.",
type=np.int32, dest='expos_comp_block_size'
)
parser.add_argument(
'--blend', action='store', default=BLEND_CHOICES[0],
help="Blending method. The default is '%s'." % BLEND_CHOICES[0],
choices=BLEND_CHOICES,
type=str, dest='blend'
)
parser.add_argument(
'--blend_strength', action='store', default=5,
help="Blending strength from [0,100] range. The default is 5",
type=np.int32, dest='blend_strength'
)
parser.add_argument(
'--output', action='store', default='result.jpg',
help="The default is 'result.jpg'",
type=str, dest='output'
)
parser.add_argument(
'--timelapse', action='store', default=None,
help="Output warped images separately as frames of a time lapse movie, "
"with 'fixed_' prepended to input file names.",
type=str, dest='timelapse'
)
parser.add_argument(
'--rangewidth', action='store', default=-1,
help="uses range_width to limit number of images to match with.",
type=int, dest='rangewidth'
)
__doc__ += '\n' + parser.format_help()
def get_matcher(args):
try_cuda = args.try_cuda
matcher_type = args.matcher
if args.match_conf is None:
if args.features == 'orb':
match_conf = 0.3
else:
match_conf = 0.65
else:
match_conf = args.match_conf
range_width = args.rangewidth
if matcher_type == "affine":
matcher = cv.detail_AffineBestOf2NearestMatcher(False, try_cuda, match_conf)
elif range_width == -1:
matcher = cv.detail_BestOf2NearestMatcher(try_cuda, match_conf)
else:
matcher = cv.detail_BestOf2NearestRangeMatcher(range_width, try_cuda, match_conf)
return matcher
def get_compensator(args):
expos_comp_type = EXPOS_COMP_CHOICES[args.expos_comp]
expos_comp_nr_feeds = args.expos_comp_nr_feeds
expos_comp_block_size = args.expos_comp_block_size
# expos_comp_nr_filtering = args.expos_comp_nr_filtering
if expos_comp_type == cv.detail.ExposureCompensator_CHANNELS:
compensator = cv.detail_ChannelsCompensator(expos_comp_nr_feeds)
# compensator.setNrGainsFilteringIterations(expos_comp_nr_filtering)
elif expos_comp_type == cv.detail.ExposureCompensator_CHANNELS_BLOCKS:
compensator = cv.detail_BlocksChannelsCompensator(
expos_comp_block_size, expos_comp_block_size,
expos_comp_nr_feeds
)
# compensator.setNrGainsFilteringIterations(expos_comp_nr_filtering)
else:
compensator = cv.detail.ExposureCompensator_createDefault(expos_comp_type)
return compensator
def main():
args = parser.parse_args()
img_names = args.img_names
work_megapix = args.work_megapix
seam_megapix = args.seam_megapix
compose_megapix = args.compose_megapix
conf_thresh = args.conf_thresh
ba_refine_mask = args.ba_refine_mask
wave_correct = WAVE_CORRECT_CHOICES[args.wave_correct]
if args.save_graph is None:
save_graph = False
else:
save_graph = True
warp_type = args.warp
blend_type = args.blend
blend_strength = args.blend_strength
result_name = args.output
if args.timelapse is not None:
timelapse = True
if args.timelapse == "as_is":
timelapse_type = cv.detail.Timelapser_AS_IS
elif args.timelapse == "crop":
timelapse_type = cv.detail.Timelapser_CROP
else:
print("Bad timelapse method")
exit()
else:
timelapse = False
finder = FEATURES_FIND_CHOICES[args.features]()
seam_work_aspect = 1
full_img_sizes = []
features = []
images = []
is_work_scale_set = False
is_seam_scale_set = False
is_compose_scale_set = False
for name in img_names:
full_img = cv.imread(cv.samples.findFile(name))
if full_img is None:
print("Cannot read image ", name)
exit()
full_img_sizes.append((full_img.shape[1], full_img.shape[0]))
if work_megapix < 0:
img = full_img
work_scale = 1
is_work_scale_set = True
else:
if is_work_scale_set is False:
work_scale = min(1.0, np.sqrt(work_megapix * 1e6 / (full_img.shape[0] * full_img.shape[1])))
is_work_scale_set = True
img = cv.resize(src=full_img, dsize=None, fx=work_scale, fy=work_scale, interpolation=cv.INTER_LINEAR_EXACT)
if is_seam_scale_set is False:
if seam_megapix > 0:
seam_scale = min(1.0, np.sqrt(seam_megapix * 1e6 / (full_img.shape[0] * full_img.shape[1])))
else:
seam_scale = 1.0
seam_work_aspect = seam_scale / work_scale
is_seam_scale_set = True
img_feat = cv.detail.computeImageFeatures2(finder, img)
features.append(img_feat)
img = cv.resize(src=full_img, dsize=None, fx=seam_scale, fy=seam_scale, interpolation=cv.INTER_LINEAR_EXACT)
images.append(img)
matcher = get_matcher(args)
p = matcher.apply2(features)
matcher.collectGarbage()
if save_graph:
with open(args.save_graph, 'w') as fh:
fh.write(cv.detail.matchesGraphAsString(img_names, p, conf_thresh))
indices = cv.detail.leaveBiggestComponent(features, p, conf_thresh)
img_subset = []
img_names_subset = []
full_img_sizes_subset = []
for i in range(len(indices)):
img_names_subset.append(img_names[indices[i]])
img_subset.append(images[indices[i]])
full_img_sizes_subset.append(full_img_sizes[indices[i]])
images = img_subset
img_names = img_names_subset
full_img_sizes = full_img_sizes_subset
num_images = len(img_names)
if num_images < 2:
print("Need more images")
exit()
estimator = ESTIMATOR_CHOICES[args.estimator]()
b, cameras = estimator.apply(features, p, None)
if not b:
print("Homography estimation failed.")
exit()
for cam in cameras:
cam.R = cam.R.astype(np.float32)
adjuster = BA_COST_CHOICES[args.ba]()
adjuster.setConfThresh(conf_thresh)
refine_mask = np.zeros((3, 3), np.uint8)
if ba_refine_mask[0] == 'x':
refine_mask[0, 0] = 1
if ba_refine_mask[1] == 'x':
refine_mask[0, 1] = 1
if ba_refine_mask[2] == 'x':
refine_mask[0, 2] = 1
if ba_refine_mask[3] == 'x':
refine_mask[1, 1] = 1
if ba_refine_mask[4] == 'x':
refine_mask[1, 2] = 1
adjuster.setRefinementMask(refine_mask)
b, cameras = adjuster.apply(features, p, cameras)
if not b:
print("Camera parameters adjusting failed.")
exit()
focals = []
for cam in cameras:
focals.append(cam.focal)
focals.sort()
if len(focals) % 2 == 1:
warped_image_scale = focals[len(focals) // 2]
else:
warped_image_scale = (focals[len(focals) // 2] + focals[len(focals) // 2 - 1]) / 2
if wave_correct is not None:
rmats = []
for cam in cameras:
rmats.append(np.copy(cam.R))
rmats = cv.detail.waveCorrect(rmats, wave_correct)
for idx, cam in enumerate(cameras):
cam.R = rmats[idx]
corners = []
masks_warped = []
images_warped = []
sizes = []
masks = []
for i in range(0, num_images):
um = cv.UMat(255 * np.ones((images[i].shape[0], images[i].shape[1]), np.uint8))
masks.append(um)
warper = cv.PyRotationWarper(warp_type, warped_image_scale * seam_work_aspect) # warper could be nullptr?
for idx in range(0, num_images):
K = cameras[idx].K().astype(np.float32)
swa = seam_work_aspect
K[0, 0] *= swa
K[0, 2] *= swa
K[1, 1] *= swa
K[1, 2] *= swa
corner, image_wp = warper.warp(images[idx], K, cameras[idx].R, cv.INTER_LINEAR, cv.BORDER_REFLECT)
corners.append(corner)
sizes.append((image_wp.shape[1], image_wp.shape[0]))
images_warped.append(image_wp)
p, mask_wp = warper.warp(masks[idx], K, cameras[idx].R, cv.INTER_NEAREST, cv.BORDER_CONSTANT)
masks_warped.append(mask_wp.get())
images_warped_f = []
for img in images_warped:
imgf = img.astype(np.float32)
images_warped_f.append(imgf)
compensator = get_compensator(args)
compensator.feed(corners=corners, images=images_warped, masks=masks_warped)
seam_finder = SEAM_FIND_CHOICES[args.seam]
masks_warped = seam_finder.find(images_warped_f, corners, masks_warped)
compose_scale = 1
corners = []
sizes = []
blender = None
timelapser = None
# https://github.com/opencv/opencv/blob/5.x/samples/cpp/stitching_detailed.cpp#L725 ?
for idx, name in enumerate(img_names):
full_img = cv.imread(name)
if not is_compose_scale_set:
if compose_megapix > 0:
compose_scale = min(1.0, np.sqrt(compose_megapix * 1e6 / (full_img.shape[0] * full_img.shape[1])))
is_compose_scale_set = True
compose_work_aspect = compose_scale / work_scale
warped_image_scale *= compose_work_aspect
warper = cv.PyRotationWarper(warp_type, warped_image_scale)
for i in range(0, len(img_names)):
cameras[i].focal *= compose_work_aspect
cameras[i].ppx *= compose_work_aspect
cameras[i].ppy *= compose_work_aspect
sz = (int(round(full_img_sizes[i][0] * compose_scale)),
int(round(full_img_sizes[i][1] * compose_scale)))
K = cameras[i].K().astype(np.float32)
roi = warper.warpRoi(sz, K, cameras[i].R)
corners.append(roi[0:2])
sizes.append(roi[2:4])
if abs(compose_scale - 1) > 1e-1:
img = cv.resize(src=full_img, dsize=None, fx=compose_scale, fy=compose_scale,
interpolation=cv.INTER_LINEAR_EXACT)
else:
img = full_img
_img_size = (img.shape[1], img.shape[0])
K = cameras[idx].K().astype(np.float32)
corner, image_warped = warper.warp(img, K, cameras[idx].R, cv.INTER_LINEAR, cv.BORDER_REFLECT)
mask = 255 * np.ones((img.shape[0], img.shape[1]), np.uint8)
p, mask_warped = warper.warp(mask, K, cameras[idx].R, cv.INTER_NEAREST, cv.BORDER_CONSTANT)
compensator.apply(idx, corners[idx], image_warped, mask_warped)
image_warped_s = image_warped.astype(np.int16)
dilated_mask = cv.dilate(masks_warped[idx], None)
seam_mask = cv.resize(dilated_mask, (mask_warped.shape[1], mask_warped.shape[0]), 0, 0, cv.INTER_LINEAR_EXACT)
mask_warped = cv.bitwise_and(seam_mask, mask_warped)
if blender is None and not timelapse:
blender = cv.detail.Blender_createDefault(cv.detail.Blender_NO)
dst_sz = cv.detail.resultRoi(corners=corners, sizes=sizes)
blend_width = np.sqrt(dst_sz[2] * dst_sz[3]) * blend_strength / 100
if blend_width < 1:
blender = cv.detail.Blender_createDefault(cv.detail.Blender_NO)
elif blend_type == "multiband":
blender = cv.detail_MultiBandBlender()
blender.setNumBands((np.log(blend_width) / np.log(2.) - 1.).astype(np.int32))
elif blend_type == "feather":
blender = cv.detail_FeatherBlender()
blender.setSharpness(1. / blend_width)
blender.prepare(dst_sz)
elif timelapser is None and timelapse:
timelapser = cv.detail.Timelapser_createDefault(timelapse_type)
timelapser.initialize(corners, sizes)
if timelapse:
ma_tones = np.ones((image_warped_s.shape[0], image_warped_s.shape[1]), np.uint8)
timelapser.process(image_warped_s, ma_tones, corners[idx])
pos_s = img_names[idx].rfind("/")
if pos_s == -1:
fixed_file_name = "fixed_" + img_names[idx]
else:
fixed_file_name = img_names[idx][:pos_s + 1] + "fixed_" + img_names[idx][pos_s + 1:]
cv.imwrite(fixed_file_name, timelapser.getDst())
else:
blender.feed(cv.UMat(image_warped_s), mask_warped, corners[idx])
if not timelapse:
result = None
result_mask = None
result, result_mask = blender.blend(result, result_mask)
cv.imwrite(result_name, result)
zoom_x = 600.0 / result.shape[1]
dst = cv.normalize(src=result, dst=None, alpha=255., norm_type=cv.NORM_MINMAX, dtype=cv.CV_8U)
dst = cv.resize(dst, dsize=None, fx=zoom_x, fy=zoom_x)
cv.imshow(result_name, dst)
cv.waitKey()
print("Done")
if __name__ == '__main__':
main()
cv.destroyAllWindows()
+121
View File
@@ -0,0 +1,121 @@
#!/usr/bin/env python
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
from numpy import pi, sin, cos
defaultSize = 512
class TestSceneRender():
def __init__(self, bgImg = None, fgImg = None,
deformation = False, speed = 0.25, **params):
self.time = 0.0
self.timeStep = 1.0 / 30.0
self.foreground = fgImg
self.deformation = deformation
self.speed = speed
if bgImg is not None:
self.sceneBg = bgImg.copy()
else:
self.sceneBg = np.zeros((defaultSize, defaultSize,3), np.uint8)
self.w = self.sceneBg.shape[0]
self.h = self.sceneBg.shape[1]
if fgImg is not None:
self.foreground = fgImg.copy()
self.center = self.currentCenter = (int(self.w/2 - fgImg.shape[0]/2), int(self.h/2 - fgImg.shape[1]/2))
self.xAmpl = self.sceneBg.shape[0] - (self.center[0] + fgImg.shape[0])
self.yAmpl = self.sceneBg.shape[1] - (self.center[1] + fgImg.shape[1])
self.initialRect = np.array([ (self.h/2, self.w/2), (self.h/2, self.w/2 + self.w/10),
(self.h/2 + self.h/10, self.w/2 + self.w/10), (self.h/2 + self.h/10, self.w/2)]).astype(int)
self.currentRect = self.initialRect
def getXOffset(self, time):
return int( self.xAmpl*cos(time*self.speed))
def getYOffset(self, time):
return int(self.yAmpl*sin(time*self.speed))
def setInitialRect(self, rect):
self.initialRect = rect
def getRectInTime(self, time):
if self.foreground is not None:
tmp = np.array(self.center) + np.array((self.getXOffset(time), self.getYOffset(time)))
x0, y0 = tmp
x1, y1 = tmp + self.foreground.shape[0:2]
return np.array([y0, x0, y1, x1])
else:
x0, y0 = self.initialRect[0] + np.array((self.getXOffset(time), self.getYOffset(time)))
x1, y1 = self.initialRect[2] + np.array((self.getXOffset(time), self.getYOffset(time)))
return np.array([y0, x0, y1, x1])
def getCurrentRect(self):
if self.foreground is not None:
x0 = self.currentCenter[0]
y0 = self.currentCenter[1]
x1 = self.currentCenter[0] + self.foreground.shape[0]
y1 = self.currentCenter[1] + self.foreground.shape[1]
return np.array([y0, x0, y1, x1])
else:
x0, y0 = self.currentRect[0]
x1, y1 = self.currentRect[2]
return np.array([x0, y0, x1, y1])
def getNextFrame(self):
img = self.sceneBg.copy()
if self.foreground is not None:
self.currentCenter = (self.center[0] + self.getXOffset(self.time), self.center[1] + self.getYOffset(self.time))
img[self.currentCenter[0]:self.currentCenter[0]+self.foreground.shape[0],
self.currentCenter[1]:self.currentCenter[1]+self.foreground.shape[1]] = self.foreground
else:
self.currentRect = self.initialRect + int( 30*cos(self.time*self.speed) + 50*sin(self.time*self.speed))
if self.deformation:
self.currentRect[1:3] += int(self.h/20*cos(self.time))
cv.fillConvexPoly(img, self.currentRect, (0, 0, 255))
self.time += self.timeStep
return img
def resetTime(self):
self.time = 0.0
def main():
backGr = cv.imread(cv.samples.findFile('graf1.png'))
fgr = cv.imread(cv.samples.findFile('box.png'))
render = TestSceneRender(backGr, fgr)
while True:
img = render.getNextFrame()
cv.imshow('img', img)
ch = cv.waitKey(3)
if ch == 27:
break
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
@@ -0,0 +1,71 @@
from __future__ import print_function
from __future__ import division
import cv2 as cv
import numpy as np
import argparse
def Hist_and_Backproj(val):
## [initialize]
bins = val
histSize = max(bins, 2)
ranges = [0, 180] # hue_range
## [initialize]
## [Get the Histogram and normalize it]
hist = cv.calcHist([hue], [0], None, [histSize], ranges, accumulate=False)
cv.normalize(hist, hist, alpha=0, beta=255, norm_type=cv.NORM_MINMAX)
## [Get the Histogram and normalize it]
## [Get Backprojection]
backproj = cv.calcBackProject([hue], [0], hist, ranges, scale=1)
## [Get Backprojection]
## [Draw the backproj]
cv.imshow('BackProj', backproj)
## [Draw the backproj]
## [Draw the histogram]
w = 400
h = 400
bin_w = int(round(w / histSize))
histImg = np.zeros((h, w, 3), dtype=np.uint8)
for i in range(bins):
cv.rectangle(histImg, (i*bin_w, h), ( (i+1)*bin_w, h - int(np.round( hist[i]*h/255.0 )) ), (0, 0, 255), cv.FILLED)
cv.imshow('Histogram', histImg)
## [Draw the histogram]
## [Read the image]
parser = argparse.ArgumentParser(description='Code for Back Projection tutorial.')
parser.add_argument('--input', help='Path to input image.', default='home.jpg')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
## [Read the image]
## [Transform it to HSV]
hsv = cv.cvtColor(src, cv.COLOR_BGR2HSV)
## [Transform it to HSV]
## [Use only the Hue value]
ch = (0, 0)
hue = np.empty(hsv.shape, hsv.dtype)
cv.mixChannels([hsv], [hue], ch)
## [Use only the Hue value]
## [Create Trackbar to enter the number of bins]
window_image = 'Source image'
cv.namedWindow(window_image)
bins = 25
cv.createTrackbar('* Hue bins: ', window_image, bins, 180, Hist_and_Backproj )
Hist_and_Backproj(bins)
## [Create Trackbar to enter the number of bins]
## [Show the image]
cv.imshow(window_image, src)
cv.waitKey()
## [Show the image]
@@ -0,0 +1,79 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
low = 20
up = 20
def callback_low(val):
global low
low = val
def callback_up(val):
global up
up = val
def pickPoint(event, x, y, flags, param):
if event != cv.EVENT_LBUTTONDOWN:
return
# Fill and get the mask
seed = (x, y)
newMaskVal = 255
newVal = (120, 120, 120)
connectivity = 8
flags = connectivity + (newMaskVal << 8 ) + cv.FLOODFILL_FIXED_RANGE + cv.FLOODFILL_MASK_ONLY
mask2 = np.zeros((src.shape[0] + 2, src.shape[1] + 2), dtype=np.uint8)
print('low:', low, 'up:', up)
cv.floodFill(src, mask2, seed, newVal, (low, low, low), (up, up, up), flags)
mask = mask2[1:-1,1:-1]
cv.imshow('Mask', mask)
Hist_and_Backproj(mask)
def Hist_and_Backproj(mask):
h_bins = 30
s_bins = 32
histSize = [h_bins, s_bins]
h_range = [0, 180]
s_range = [0, 256]
ranges = h_range + s_range # Concat list
channels = [0, 1]
# Get the Histogram and normalize it
hist = cv.calcHist([hsv], channels, mask, histSize, ranges, accumulate=False)
cv.normalize(hist, hist, alpha=0, beta=255, norm_type=cv.NORM_MINMAX)
# Get Backprojection
backproj = cv.calcBackProject([hsv], channels, hist, ranges, scale=1)
# Draw the backproj
cv.imshow('BackProj', backproj)
# Read the image
parser = argparse.ArgumentParser(description='Code for Back Projection tutorial.')
parser.add_argument('--input', help='Path to input image.', default='home.jpg')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
# Transform it to HSV
hsv = cv.cvtColor(src, cv.COLOR_BGR2HSV)
# Show the image
window_image = 'Source image'
cv.namedWindow(window_image)
cv.imshow(window_image, src)
# Set Trackbars for floodfill thresholds
cv.createTrackbar('Low thresh', window_image, low, 255, callback_low)
cv.createTrackbar('High thresh', window_image, up, 255, callback_up)
# Set a Mouse Callback
cv.setMouseCallback(window_image, pickPoint)
cv.waitKey()
@@ -0,0 +1,71 @@
from __future__ import print_function
from __future__ import division
import cv2 as cv
import numpy as np
import argparse
## [Load image]
parser = argparse.ArgumentParser(description='Code for Histogram Calculation tutorial.')
parser.add_argument('--input', help='Path to input image.', default='lena.jpg')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
## [Load image]
## [Separate the image in 3 places ( B, G and R )]
bgr_planes = cv.split(src)
## [Separate the image in 3 places ( B, G and R )]
## [Establish the number of bins]
histSize = 256
## [Establish the number of bins]
## [Set the ranges ( for B,G,R) )]
histRange = (0, 256) # the upper boundary is exclusive
## [Set the ranges ( for B,G,R) )]
## [Set histogram param]
accumulate = False
## [Set histogram param]
## [Compute the histograms]
b_hist = cv.calcHist(bgr_planes, [0], None, [histSize], histRange, accumulate=accumulate)
g_hist = cv.calcHist(bgr_planes, [1], None, [histSize], histRange, accumulate=accumulate)
r_hist = cv.calcHist(bgr_planes, [2], None, [histSize], histRange, accumulate=accumulate)
## [Compute the histograms]
## [Draw the histograms for B, G and R]
hist_w = 512
hist_h = 400
bin_w = int(round( hist_w/histSize ))
histImage = np.zeros((hist_h, hist_w, 3), dtype=np.uint8)
## [Draw the histograms for B, G and R]
## [Normalize the result to ( 0, histImage.rows )]
cv.normalize(b_hist, b_hist, alpha=0, beta=hist_h, norm_type=cv.NORM_MINMAX)
cv.normalize(g_hist, g_hist, alpha=0, beta=hist_h, norm_type=cv.NORM_MINMAX)
cv.normalize(r_hist, r_hist, alpha=0, beta=hist_h, norm_type=cv.NORM_MINMAX)
## [Normalize the result to ( 0, histImage.rows )]
## [Draw for each channel]
for i in range(1, histSize):
cv.line(histImage, ( bin_w*(i-1), hist_h - int(b_hist[i-1]) ),
( bin_w*(i), hist_h - int(b_hist[i]) ),
( 255, 0, 0), thickness=2)
cv.line(histImage, ( bin_w*(i-1), hist_h - int(g_hist[i-1]) ),
( bin_w*(i), hist_h - int(g_hist[i]) ),
( 0, 255, 0), thickness=2)
cv.line(histImage, ( bin_w*(i-1), hist_h - int(r_hist[i-1]) ),
( bin_w*(i), hist_h - int(r_hist[i]) ),
( 0, 0, 255), thickness=2)
## [Draw for each channel]
## [Display]
cv.imshow('Source image', src)
cv.imshow('calcHist Demo', histImage)
cv.waitKey()
## [Display]
@@ -0,0 +1,69 @@
from __future__ import print_function
from __future__ import division
import cv2 as cv
import numpy as np
import argparse
## [Load three images with different environment settings]
parser = argparse.ArgumentParser(description='Code for Histogram Comparison tutorial.')
parser.add_argument('--input1', help='Path to input image 1.')
parser.add_argument('--input2', help='Path to input image 2.')
parser.add_argument('--input3', help='Path to input image 3.')
args = parser.parse_args()
src_base = cv.imread(args.input1)
src_test1 = cv.imread(args.input2)
src_test2 = cv.imread(args.input3)
if src_base is None or src_test1 is None or src_test2 is None:
print('Could not open or find the images!')
exit(0)
## [Load three images with different environment settings]
## [Convert to HSV]
hsv_base = cv.cvtColor(src_base, cv.COLOR_BGR2HSV)
hsv_test1 = cv.cvtColor(src_test1, cv.COLOR_BGR2HSV)
hsv_test2 = cv.cvtColor(src_test2, cv.COLOR_BGR2HSV)
## [Convert to HSV]
## [Convert to HSV half]
hsv_half_down = hsv_base[hsv_base.shape[0]//2:,:]
## [Convert to HSV half]
## [Using 50 bins for hue and 60 for saturation]
h_bins = 50
s_bins = 60
histSize = [h_bins, s_bins]
# hue varies from 0 to 179, saturation from 0 to 255
h_ranges = [0, 180]
s_ranges = [0, 256]
ranges = h_ranges + s_ranges # concat lists
# Use the 0-th and 1-st channels
channels = [0, 1]
## [Using 50 bins for hue and 60 for saturation]
## [Calculate the histograms for the HSV images]
hist_base = cv.calcHist([hsv_base], channels, None, histSize, ranges, accumulate=False)
cv.normalize(hist_base, hist_base, alpha=1, beta=0, norm_type=cv.NORM_L1)
hist_half_down = cv.calcHist([hsv_half_down], channels, None, histSize, ranges, accumulate=False)
cv.normalize(hist_half_down, hist_half_down, alpha=1, beta=0, norm_type=cv.NORM_L1)
hist_test1 = cv.calcHist([hsv_test1], channels, None, histSize, ranges, accumulate=False)
cv.normalize(hist_test1, hist_test1, alpha=1, beta=0, norm_type=cv.NORM_L1)
hist_test2 = cv.calcHist([hsv_test2], channels, None, histSize, ranges, accumulate=False)
cv.normalize(hist_test2, hist_test2, alpha=1, beta=0, norm_type=cv.NORM_L1)
## [Calculate the histograms for the HSV images]
## [Apply the histogram comparison methods]
for compare_method in range(6):
base_base = cv.compareHist(hist_base, hist_base, compare_method)
base_half = cv.compareHist(hist_base, hist_half_down, compare_method)
base_test1 = cv.compareHist(hist_base, hist_test1, compare_method)
base_test2 = cv.compareHist(hist_base, hist_test2, compare_method)
print('Method:', compare_method, 'Perfect, Base-Half, Base-Test(1), Base-Test(2) :',\
base_base, '/', base_half, '/', base_test1, '/', base_test2)
## [Apply the histogram comparison methods]
@@ -0,0 +1,31 @@
from __future__ import print_function
import cv2 as cv
import argparse
## [Load image]
parser = argparse.ArgumentParser(description='Code for Histogram Equalization tutorial.')
parser.add_argument('--input', help='Path to input image.', default='lena.jpg')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
## [Load image]
## [Convert to grayscale]
src = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
## [Convert to grayscale]
## [Apply Histogram Equalization]
dst = cv.equalizeHist(src)
## [Apply Histogram Equalization]
## [Display results]
cv.imshow('Source image', src)
cv.imshow('Equalized Image', dst)
## [Display results]
## [Wait until user exits the program]
cv.waitKey()
## [Wait until user exits the program]
@@ -0,0 +1,54 @@
"""
@file filter2D.py
@brief Sample code that shows how to implement your own linear filters by using filter2D function
"""
import sys
import cv2 as cv
import numpy as np
def main(argv):
window_name = 'filter2D Demo'
## [load]
imageName = argv[0] if len(argv) > 0 else 'lena.jpg'
# Loads an image
src = cv.imread(cv.samples.findFile(imageName), cv.IMREAD_COLOR)
# Check if image is loaded fine
if src is None:
print ('Error opening image!')
print ('Usage: filter2D.py [image_name -- default lena.jpg] \n')
return -1
## [load]
## [init_arguments]
# Initialize ddepth argument for the filter
ddepth = -1
## [init_arguments]
# Loop - Will filter the image with different kernel sizes each 0.5 seconds
ind = 0
while True:
## [update_kernel]
# Update kernel size for a normalized box filter
kernel_size = 3 + 2 * (ind % 5)
kernel = np.ones((kernel_size, kernel_size), dtype=np.float32)
kernel /= (kernel_size * kernel_size)
## [update_kernel]
## [apply_filter]
# Apply filter
dst = cv.filter2D(src, ddepth, kernel)
## [apply_filter]
cv.imshow(window_name, dst)
c = cv.waitKey(500)
if c == 27:
break
ind += 1
return 0
if __name__ == "__main__":
main(sys.argv[1:])
@@ -0,0 +1,59 @@
import sys
import cv2 as cv
import numpy as np
def main(argv):
## [load]
default_file = 'smarties.png'
filename = argv[0] if len(argv) > 0 else default_file
# Loads an image
src = cv.imread(cv.samples.findFile(filename), cv.IMREAD_COLOR)
# Check if image is loaded fine
if src is None:
print ('Error opening image!')
print ('Usage: hough_circle.py [image_name -- default ' + default_file + '] \n')
return -1
## [load]
## [convert_to_gray]
# Convert it to gray
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
## [convert_to_gray]
## [reduce_noise]
# Reduce the noise to avoid false circle detection
gray = cv.medianBlur(gray, 5)
## [reduce_noise]
## [houghcircles]
rows = gray.shape[0]
circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, 1, rows / 8,
param1=100, param2=30,
minRadius=1, maxRadius=30)
## [houghcircles]
## [draw]
if circles is not None:
circles = np.uint16(np.around(circles))
for i in circles[0, :]:
center = (i[0], i[1])
# circle center
cv.circle(src, center, 1, (0, 100, 100), 3)
# circle outline
radius = i[2]
cv.circle(src, center, radius, (255, 0, 255), 3)
## [draw]
## [display]
cv.imshow("detected circles", src)
cv.waitKey(0)
## [display]
return 0
if __name__ == "__main__":
main(sys.argv[1:])
@@ -0,0 +1,79 @@
"""
@file hough_lines.py
@brief This program demonstrates line finding with the Hough transform
"""
import sys
import math
import cv2 as cv
import numpy as np
def main(argv):
## [load]
default_file = 'sudoku.png'
filename = argv[0] if len(argv) > 0 else default_file
# Loads an image
src = cv.imread(cv.samples.findFile(filename), cv.IMREAD_GRAYSCALE)
# Check if image is loaded fine
if src is None:
print ('Error opening image!')
print ('Usage: hough_lines.py [image_name -- default ' + default_file + '] \n')
return -1
## [load]
## [edge_detection]
# Edge detection
dst = cv.Canny(src, 50, 200, None, 3)
## [edge_detection]
# Copy edges to the images that will display the results in BGR
cdst = cv.cvtColor(dst, cv.COLOR_GRAY2BGR)
cdstP = np.copy(cdst)
## [hough_lines]
# Standard Hough Line Transform
lines = cv.HoughLines(dst, 1, np.pi / 180, 150, None, 0, 0)
## [hough_lines]
## [draw_lines]
# Draw the lines
if lines is not None:
for i in range(0, len(lines)):
rho = lines[i][0][0]
theta = lines[i][0][1]
a = math.cos(theta)
b = math.sin(theta)
x0 = a * rho
y0 = b * rho
pt1 = (int(x0 + 1000*(-b)), int(y0 + 1000*(a)))
pt2 = (int(x0 - 1000*(-b)), int(y0 - 1000*(a)))
cv.line(cdst, pt1, pt2, (0,0,255), 3, cv.LINE_AA)
## [draw_lines]
## [hough_lines_p]
# Probabilistic Line Transform
linesP = cv.HoughLinesP(dst, 1, np.pi / 180, 50, None, 50, 10)
## [hough_lines_p]
## [draw_lines_p]
# Draw the lines
if linesP is not None:
for i in range(0, len(linesP)):
l = linesP[i][0]
cv.line(cdstP, (l[0], l[1]), (l[2], l[3]), (0,0,255), 3, cv.LINE_AA)
## [draw_lines_p]
## [imshow]
# Show results
cv.imshow("Source", src)
cv.imshow("Detected Lines (in red) - Standard Hough Line Transform", cdst)
cv.imshow("Detected Lines (in red) - Probabilistic Line Transform", cdstP)
## [imshow]
## [exit]
# Wait and Exit
cv.waitKey()
return 0
## [exit]
if __name__ == "__main__":
main(sys.argv[1:])
@@ -0,0 +1,59 @@
"""
@file laplace_demo.py
@brief Sample code showing how to detect edges using the Laplace operator
"""
import sys
import cv2 as cv
def main(argv):
# [variables]
# Declare the variables we are going to use
ddepth = cv.CV_16S
kernel_size = 3
window_name = "Laplace Demo"
# [variables]
# [load]
imageName = argv[0] if len(argv) > 0 else 'lena.jpg'
src = cv.imread(cv.samples.findFile(imageName), cv.IMREAD_COLOR) # Load an image
# Check if image is loaded fine
if src is None:
print ('Error opening image')
print ('Program Arguments: [image_name -- default lena.jpg]')
return -1
# [load]
# [reduce_noise]
# Remove noise by blurring with a Gaussian filter
src = cv.GaussianBlur(src, (3, 3), 0)
# [reduce_noise]
# [convert_to_gray]
# Convert the image to grayscale
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# [convert_to_gray]
# Create Window
cv.namedWindow(window_name, cv.WINDOW_AUTOSIZE)
# [laplacian]
# Apply Laplace function
dst = cv.Laplacian(src_gray, ddepth, ksize=kernel_size)
# [laplacian]
# [convert]
# converting back to uint8
abs_dst = cv.convertScaleAbs(dst)
# [convert]
# [display]
cv.imshow(window_name, abs_dst)
cv.waitKey(0)
# [display]
return 0
if __name__ == "__main__":
main(sys.argv[1:])
@@ -0,0 +1,69 @@
"""
@file copy_make_border.py
@brief Sample code that shows the functionality of copyMakeBorder
"""
import sys
from random import randint
import cv2 as cv
def main(argv):
## [variables]
# First we declare the variables we are going to use
borderType = cv.BORDER_CONSTANT
window_name = "copyMakeBorder Demo"
## [variables]
## [load]
imageName = argv[0] if len(argv) > 0 else 'lena.jpg'
# Loads an image
src = cv.imread(cv.samples.findFile(imageName), cv.IMREAD_COLOR)
# Check if image is loaded fine
if src is None:
print ('Error opening image!')
print ('Usage: copy_make_border.py [image_name -- default lena.jpg] \n')
return -1
## [load]
# Brief how-to for this program
print ('\n'
'\t copyMakeBorder Demo: \n'
' -------------------- \n'
' ** Press \'c\' to set the border to a random constant value \n'
' ** Press \'r\' to set the border to be replicated \n'
' ** Press \'ESC\' to exit the program ')
## [create_window]
cv.namedWindow(window_name, cv.WINDOW_AUTOSIZE)
## [create_window]
## [init_arguments]
# Initialize arguments for the filter
top = int(0.05 * src.shape[0]) # shape[0] = rows
bottom = top
left = int(0.05 * src.shape[1]) # shape[1] = cols
right = left
## [init_arguments]
while 1:
## [update_value]
value = [randint(0, 255), randint(0, 255), randint(0, 255)]
## [update_value]
## [copymakeborder]
dst = cv.copyMakeBorder(src, top, bottom, left, right, borderType, None, value)
## [copymakeborder]
## [display]
cv.imshow(window_name, dst)
## [display]
## [check_keypress]
c = cv.waitKey(500)
if c == 27:
break
elif c == 99: # 99 = ord('c')
borderType = cv.BORDER_CONSTANT
elif c == 114: # 114 = ord('r')
borderType = cv.BORDER_REPLICATE
## [check_keypress]
return 0
if __name__ == "__main__":
main(sys.argv[1:])
@@ -0,0 +1,74 @@
"""
@file sobel_demo.py
@brief Sample code using Sobel and/or Scharr OpenCV functions to make a simple Edge Detector
"""
import sys
import cv2 as cv
def main(argv):
## [variables]
# First we declare the variables we are going to use
window_name = ('Sobel Demo - Simple Edge Detector')
scale = 1
delta = 0
ddepth = cv.CV_16S
## [variables]
## [load]
# As usual we load our source image (src)
# Check number of arguments
if len(argv) < 1:
print ('Not enough parameters')
print ('Usage:\nmorph_lines_detection.py < path_to_image >')
return -1
# Load the image
src = cv.imread(argv[0], cv.IMREAD_COLOR)
# Check if image is loaded fine
if src is None:
print ('Error opening image: ' + argv[0])
return -1
## [load]
## [reduce_noise]
# Remove noise by blurring with a Gaussian filter ( kernel size = 3 )
src = cv.GaussianBlur(src, (3, 3), 0)
## [reduce_noise]
## [convert_to_gray]
# Convert the image to grayscale
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
## [convert_to_gray]
## [sobel]
# Gradient-X
# grad_x = cv.Scharr(gray,ddepth,1,0)
grad_x = cv.Sobel(gray, ddepth, 1, 0, ksize=3, scale=scale, delta=delta, borderType=cv.BORDER_DEFAULT)
# Gradient-Y
# grad_y = cv.Scharr(gray,ddepth,0,1)
grad_y = cv.Sobel(gray, ddepth, 0, 1, ksize=3, scale=scale, delta=delta, borderType=cv.BORDER_DEFAULT)
## [sobel]
## [convert]
# converting back to uint8
abs_grad_x = cv.convertScaleAbs(grad_x)
abs_grad_y = cv.convertScaleAbs(grad_y)
## [convert]
## [blend]
## Total Gradient (approximate)
grad = cv.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
## [blend]
## [display]
cv.imshow(window_name, grad)
cv.waitKey(0)
## [display]
return 0
if __name__ == "__main__":
main(sys.argv[1:])
@@ -0,0 +1,34 @@
from __future__ import print_function
import cv2 as cv
import argparse
max_lowThreshold = 100
window_name = 'Edge Map'
title_trackbar = 'Min Threshold:'
ratio = 3
kernel_size = 3
def CannyThreshold(val):
low_threshold = val
img_blur = cv.blur(src_gray, (3,3))
detected_edges = cv.Canny(img_blur, low_threshold, low_threshold*ratio, kernel_size)
mask = detected_edges != 0
dst = src * (mask[:,:,None].astype(src.dtype))
cv.imshow(window_name, dst)
parser = argparse.ArgumentParser(description='Code for Canny Edge Detector tutorial.')
parser.add_argument('--input', help='Path to input image.', default='fruits.jpg')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image: ', args.input)
exit(0)
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
cv.namedWindow(window_name)
cv.createTrackbar(title_trackbar, window_name , 0, max_lowThreshold, CannyThreshold)
CannyThreshold(0)
cv.waitKey()
@@ -0,0 +1,139 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
import random as rng
rng.seed(12345)
## [load_image]
# Load the image
parser = argparse.ArgumentParser(description='Code for Image Segmentation with Distance Transform and Watershed Algorithm.\
Sample code showing how to segment overlapping objects using Laplacian filtering, \
in addition to Watershed and Distance Transformation')
parser.add_argument('--input', help='Path to input image.', default='cards.png')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
# Show source image
cv.imshow('Source Image', src)
## [load_image]
## [black_bg]
# Change the background from white to black, since that will help later to extract
# better results during the use of Distance Transform
src[np.all(src == 255, axis=2)] = 0
# Show output image
cv.imshow('Black Background Image', src)
## [black_bg]
## [sharp]
# Create a kernel that we will use to sharpen our image
# an approximation of second derivative, a quite strong kernel
kernel = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]], dtype=np.float32)
# do the laplacian filtering as it is
# well, we need to convert everything in something more deeper then CV_8U
# because the kernel has some negative values,
# and we can expect in general to have a Laplacian image with negative values
# BUT a 8bits unsigned int (the one we are working with) can contain values from 0 to 255
# so the possible negative number will be truncated
imgLaplacian = cv.filter2D(src, cv.CV_32F, kernel)
sharp = np.float32(src)
imgResult = sharp - imgLaplacian
# convert back to 8bits gray scale
imgResult = np.clip(imgResult, 0, 255)
imgResult = imgResult.astype('uint8')
imgLaplacian = np.clip(imgLaplacian, 0, 255)
imgLaplacian = np.uint8(imgLaplacian)
#cv.imshow('Laplace Filtered Image', imgLaplacian)
cv.imshow('New Sharped Image', imgResult)
## [sharp]
## [bin]
# Create binary image from source image
bw = cv.cvtColor(imgResult, cv.COLOR_BGR2GRAY)
_, bw = cv.threshold(bw, 40, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow('Binary Image', bw)
## [bin]
## [dist]
# Perform the distance transform algorithm
dist = cv.distanceTransform(bw, cv.DIST_L2, 3)
# Normalize the distance image for range = {0.0, 1.0}
# so we can visualize and threshold it
cv.normalize(dist, dist, 0, 1.0, cv.NORM_MINMAX)
cv.imshow('Distance Transform Image', dist)
## [dist]
## [peaks]
# Threshold to obtain the peaks
# This will be the markers for the foreground objects
_, dist = cv.threshold(dist, 0.4, 1.0, cv.THRESH_BINARY)
# Dilate a bit the dist image
kernel1 = np.ones((3,3), dtype=np.uint8)
dist = cv.dilate(dist, kernel1)
cv.imshow('Peaks', dist)
## [peaks]
## [seeds]
# Create the CV_8U version of the distance image
# It is needed for findContours()
dist_8u = dist.astype('uint8')
# Find total markers
contours, _ = cv.findContours(dist_8u, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# Create the marker image for the watershed algorithm
markers = np.zeros(dist.shape, dtype=np.int32)
# Draw the foreground markers
for i in range(len(contours)):
cv.drawContours(markers, contours, i, (i+1), -1)
# Draw the background marker
cv.circle(markers, (5,5), 3, (255,255,255), -1)
markers_8u = (markers * 10).astype('uint8')
cv.imshow('Markers', markers_8u)
## [seeds]
## [watershed]
# Perform the watershed algorithm
cv.watershed(imgResult, markers)
#mark = np.zeros(markers.shape, dtype=np.uint8)
mark = markers.astype('uint8')
mark = cv.bitwise_not(mark)
# uncomment this if you want to see how the mark
# image looks like at that point
#cv.imshow('Markers_v2', mark)
# Generate random colors
colors = []
for contour in contours:
colors.append((rng.randint(0,256), rng.randint(0,256), rng.randint(0,256)))
# Create the result image
dst = np.zeros((markers.shape[0], markers.shape[1], 3), dtype=np.uint8)
# Fill labeled objects with random colors
for i in range(markers.shape[0]):
for j in range(markers.shape[1]):
index = markers[i,j]
if index > 0 and index <= len(contours):
dst[i,j,:] = colors[index-1]
# Visualize the final image
cv.imshow('Final Result', dst)
## [watershed]
cv.waitKey()
@@ -0,0 +1,65 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
## [Update]
def update_map(ind, map_x, map_y):
if ind == 0:
for i in range(map_x.shape[0]):
for j in range(map_x.shape[1]):
if j > map_x.shape[1]*0.25 and j < map_x.shape[1]*0.75 and i > map_x.shape[0]*0.25 and i < map_x.shape[0]*0.75:
map_x[i,j] = 2 * (j-map_x.shape[1]*0.25) + 0.5
map_y[i,j] = 2 * (i-map_y.shape[0]*0.25) + 0.5
else:
map_x[i,j] = 0
map_y[i,j] = 0
elif ind == 1:
for i in range(map_x.shape[0]):
map_x[i,:] = [x for x in range(map_x.shape[1])]
for j in range(map_y.shape[1]):
map_y[:,j] = [map_y.shape[0]-y for y in range(map_y.shape[0])]
elif ind == 2:
for i in range(map_x.shape[0]):
map_x[i,:] = [map_x.shape[1]-x for x in range(map_x.shape[1])]
for j in range(map_y.shape[1]):
map_y[:,j] = [y for y in range(map_y.shape[0])]
elif ind == 3:
for i in range(map_x.shape[0]):
map_x[i,:] = [map_x.shape[1]-x for x in range(map_x.shape[1])]
for j in range(map_y.shape[1]):
map_y[:,j] = [map_y.shape[0]-y for y in range(map_y.shape[0])]
## [Update]
parser = argparse.ArgumentParser(description='Code for Remapping tutorial.')
parser.add_argument('--input', help='Path to input image.', default='chicky_512.png')
args = parser.parse_args()
## [Load]
src = cv.imread(cv.samples.findFile(args.input), cv.IMREAD_COLOR)
if src is None:
print('Could not open or find the image: ', args.input)
exit(0)
## [Load]
## [Create]
map_x = np.zeros((src.shape[0], src.shape[1]), dtype=np.float32)
map_y = np.zeros((src.shape[0], src.shape[1]), dtype=np.float32)
## [Create]
## [Window]
window_name = 'Remap demo'
cv.namedWindow(window_name)
## [Window]
## [Loop]
ind = 0
while True:
update_map(ind, map_x, map_y)
ind = (ind + 1) % 4
dst = cv.remap(src, map_x, map_y, cv.INTER_LINEAR)
cv.imshow(window_name, dst)
c = cv.waitKey(1000)
if c == 27:
break
## [Loop]
@@ -0,0 +1,54 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
## [Load the image]
parser = argparse.ArgumentParser(description='Code for Affine Transformations tutorial.')
parser.add_argument('--input', help='Path to input image.', default='lena.jpg')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
## [Load the image]
## [Set your 3 points to calculate the Affine Transform]
srcTri = np.array( [[0, 0], [src.shape[1] - 1, 0], [0, src.shape[0] - 1]] ).astype(np.float32)
dstTri = np.array( [[0, src.shape[1]*0.33], [src.shape[1]*0.85, src.shape[0]*0.25], [src.shape[1]*0.15, src.shape[0]*0.7]] ).astype(np.float32)
## [Set your 3 points to calculate the Affine Transform]
## [Get the Affine Transform]
warp_mat = cv.getAffineTransform(srcTri, dstTri)
## [Get the Affine Transform]
## [Apply the Affine Transform just found to the src image]
warp_dst = cv.warpAffine(src, warp_mat, (src.shape[1], src.shape[0]))
## [Apply the Affine Transform just found to the src image]
# Rotating the image after Warp
## [Compute a rotation matrix with respect to the center of the image]
center = (warp_dst.shape[1]//2, warp_dst.shape[0]//2)
angle = -50
scale = 0.6
## [Compute a rotation matrix with respect to the center of the image]
## [Get the rotation matrix with the specifications above]
rot_mat = cv.getRotationMatrix2D( center, angle, scale )
## [Get the rotation matrix with the specifications above]
## [Rotate the warped image]
warp_rotate_dst = cv.warpAffine(warp_dst, rot_mat, (warp_dst.shape[1], warp_dst.shape[0]))
## [Rotate the warped image]
## [Show what you got]
cv.imshow('Source image', src)
cv.imshow('Warp', warp_dst)
cv.imshow('Warp + Rotate', warp_rotate_dst)
## [Show what you got]
## [Wait until user exits the program]
cv.waitKey()
## [Wait until user exits the program]
@@ -0,0 +1,82 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
import random as rng
rng.seed(12345)
def thresh_callback(val):
threshold = val
## [Canny]
# Detect edges using Canny
canny_output = cv.Canny(src_gray, threshold, threshold * 2)
## [Canny]
## [findContours]
# Find contours
contours, _ = cv.findContours(canny_output, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
## [findContours]
## [allthework]
# Approximate contours to polygons + get bounding rects and circles
contours_poly = [None]*len(contours)
boundRect = [None]*len(contours)
centers = [None]*len(contours)
radius = [None]*len(contours)
for i, c in enumerate(contours):
contours_poly[i] = cv.approxPolyDP(c, 3, True)
boundRect[i] = cv.boundingRect(contours_poly[i])
centers[i], radius[i] = cv.minEnclosingCircle(contours_poly[i])
## [allthework]
## [zeroMat]
drawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)
## [zeroMat]
## [forContour]
# Draw polygonal contour + bonding rects + circles
for i in range(len(contours)):
color = (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256))
cv.drawContours(drawing, contours_poly, i, color)
cv.rectangle(drawing, (int(boundRect[i][0]), int(boundRect[i][1])), \
(int(boundRect[i][0]+boundRect[i][2]), int(boundRect[i][1]+boundRect[i][3])), color, 2)
cv.circle(drawing, (int(centers[i][0]), int(centers[i][1])), int(radius[i]), color, 2)
## [forContour]
## [showDrawings]
# Show in a window
cv.imshow('Contours', drawing)
## [showDrawings]
## [setup]
# Load source image
parser = argparse.ArgumentParser(description='Code for Creating Bounding boxes and circles for contours tutorial.')
parser.add_argument('--input', help='Path to input image.', default='stuff.jpg')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
# Convert image to gray and blur it
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
src_gray = cv.blur(src_gray, (3,3))
## [setup]
## [createWindow]
# Create Window
source_window = 'Source'
cv.namedWindow(source_window)
cv.imshow(source_window, src)
## [createWindow]
## [trackbar]
max_thresh = 255
thresh = 100 # initial threshold
cv.createTrackbar('Canny thresh:', source_window, thresh, max_thresh, thresh_callback)
thresh_callback(thresh)
## [trackbar]
cv.waitKey()
@@ -0,0 +1,82 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
import random as rng
rng.seed(12345)
def thresh_callback(val):
threshold = val
## [Canny]
# Detect edges using Canny
canny_output = cv.Canny(src_gray, threshold, threshold * 2)
## [Canny]
## [findContours]
# Find contours
contours, _ = cv.findContours(canny_output, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
## [findContours]
# Find the rotated rectangles and ellipses for each contour
minRect = [None]*len(contours)
minEllipse = [None]*len(contours)
for i, c in enumerate(contours):
minRect[i] = cv.minAreaRect(c)
if c.shape[0] > 5:
minEllipse[i] = cv.fitEllipse(c)
# Draw contours + rotated rects + ellipses
## [zeroMat]
drawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)
## [zeroMat]
## [forContour]
for i, c in enumerate(contours):
color = (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256))
# contour
cv.drawContours(drawing, contours, i, color)
# ellipse
if c.shape[0] > 5:
cv.ellipse(drawing, minEllipse[i], color, 2)
# rotated rectangle
box = cv.boxPoints(minRect[i])
box = np.intp(box) #np.intp: Integer used for indexing (same as C ssize_t; normally either int32 or int64)
cv.drawContours(drawing, [box], 0, color)
## [forContour]
## [showDrawings]
# Show in a window
cv.imshow('Contours', drawing)
## [showDrawings]
## [setup]
# Load source image
parser = argparse.ArgumentParser(description='Code for Creating Bounding rotated boxes and ellipses for contours tutorial.')
parser.add_argument('--input', help='Path to input image.', default='stuff.jpg')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
# Convert image to gray and blur it
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
src_gray = cv.blur(src_gray, (3,3))
## [setup]
## [createWindow]
# Create Window
source_window = 'Source'
cv.namedWindow(source_window)
cv.imshow(source_window, src)
## [createWindow]
## [trackbar]
max_thresh = 255
thresh = 100 # initial threshold
cv.createTrackbar('Canny Thresh:', source_window, thresh, max_thresh, thresh_callback)
thresh_callback(thresh)
## [trackbar]
cv.waitKey()
@@ -0,0 +1,50 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
import random as rng
rng.seed(12345)
def thresh_callback(val):
threshold = val
# Detect edges using Canny
canny_output = cv.Canny(src_gray, threshold, threshold * 2)
# Find contours
contours, hierarchy = cv.findContours(canny_output, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# Draw contours
drawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)
for i in range(len(contours)):
color = (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256))
cv.drawContours(drawing, contours, i, color, 2, cv.LINE_8, hierarchy, 0)
# Show in a window
cv.imshow('Contours', drawing)
# Load source image
parser = argparse.ArgumentParser(description='Code for Finding contours in your image tutorial.')
parser.add_argument('--input', help='Path to input image.', default='HappyFish.jpg')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
# Convert image to gray and blur it
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
src_gray = cv.blur(src_gray, (3,3))
# Create Window
source_window = 'Source'
cv.namedWindow(source_window)
cv.imshow(source_window, src)
max_thresh = 255
thresh = 100 # initial threshold
cv.createTrackbar('Canny Thresh:', source_window, thresh, max_thresh, thresh_callback)
thresh_callback(thresh)
cv.waitKey()
@@ -0,0 +1,57 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
import random as rng
rng.seed(12345)
def thresh_callback(val):
threshold = val
# Detect edges using Canny
canny_output = cv.Canny(src_gray, threshold, threshold * 2)
# Find contours
contours, _ = cv.findContours(canny_output, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# Find the convex hull object for each contour
hull_list = []
for i in range(len(contours)):
hull = cv.convexHull(contours[i])
hull_list.append(hull)
# Draw contours + hull results
drawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)
for i in range(len(contours)):
color = (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256))
cv.drawContours(drawing, contours, i, color)
cv.drawContours(drawing, hull_list, i, color)
# Show in a window
cv.imshow('Contours', drawing)
# Load source image
parser = argparse.ArgumentParser(description='Code for Convex Hull tutorial.')
parser.add_argument('--input', help='Path to input image.', default='stuff.jpg')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
# Convert image to gray and blur it
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
src_gray = cv.blur(src_gray, (3,3))
# Create Window
source_window = 'Source'
cv.namedWindow(source_window)
cv.imshow(source_window, src)
max_thresh = 255
thresh = 100 # initial threshold
cv.createTrackbar('Canny thresh:', source_window, thresh, max_thresh, thresh_callback)
thresh_callback(thresh)
cv.waitKey()
@@ -0,0 +1,83 @@
from __future__ import print_function
from __future__ import division
import cv2 as cv
import numpy as np
import argparse
import random as rng
rng.seed(12345)
def thresh_callback(val):
threshold = val
## [Canny]
# Detect edges using Canny
canny_output = cv.Canny(src_gray, threshold, threshold * 2)
## [Canny]
## [findContours]
# Find contours
contours, _ = cv.findContours(canny_output, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
## [findContours]
# Get the moments
mu = [None]*len(contours)
for i in range(len(contours)):
mu[i] = cv.moments(contours[i])
# Get the mass centers
mc = [None]*len(contours)
for i in range(len(contours)):
# add 1e-5 to avoid division by zero
mc[i] = (mu[i]['m10'] / (mu[i]['m00'] + 1e-5), mu[i]['m01'] / (mu[i]['m00'] + 1e-5))
# Draw contours
## [zeroMat]
drawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)
## [zeroMat]
## [forContour]
for i in range(len(contours)):
color = (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256))
cv.drawContours(drawing, contours, i, color, 2)
cv.circle(drawing, (int(mc[i][0]), int(mc[i][1])), 4, color, -1)
## [forContour]
## [showDrawings]
# Show in a window
cv.imshow('Contours', drawing)
## [showDrawings]
# Calculate the area with the moments 00 and compare with the result of the OpenCV function
for i in range(len(contours)):
print(' * Contour[%d] - Area (M_00) = %.2f - Area OpenCV: %.2f - Length: %.2f' % (i, mu[i]['m00'], cv.contourArea(contours[i]), cv.arcLength(contours[i], True)))
## [setup]
# Load source image
parser = argparse.ArgumentParser(description='Code for Image Moments tutorial.')
parser.add_argument('--input', help='Path to input image.', default='stuff.jpg')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
# Convert image to gray and blur it
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
src_gray = cv.blur(src_gray, (3,3))
## [setup]
## [createWindow]
# Create Window
source_window = 'Source'
cv.namedWindow(source_window)
cv.imshow(source_window, src)
## [createWindow]
## [trackbar]
max_thresh = 255
thresh = 100 # initial threshold
cv.createTrackbar('Canny Thresh:', source_window, thresh, max_thresh, thresh_callback)
thresh_callback(thresh)
## [trackbar]
cv.waitKey()
@@ -0,0 +1,52 @@
from __future__ import print_function
from __future__ import division
import cv2 as cv
import numpy as np
# Create an image
r = 100
src = np.zeros((4*r, 4*r), dtype=np.uint8)
# Create a sequence of points to make a contour
vert = [None]*6
vert[0] = (3*r//2, int(1.34*r))
vert[1] = (1*r, 2*r)
vert[2] = (3*r//2, int(2.866*r))
vert[3] = (5*r//2, int(2.866*r))
vert[4] = (3*r, 2*r)
vert[5] = (5*r//2, int(1.34*r))
# Draw it in src
for i in range(6):
cv.line(src, vert[i], vert[(i+1)%6], ( 255 ), 3)
# Get the contours
contours, _ = cv.findContours(src, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# Calculate the distances to the contour
raw_dist = np.empty(src.shape, dtype=np.float32)
for i in range(src.shape[0]):
for j in range(src.shape[1]):
raw_dist[i,j] = cv.pointPolygonTest(contours[0], (j,i), True)
minVal, maxVal, _, maxDistPt = cv.minMaxLoc(raw_dist)
minVal = abs(minVal)
maxVal = abs(maxVal)
# Depicting the distances graphically
drawing = np.zeros((src.shape[0], src.shape[1], 3), dtype=np.uint8)
for i in range(src.shape[0]):
for j in range(src.shape[1]):
if raw_dist[i,j] < 0:
drawing[i,j,0] = 255 - abs(raw_dist[i,j]) * 255 / minVal
elif raw_dist[i,j] > 0:
drawing[i,j,2] = 255 - raw_dist[i,j] * 255 / maxVal
else:
drawing[i,j,0] = 255
drawing[i,j,1] = 255
drawing[i,j,2] = 255
cv.circle(drawing,maxDistPt, int(maxVal),(255,255,255), 1, cv.LINE_8, 0)
cv.imshow('Source', src)
cv.imshow('Distance and inscribed circle', drawing)
cv.waitKey()
@@ -0,0 +1,70 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
import random as rng
source_window = 'Image'
maxTrackbar = 25
rng.seed(12345)
def goodFeaturesToTrack_Demo(val):
maxCorners = max(val, 1)
# Parameters for Shi-Tomasi algorithm
qualityLevel = 0.01
minDistance = 10
blockSize = 3
gradientSize = 3
useHarrisDetector = False
k = 0.04
# Copy the source image
copy = np.copy(src)
# Apply corner detection
corners = cv.goodFeaturesToTrack(src_gray, maxCorners, qualityLevel, minDistance, None, \
blockSize=blockSize, gradientSize=gradientSize, useHarrisDetector=useHarrisDetector, k=k)
# Draw corners detected
print('** Number of corners detected:', corners.shape[0])
radius = 4
for i in range(corners.shape[0]):
cv.circle(copy, (int(corners[i,0,0]), int(corners[i,0,1])), radius, (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256)), cv.FILLED)
# Show what you got
cv.namedWindow(source_window)
cv.imshow(source_window, copy)
# Set the needed parameters to find the refined corners
winSize = (5, 5)
zeroZone = (-1, -1)
criteria = (cv.TERM_CRITERIA_EPS + cv.TermCriteria_COUNT, 40, 0.001)
# Calculate the refined corner locations
corners = cv.cornerSubPix(src_gray, corners, winSize, zeroZone, criteria)
# Write them down
for i in range(corners.shape[0]):
print(" -- Refined Corner [", i, "] (", corners[i,0,0], ",", corners[i,0,1], ")")
# Load source image and convert it to gray
parser = argparse.ArgumentParser(description='Code for Shi-Tomasi corner detector tutorial.')
parser.add_argument('--input', help='Path to input image.', default='pic3.png')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# Create a window and a trackbar
cv.namedWindow(source_window)
maxCorners = 10 # initial threshold
cv.createTrackbar('Threshold: ', source_window, maxCorners, maxTrackbar, goodFeaturesToTrack_Demo)
cv.imshow(source_window, src)
goodFeaturesToTrack_Demo(maxCorners)
cv.waitKey()
@@ -0,0 +1,80 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
import random as rng
myHarris_window = 'My Harris corner detector'
myShiTomasi_window = 'My Shi Tomasi corner detector'
myHarris_qualityLevel = 50
myShiTomasi_qualityLevel = 50
max_qualityLevel = 100
rng.seed(12345)
def myHarris_function(val):
myHarris_copy = np.copy(src)
myHarris_qualityLevel = max(val, 1)
for i in range(src_gray.shape[0]):
for j in range(src_gray.shape[1]):
if Mc[i,j] > myHarris_minVal + ( myHarris_maxVal - myHarris_minVal )*myHarris_qualityLevel/max_qualityLevel:
cv.circle(myHarris_copy, (j,i), 4, (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256)), cv.FILLED)
cv.imshow(myHarris_window, myHarris_copy)
def myShiTomasi_function(val):
myShiTomasi_copy = np.copy(src)
myShiTomasi_qualityLevel = max(val, 1)
for i in range(src_gray.shape[0]):
for j in range(src_gray.shape[1]):
if myShiTomasi_dst[i,j] > myShiTomasi_minVal + ( myShiTomasi_maxVal - myShiTomasi_minVal )*myShiTomasi_qualityLevel/max_qualityLevel:
cv.circle(myShiTomasi_copy, (j,i), 4, (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256)), cv.FILLED)
cv.imshow(myShiTomasi_window, myShiTomasi_copy)
# Load source image and convert it to gray
parser = argparse.ArgumentParser(description='Code for Creating your own corner detector tutorial.')
parser.add_argument('--input', help='Path to input image.', default='building.jpg')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# Set some parameters
blockSize = 3
apertureSize = 3
# My Harris matrix -- Using cornerEigenValsAndVecs
myHarris_dst = cv.cornerEigenValsAndVecs(src_gray, blockSize, apertureSize)
# calculate Mc
Mc = np.empty(src_gray.shape, dtype=np.float32)
for i in range(src_gray.shape[0]):
for j in range(src_gray.shape[1]):
lambda_1 = myHarris_dst[i,j,0]
lambda_2 = myHarris_dst[i,j,1]
Mc[i,j] = lambda_1*lambda_2 - 0.04*pow( ( lambda_1 + lambda_2 ), 2 )
myHarris_minVal, myHarris_maxVal, _, _ = cv.minMaxLoc(Mc)
# Create Window and Trackbar
cv.namedWindow(myHarris_window)
cv.createTrackbar('Quality Level:', myHarris_window, myHarris_qualityLevel, max_qualityLevel, myHarris_function)
myHarris_function(myHarris_qualityLevel)
# My Shi-Tomasi -- Using cornerMinEigenVal
myShiTomasi_dst = cv.cornerMinEigenVal(src_gray, blockSize, apertureSize)
myShiTomasi_minVal, myShiTomasi_maxVal, _, _ = cv.minMaxLoc(myShiTomasi_dst)
# Create Window and Trackbar
cv.namedWindow(myShiTomasi_window)
cv.createTrackbar('Quality Level:', myShiTomasi_window, myShiTomasi_qualityLevel, max_qualityLevel, myShiTomasi_function)
myShiTomasi_function(myShiTomasi_qualityLevel)
cv.waitKey()
@@ -0,0 +1,58 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
import random as rng
source_window = 'Image'
maxTrackbar = 100
rng.seed(12345)
def goodFeaturesToTrack_Demo(val):
maxCorners = max(val, 1)
# Parameters for Shi-Tomasi algorithm
qualityLevel = 0.01
minDistance = 10
blockSize = 3
gradientSize = 3
useHarrisDetector = False
k = 0.04
# Copy the source image
copy = np.copy(src)
# Apply corner detection
corners = cv.goodFeaturesToTrack(src_gray, maxCorners, qualityLevel, minDistance, None, \
blockSize=blockSize, gradientSize=gradientSize, useHarrisDetector=useHarrisDetector, k=k)
# Draw corners detected
print('** Number of corners detected:', corners.shape[0])
radius = 4
for i in range(corners.shape[0]):
cv.circle(copy, (int(corners[i,0,0]), int(corners[i,0,1])), radius, (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256)), cv.FILLED)
# Show what you got
cv.namedWindow(source_window)
cv.imshow(source_window, copy)
# Load source image and convert it to gray
parser = argparse.ArgumentParser(description='Code for Shi-Tomasi corner detector tutorial.')
parser.add_argument('--input', help='Path to input image.', default='pic3.png')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# Create a window and a trackbar
cv.namedWindow(source_window)
maxCorners = 23 # initial threshold
cv.createTrackbar('Threshold: ', source_window, maxCorners, maxTrackbar, goodFeaturesToTrack_Demo)
cv.imshow(source_window, src)
goodFeaturesToTrack_Demo(maxCorners)
cv.waitKey()
@@ -0,0 +1,55 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
source_window = 'Source image'
corners_window = 'Corners detected'
max_thresh = 255
def cornerHarris_demo(val):
thresh = val
# Detector parameters
blockSize = 2
apertureSize = 3
k = 0.04
# Detecting corners
dst = cv.cornerHarris(src_gray, blockSize, apertureSize, k)
# Normalizing
dst_norm = np.empty(dst.shape, dtype=np.float32)
cv.normalize(dst, dst_norm, alpha=0, beta=255, norm_type=cv.NORM_MINMAX)
dst_norm_scaled = cv.convertScaleAbs(dst_norm)
# Drawing a circle around corners
for i in range(dst_norm.shape[0]):
for j in range(dst_norm.shape[1]):
if int(dst_norm[i,j]) > thresh:
cv.circle(dst_norm_scaled, (j,i), 5, (0), 2)
# Showing the result
cv.namedWindow(corners_window)
cv.imshow(corners_window, dst_norm_scaled)
# Load source image and convert it to gray
parser = argparse.ArgumentParser(description='Code for Harris corner detector tutorial.')
parser.add_argument('--input', help='Path to input image.', default='building.jpg')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# Create a window and a trackbar
cv.namedWindow(source_window)
thresh = 200 # initial threshold
cv.createTrackbar('Threshold: ', source_window, thresh, max_thresh, cornerHarris_demo)
cv.imshow(source_window, src)
cornerHarris_demo(thresh)
cv.waitKey()
@@ -0,0 +1,36 @@
from __future__ import print_function
import cv2 as cv
alpha = 0.5
try:
raw_input # Python 2
except NameError:
raw_input = input # Python 3
print(''' Simple Linear Blender
-----------------------
* Enter alpha [0.0-1.0]: ''')
input_alpha = float(raw_input().strip())
if 0 <= alpha <= 1:
alpha = input_alpha
# [load]
src1 = cv.imread(cv.samples.findFile('LinuxLogo.jpg'))
src2 = cv.imread(cv.samples.findFile('WindowsLogo.jpg'))
# [load]
if src1 is None:
print("Error loading src1")
exit(-1)
elif src2 is None:
print("Error loading src2")
exit(-1)
# [blend_images]
beta = (1.0 - alpha)
dst = cv.addWeighted(src1, alpha, src2, beta, 0.0)
# [blend_images]
# [display]
cv.imshow('dst', dst)
cv.waitKey(0)
# [display]
cv.destroyAllWindows()
@@ -0,0 +1,80 @@
from __future__ import print_function
import sys
import cv2 as cv
import numpy as np
def print_help():
print('''
This program demonstrated the use of the discrete Fourier transform (DFT).
The dft of an image is taken and it's power spectrum is displayed.
Usage:
discrete_fourier_transform.py [image_name -- default lena.jpg]''')
def main(argv):
print_help()
filename = argv[0] if len(argv) > 0 else 'lena.jpg'
I = cv.imread(cv.samples.findFile(filename), cv.IMREAD_GRAYSCALE)
if I is None:
print('Error opening image')
return -1
## [expand]
rows, cols = I.shape
m = cv.getOptimalDFTSize( rows )
n = cv.getOptimalDFTSize( cols )
padded = cv.copyMakeBorder(I, 0, m - rows, 0, n - cols, cv.BORDER_CONSTANT, value=[0, 0, 0])
## [expand]
## [complex_and_real]
planes = [np.float32(padded), np.zeros(padded.shape, np.float32)]
complexI = cv.merge(planes) # Add to the expanded another plane with zeros
## [complex_and_real]
## [dft]
cv.dft(complexI, complexI) # this way the result may fit in the source matrix
## [dft]
# compute the magnitude and switch to logarithmic scale
# = > log(1 + sqrt(Re(DFT(I)) ^ 2 + Im(DFT(I)) ^ 2))
## [magnitude]
cv.split(complexI, planes) # planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))
cv.magnitude(planes[0], planes[1], planes[0])# planes[0] = magnitude
magI = planes[0]
## [magnitude]
## [log]
matOfOnes = np.ones(magI.shape, dtype=magI.dtype)
cv.add(matOfOnes, magI, magI) # switch to logarithmic scale
cv.log(magI, magI)
## [log]
## [crop_rearrange]
magI_rows, magI_cols = magI.shape
# crop the spectrum, if it has an odd number of rows or columns
magI = magI[0:(magI_rows & -2), 0:(magI_cols & -2)]
cx = int(magI_rows/2)
cy = int(magI_cols/2)
q0 = magI[0:cx, 0:cy] # Top-Left - Create a ROI per quadrant
q1 = magI[cx:cx+cx, 0:cy] # Top-Right
q2 = magI[0:cx, cy:cy+cy] # Bottom-Left
q3 = magI[cx:cx+cx, cy:cy+cy] # Bottom-Right
tmp = np.copy(q0) # swap quadrants (Top-Left with Bottom-Right)
magI[0:cx, 0:cy] = q3
magI[cx:cx + cx, cy:cy + cy] = tmp
tmp = np.copy(q1) # swap quadrant (Top-Right with Bottom-Left)
magI[cx:cx + cx, 0:cy] = q2
magI[0:cx, cy:cy + cy] = tmp
## [crop_rearrange]
## [normalize]
cv.normalize(magI, magI, 0, 1, cv.NORM_MINMAX) # Transform the matrix with float values into a
## viewable image form(float between values 0 and 1).
## [normalize]
cv.imshow("Input Image" , I ) # Show the result
cv.imshow("spectrum magnitude", magI)
cv.waitKey()
if __name__ == "__main__":
main(sys.argv[1:])
@@ -0,0 +1,157 @@
from __future__ import print_function
import numpy as np
import cv2 as cv
import sys
def help(filename):
print (
'''
{0} shows the usage of the OpenCV serialization functionality. \n\n
usage:\n
python3 {0} [output file name] (default outputfile.yml.gz)\n\n
The output file may be XML (xml), YAML (yml/yaml), or JSON (json).\n
You can even compress it by specifying this in its extension like xml.gz yaml.gz etc...\n
With FileStorage you can serialize objects in OpenCV.\n\n
For example: - create a class and have it serialized\n
- use it to read and write matrices.\n
'''.format(filename)
)
class MyData:
A = 97
X = np.pi
name = 'mydata1234'
def __repr__(self):
s = '{ name = ' + self.name + ', X = ' + str(self.X)
s = s + ', A = ' + str(self.A) + '}'
return s
## [inside]
def write(self, fs, name):
fs.startWriteStruct(name, cv.FileNode_MAP|cv.FileNode_FLOW)
fs.write('A', self.A)
fs.write('X', self.X)
fs.write('name', self.name)
fs.endWriteStruct()
def read(self, node):
if (not node.empty()):
self.A = int(node.getNode('A').real())
self.X = node.getNode('X').real()
self.name = node.getNode('name').string()
else:
self.A = self.X = 0
self.name = ''
## [inside]
def main(argv):
if len(argv) != 2:
help(argv[0])
filename = 'outputfile.yml.gz'
else :
filename = argv[1]
# write
## [iomati]
R = np.eye(3,3)
T = np.zeros((3,1))
## [iomati]
## [customIOi]
m = MyData()
## [customIOi]
## [open]
s = cv.FileStorage(filename, cv.FileStorage_WRITE)
# or:
# s = cv.FileStorage()
# s.open(filename, cv.FileStorage_WRITE)
## [open]
## [writeNum]
s.write('iterationNr', 100)
## [writeNum]
## [writeStr]
s.startWriteStruct('strings', cv.FileNode_SEQ)
for elem in ['image1.jpg', 'Awesomeness', '../data/baboon.jpg']:
s.write('', elem)
s.endWriteStruct()
## [writeStr]
## [writeMap]
s.startWriteStruct('Mapping', cv.FileNode_MAP)
s.write('One', 1)
s.write('Two', 2)
s.endWriteStruct()
## [writeMap]
## [iomatw]
s.write('R_MAT', R)
s.write('T_MAT', T)
## [iomatw]
## [customIOw]
m.write(s, 'MyData')
## [customIOw]
## [close]
s.release()
## [close]
print ('Write operation to file:', filename, 'completed successfully.')
# read
print ('\nReading: ')
s = cv.FileStorage()
s.open(filename, cv.FileStorage_READ)
## [readNum]
n = s.getNode('iterationNr')
itNr = int(n.real())
## [readNum]
print (itNr)
if (not s.isOpened()):
print ('Failed to open ', filename, file=sys.stderr)
help(argv[0])
exit(1)
## [readStr]
n = s.getNode('strings')
if (not n.isSeq()):
print ('strings is not a sequence! FAIL', file=sys.stderr)
exit(1)
for i in range(n.size()):
print (n.at(i).string())
## [readStr]
## [readMap]
n = s.getNode('Mapping')
print ('Two',int(n.getNode('Two').real()),'; ')
print ('One',int(n.getNode('One').real()),'\n')
## [readMap]
## [iomat]
R = s.getNode('R_MAT').mat()
T = s.getNode('T_MAT').mat()
## [iomat]
## [customIO]
m.read(s.getNode('MyData'))
## [customIO]
print ('\nR =',R)
print ('T =',T,'\n')
print ('MyData =','\n',m,'\n')
## [nonexist]
print ('Attempt to read NonExisting (should initialize the data structure',
'with its default).')
m.read(s.getNode('NonExisting'))
print ('\nNonExisting =','\n',m)
## [nonexist]
print ('\nTip: Open up',filename,'with a text editor to see the serialized data.')
if __name__ == '__main__':
main(sys.argv)
@@ -0,0 +1,100 @@
from __future__ import print_function
import sys
import time
import numpy as np
import cv2 as cv
## [basic_method]
def is_grayscale(my_image):
return len(my_image.shape) < 3
def saturated(sum_value):
if sum_value > 255:
sum_value = 255
if sum_value < 0:
sum_value = 0
return sum_value
def sharpen(my_image):
if is_grayscale(my_image):
height, width = my_image.shape
else:
my_image = cv.cvtColor(my_image, cv.CV_8U)
height, width, n_channels = my_image.shape
result = np.zeros(my_image.shape, my_image.dtype)
## [basic_method_loop]
for j in range(1, height - 1):
for i in range(1, width - 1):
if is_grayscale(my_image):
sum_value = 5 * my_image[j, i] - my_image[j + 1, i] - my_image[j - 1, i] \
- my_image[j, i + 1] - my_image[j, i - 1]
result[j, i] = saturated(sum_value)
else:
for k in range(0, n_channels):
sum_value = 5 * my_image[j, i, k] - my_image[j + 1, i, k] \
- my_image[j - 1, i, k] - my_image[j, i + 1, k]\
- my_image[j, i - 1, k]
result[j, i, k] = saturated(sum_value)
## [basic_method_loop]
return result
## [basic_method]
def main(argv):
filename = 'lena.jpg'
img_codec = cv.IMREAD_COLOR
if argv:
filename = sys.argv[1]
if len(argv) >= 2 and sys.argv[2] == "G":
img_codec = cv.IMREAD_GRAYSCALE
src = cv.imread(cv.samples.findFile(filename), img_codec)
if src is None:
print("Can't open image [" + filename + "]")
print("Usage:")
print("mat_mask_operations.py [image_path -- default lena.jpg] [G -- grayscale]")
return -1
cv.namedWindow("Input", cv.WINDOW_AUTOSIZE)
cv.namedWindow("Output", cv.WINDOW_AUTOSIZE)
cv.imshow("Input", src)
t = round(time.time())
dst0 = sharpen(src)
t = (time.time() - t)
print("Hand written function time passed in seconds: %s" % t)
cv.imshow("Output", dst0)
cv.waitKey()
t = time.time()
## [kern]
kernel = np.array([[0, -1, 0],
[-1, 5, -1],
[0, -1, 0]], np.float32) # kernel should be floating point type
## [kern]
## [filter2D]
dst1 = cv.filter2D(src, -1, kernel)
# ddepth = -1, means destination image has depth same as input image
## [filter2D]
t = (time.time() - t)
print("Built-in filter2D time passed in seconds: %s" % t)
cv.imshow("Output", dst1)
cv.waitKey(0)
cv.destroyAllWindows()
return 0
if __name__ == "__main__":
main(sys.argv[1:])
@@ -0,0 +1,92 @@
from __future__ import division
import cv2 as cv
import numpy as np
# Snippet code for Operations with images tutorial (not intended to be run)
def load():
# Input/Output
filename = 'img.jpg'
## [Load an image from a file]
img = cv.imread(filename)
## [Load an image from a file]
## [Load an image from a file in grayscale]
img = cv.imread(filename, cv.IMREAD_GRAYSCALE)
## [Load an image from a file in grayscale]
## [Save image]
cv.imwrite(filename, img)
## [Save image]
def access_pixel():
# Accessing pixel intensity values
img = np.empty((4,4,3), np.uint8)
y = 0
x = 0
## [Pixel access 1]
_intensity = img[y,x]
## [Pixel access 1]
## [Pixel access 3]
_blue = img[y,x,0]
_green = img[y,x,1]
_red = img[y,x,2]
## [Pixel access 3]
## [Pixel access 5]
img[y,x] = 128
## [Pixel access 5]
def reference_counting():
# Memory management and reference counting
## [Reference counting 2]
img = cv.imread('image.jpg')
_img1 = np.copy(img)
## [Reference counting 2]
## [Reference counting 3]
img = cv.imread('image.jpg')
_sobelx = cv.Sobel(img, cv.CV_32F, 1, 0)
## [Reference counting 3]
def primitive_operations():
img = np.empty((4,4,3), np.uint8)
## [Set image to black]
img[:] = 0
## [Set image to black]
## [Select ROI]
_smallImg = img[10:110,10:110]
## [Select ROI]
## [BGR to Gray]
img = cv.imread('image.jpg')
_grey = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
## [BGR to Gray]
src = np.ones((4,4), np.uint8)
## [Convert to CV_32F]
_dst = src.astype(np.float32)
## [Convert to CV_32F]
def visualize_images():
## [imshow 1]
img = cv.imread('image.jpg')
cv.namedWindow('image', cv.WINDOW_AUTOSIZE)
cv.imshow('image', img)
cv.waitKey()
## [imshow 1]
## [imshow 2]
img = cv.imread('image.jpg')
grey = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
sobelx = cv.Sobel(grey, cv.CV_32F, 1, 0)
# find minimum and maximum intensities
minVal = np.amin(sobelx)
maxVal = np.amax(sobelx)
draw = cv.convertScaleAbs(sobelx, alpha=255.0/(maxVal - minVal), beta=-minVal * 255.0/(maxVal - minVal))
cv.namedWindow('image', cv.WINDOW_AUTOSIZE)
cv.imshow('image', draw)
cv.waitKey()
## [imshow 2]
@@ -0,0 +1,41 @@
import numpy as np
from ..accuracy_eval import SemSegmEvaluation
from ..utils import plot_acc
def test_segm_models(models_list, data_fetcher, eval_params, experiment_name, is_print_eval_params=True,
is_plot_acc=True):
if is_print_eval_params:
print(
"===== Running evaluation of the classification models with the following params:\n"
"\t0. val data location: {}\n"
"\t1. val data labels: {}\n"
"\t2. frame size: {}\n"
"\t3. batch size: {}\n"
"\t4. transform to RGB: {}\n"
"\t5. log file location: {}\n".format(
eval_params.imgs_segm_dir,
eval_params.img_cls_file,
eval_params.frame_size,
eval_params.batch_size,
eval_params.bgr_to_rgb,
eval_params.log
)
)
accuracy_evaluator = SemSegmEvaluation(eval_params.log, eval_params.img_cls_file, eval_params.batch_size)
accuracy_evaluator.process(models_list, data_fetcher)
accuracy_array = np.array(accuracy_evaluator.general_fw_accuracy)
print(
"===== End of processing. Accuracy results:\n"
"\t1. max accuracy (top-5) for the original model: {}\n"
"\t2. max accuracy (top-5) for the DNN model: {}\n".format(
max(accuracy_array[:, 0]),
max(accuracy_array[:, 1]),
)
)
if is_plot_acc:
plot_acc(accuracy_array, experiment_name)
@@ -0,0 +1,59 @@
from torchvision import models
from ..pytorch_model import (
PyTorchModelPreparer,
PyTorchModelProcessor,
PyTorchDnnModelProcessor
)
from ...common.utils import set_pytorch_env, create_parser
class PyTorchFcnResNet50(PyTorchModelPreparer):
def __init__(self, model_name, original_model):
super(PyTorchFcnResNet50, self).__init__(model_name, original_model)
def main():
parser = create_parser()
cmd_args = parser.parse_args()
set_pytorch_env()
# Test the base process of model retrieval
resnets = PyTorchFcnResNet50(
model_name="resnet50",
original_model=models.segmentation.fcn_resnet50(pretrained=True)
)
model_dict = resnets.get_prepared_models()
if cmd_args.is_evaluate:
from ...common.test_config import TestConfig
from ...common.accuracy_eval import PASCALDataFetch
from ...common.test.voc_segm_test import test_segm_models
eval_params = TestConfig()
model_names = list(model_dict.keys())
original_model_name = model_names[0]
dnn_model_name = model_names[1]
#img_dir, segm_dir, names_file, segm_cls_colors_file, preproc)
data_fetcher = PASCALDataFetch(
imgs_dir=eval_params.imgs_segm_dir,
frame_size=eval_params.frame_size,
bgr_to_rgb=eval_params.bgr_to_rgb,
)
test_segm_models(
[
PyTorchModelProcessor(model_dict[original_model_name], original_model_name),
PyTorchDnnModelProcessor(model_dict[dnn_model_name], dnn_model_name)
],
data_fetcher,
eval_params,
original_model_name
)
if __name__ == "__main__":
main()
@@ -0,0 +1,71 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
def basicPanoramaStitching(img1Path, img2Path):
img1 = cv.imread(cv.samples.findFile(img1Path))
img2 = cv.imread(cv.samples.findFile(img2Path))
# [camera-pose-from-Blender-at-location-1]
c1Mo = np.array([[0.9659258723258972, 0.2588190734386444, 0.0, 1.5529145002365112],
[ 0.08852133899927139, -0.3303661346435547, -0.9396926164627075, -0.10281121730804443],
[-0.24321036040782928, 0.9076734185218811, -0.342020183801651, 6.130080699920654],
[0, 0, 0, 1]],dtype=np.float64)
# [camera-pose-from-Blender-at-location-1]
# [camera-pose-from-Blender-at-location-2]
c2Mo = np.array([[0.9659258723258972, -0.2588190734386444, 0.0, -1.5529145002365112],
[-0.08852133899927139, -0.3303661346435547, -0.9396926164627075, -0.10281121730804443],
[0.24321036040782928, 0.9076734185218811, -0.342020183801651, 6.130080699920654],
[0, 0, 0, 1]],dtype=np.float64)
# [camera-pose-from-Blender-at-location-2]
# [camera-intrinsics-from-Blender]
cameraMatrix = np.array([[700.0, 0.0, 320.0], [0.0, 700.0, 240.0], [0, 0, 1]], dtype=np.float32)
# [camera-intrinsics-from-Blender]
# [extract-rotation]
R1 = c1Mo[0:3, 0:3]
R2 = c2Mo[0:3, 0:3]
#[extract-rotation]
# [compute-rotation-displacement]
R2 = R2.transpose()
R_2to1 = np.dot(R1,R2)
# [compute-rotation-displacement]
# [compute-homography]
H = cameraMatrix.dot(R_2to1).dot(np.linalg.inv(cameraMatrix))
H = H / H[2][2]
# [compute-homography]
# [stitch]
img_stitch = cv.warpPerspective(img2, H, (img2.shape[1]*2, img2.shape[0]))
img_stitch[0:img1.shape[0], 0:img1.shape[1]] = img1
# [stitch]
img_space = np.zeros((img1.shape[0],50,3), dtype=np.uint8)
img_compare = cv.hconcat([img1,img_space, img2])
cv.imshow("Final", img_compare)
cv.imshow("Panorama", img_stitch)
cv.waitKey(0)
def main():
import argparse
parser = argparse.ArgumentParser(description="Code for homography tutorial. Example 5: basic panorama stitching from a rotating camera.")
parser.add_argument("-I1","--image1", help = "path to first image", default="Blender_Suzanne1.jpg")
parser.add_argument("-I2","--image2", help = "path to second image", default="Blender_Suzanne2.jpg")
args = parser.parse_args()
print("Panorama Stitching Started")
basicPanoramaStitching(args.image1, args.image2)
print("Panorama Stitching Completed Successfully")
if __name__ == '__main__':
main()
@@ -0,0 +1,74 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
import sys
def randomColor():
color = np.random.randint(0, 255,(1, 3))
return color[0].tolist()
def perspectiveCorrection(img1Path, img2Path ,patternSize ):
img1 = cv.imread(cv.samples.findFile(img1Path))
img2 = cv.imread(cv.samples.findFile(img2Path))
# [find-corners]
ret1, corners1 = cv.findChessboardCorners(img1, patternSize)
ret2, corners2 = cv.findChessboardCorners(img2, patternSize)
# [find-corners]
if not ret1 or not ret2:
print("Error, cannot find the chessboard corners in both images.")
sys.exit(-1)
# [estimate-homography]
H, _ = cv.findHomography(corners1, corners2)
print(H)
# [estimate-homography]
# [warp-chessboard]
img1_warp = cv.warpPerspective(img1, H, (img1.shape[1], img1.shape[0]))
# [warp-chessboard]
img_draw_warp = cv.hconcat([img2, img1_warp])
cv.imshow("Desired chessboard view / Warped source chessboard view", img_draw_warp )
corners1 = corners1.tolist()
corners1 = [a[0] for a in corners1]
# [compute-transformed-corners]
img_draw_matches = cv.hconcat([img1, img2])
for i in range(len(corners1)):
pt1 = np.array([corners1[i][0], corners1[i][1], 1])
pt1 = pt1.reshape(3, 1)
pt2 = np.dot(H, pt1)
pt2 = pt2/pt2[2]
end = (int(img1.shape[1] + pt2[0]), int(pt2[1]))
cv.line(img_draw_matches, tuple([int(j) for j in corners1[i]]), end, randomColor(), 2)
cv.imshow("Draw matches", img_draw_matches)
cv.waitKey(0)
# [compute-transformed-corners]
def main():
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-I1', "--image1", help="Path to the first image", default="left02.jpg")
parser.add_argument('-I2', "--image2", help="Path to the second image", default="left01.jpg")
parser.add_argument('-H', "--height", help="Height of pattern size", default=6)
parser.add_argument('-W', "--width", help="Width of pattern size", default=9)
args = parser.parse_args()
img1Path = args.image1
img2Path = args.image2
h = args.height
w = args.width
perspectiveCorrection(img1Path, img2Path, (w, h))
if __name__ == "__main__":
main()
@@ -0,0 +1,81 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
from math import sqrt
## [load]
parser = argparse.ArgumentParser(description='Code for AKAZE local features matching tutorial.')
parser.add_argument('--input1', help='Path to input image 1.', default='graf1.png')
parser.add_argument('--input2', help='Path to input image 2.', default='graf3.png')
parser.add_argument('--homography', help='Path to the homography matrix.', default='H1to3p.xml')
args = parser.parse_args()
img1 = cv.imread(cv.samples.findFile(args.input1), cv.IMREAD_GRAYSCALE)
img2 = cv.imread(cv.samples.findFile(args.input2), cv.IMREAD_GRAYSCALE)
if img1 is None or img2 is None:
print('Could not open or find the images!')
exit(0)
fs = cv.FileStorage(cv.samples.findFile(args.homography), cv.FILE_STORAGE_READ)
homography = fs.getFirstTopLevelNode().mat()
## [load]
## [AKAZE]
akaze = cv.xfeatures2d.AKAZE_create()
kpts1, desc1 = akaze.detectAndCompute(img1, None)
kpts2, desc2 = akaze.detectAndCompute(img2, None)
## [AKAZE]
## [2-nn matching]
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE_HAMMING)
nn_matches = matcher.knnMatch(desc1, desc2, 2)
## [2-nn matching]
## [ratio test filtering]
matched1 = []
matched2 = []
nn_match_ratio = 0.8 # Nearest neighbor matching ratio
for m, n in nn_matches:
if m.distance < nn_match_ratio * n.distance:
matched1.append(kpts1[m.queryIdx])
matched2.append(kpts2[m.trainIdx])
## [ratio test filtering]
## [homography check]
inliers1 = []
inliers2 = []
good_matches = []
inlier_threshold = 2.5 # Distance threshold to identify inliers with homography check
for i, m in enumerate(matched1):
col = np.ones((3,1), dtype=np.float64)
col[0:2,0] = m.pt
col = np.dot(homography, col)
col /= col[2,0]
dist = sqrt(pow(col[0,0] - matched2[i].pt[0], 2) +\
pow(col[1,0] - matched2[i].pt[1], 2))
if dist < inlier_threshold:
good_matches.append(cv.DMatch(len(inliers1), len(inliers2), 0))
inliers1.append(matched1[i])
inliers2.append(matched2[i])
## [homography check]
## [draw final matches]
res = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8)
cv.drawMatches(img1, inliers1, img2, inliers2, good_matches, res)
cv.imwrite("akaze_result.png", res)
inlier_ratio = len(inliers1) / float(len(matched1))
print('A-KAZE Matching Results')
print('*******************************')
print('# Keypoints 1: \t', len(kpts1))
print('# Keypoints 2: \t', len(kpts2))
print('# Matches: \t', len(matched1))
print('# Inliers: \t', len(inliers1))
print('# Inliers Ratio: \t', inlier_ratio)
cv.imshow('result', res)
cv.waitKey()
## [draw final matches]
@@ -0,0 +1,35 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
parser = argparse.ArgumentParser(description='Code for Feature Detection tutorial.')
parser.add_argument('--input1', help='Path to input image 1.', default='box.png')
parser.add_argument('--input2', help='Path to input image 2.', default='box_in_scene.png')
args = parser.parse_args()
img1 = cv.imread(cv.samples.findFile(args.input1), cv.IMREAD_GRAYSCALE)
img2 = cv.imread(cv.samples.findFile(args.input2), cv.IMREAD_GRAYSCALE)
if img1 is None or img2 is None:
print('Could not open or find the images!')
exit(0)
#-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors
minHessian = 400
detector = cv.xfeatures2d_SURF.create(hessianThreshold=minHessian)
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
#-- Step 2: Matching descriptor vectors with a brute force matcher
# Since SURF is a floating-point descriptor NORM_L2 is used
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
matches = matcher.match(descriptors1, descriptors2)
#-- Draw matches
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8)
cv.drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches)
#-- Show detected matches
cv.imshow('Matches', img_matches)
cv.waitKey()
@@ -0,0 +1,27 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
parser = argparse.ArgumentParser(description='Code for Feature Detection tutorial.')
parser.add_argument('--input', help='Path to input image.', default='box.png')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input), cv.IMREAD_GRAYSCALE)
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
#-- Step 1: Detect the keypoints using SURF Detector
minHessian = 400
detector = cv.xfeatures2d_SURF.create(hessianThreshold=minHessian)
keypoints = detector.detect(src)
#-- Draw keypoints
img_keypoints = np.empty((src.shape[0], src.shape[1], 3), dtype=np.uint8)
cv.drawKeypoints(src, keypoints, img_keypoints)
#-- Show detected (drawn) keypoints
cv.imshow('SURF Keypoints', img_keypoints)
cv.waitKey()
@@ -0,0 +1,42 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
parser = argparse.ArgumentParser(description='Code for Feature Matching with FLANN tutorial.')
parser.add_argument('--input1', help='Path to input image 1.', default='box.png')
parser.add_argument('--input2', help='Path to input image 2.', default='box_in_scene.png')
args = parser.parse_args()
img1 = cv.imread(cv.samples.findFile(args.input1), cv.IMREAD_GRAYSCALE)
img2 = cv.imread(cv.samples.findFile(args.input2), cv.IMREAD_GRAYSCALE)
if img1 is None or img2 is None:
print('Could not open or find the images!')
exit(0)
#-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors
minHessian = 400
detector = cv.xfeatures2d_SURF.create(hessianThreshold=minHessian)
keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
#-- Step 2: Matching descriptor vectors with a FLANN based matcher
# Since SURF is a floating-point descriptor NORM_L2 is used
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_FLANNBASED)
knn_matches = matcher.knnMatch(descriptors1, descriptors2, 2)
#-- Filter matches using the Lowe's ratio test
ratio_thresh = 0.7
good_matches = []
for m,n in knn_matches:
if m.distance < ratio_thresh * n.distance:
good_matches.append(m)
#-- Draw matches
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8)
cv.drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
#-- Show detected matches
cv.imshow('Good Matches', img_matches)
cv.waitKey()
@@ -0,0 +1,77 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
parser = argparse.ArgumentParser(description='Code for Feature Matching with FLANN tutorial.')
parser.add_argument('--input1', help='Path to input image 1.', default='box.png')
parser.add_argument('--input2', help='Path to input image 2.', default='box_in_scene.png')
args = parser.parse_args()
img_object = cv.imread(cv.samples.findFile(args.input1), cv.IMREAD_GRAYSCALE)
img_scene = cv.imread(cv.samples.findFile(args.input2), cv.IMREAD_GRAYSCALE)
if img_object is None or img_scene is None:
print('Could not open or find the images!')
exit(0)
#-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors
minHessian = 400
detector = cv.xfeatures2d_SURF.create(hessianThreshold=minHessian)
keypoints_obj, descriptors_obj = detector.detectAndCompute(img_object, None)
keypoints_scene, descriptors_scene = detector.detectAndCompute(img_scene, None)
#-- Step 2: Matching descriptor vectors with a FLANN based matcher
# Since SURF is a floating-point descriptor NORM_L2 is used
matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_FLANNBASED)
knn_matches = matcher.knnMatch(descriptors_obj, descriptors_scene, 2)
#-- Filter matches using the Lowe's ratio test
ratio_thresh = 0.75
good_matches = []
for m,n in knn_matches:
if m.distance < ratio_thresh * n.distance:
good_matches.append(m)
#-- Draw matches
img_matches = np.empty((max(img_object.shape[0], img_scene.shape[0]), img_object.shape[1]+img_scene.shape[1], 3), dtype=np.uint8)
cv.drawMatches(img_object, keypoints_obj, img_scene, keypoints_scene, good_matches, img_matches, flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
#-- Localize the object
obj = np.empty((len(good_matches),2), dtype=np.float32)
scene = np.empty((len(good_matches),2), dtype=np.float32)
for i in range(len(good_matches)):
#-- Get the keypoints from the good matches
obj[i,0] = keypoints_obj[good_matches[i].queryIdx].pt[0]
obj[i,1] = keypoints_obj[good_matches[i].queryIdx].pt[1]
scene[i,0] = keypoints_scene[good_matches[i].trainIdx].pt[0]
scene[i,1] = keypoints_scene[good_matches[i].trainIdx].pt[1]
H, _ = cv.findHomography(obj, scene, cv.RANSAC)
#-- Get the corners from the image_1 ( the object to be "detected" )
obj_corners = np.empty((4,1,2), dtype=np.float32)
obj_corners[0,0,0] = 0
obj_corners[0,0,1] = 0
obj_corners[1,0,0] = img_object.shape[1]
obj_corners[1,0,1] = 0
obj_corners[2,0,0] = img_object.shape[1]
obj_corners[2,0,1] = img_object.shape[0]
obj_corners[3,0,0] = 0
obj_corners[3,0,1] = img_object.shape[0]
scene_corners = cv.perspectiveTransform(obj_corners, H)
#-- Draw lines between the corners (the mapped object in the scene - image_2 )
cv.line(img_matches, (int(scene_corners[0,0,0] + img_object.shape[1]), int(scene_corners[0,0,1])),\
(int(scene_corners[1,0,0] + img_object.shape[1]), int(scene_corners[1,0,1])), (0,255,0), 4)
cv.line(img_matches, (int(scene_corners[1,0,0] + img_object.shape[1]), int(scene_corners[1,0,1])),\
(int(scene_corners[2,0,0] + img_object.shape[1]), int(scene_corners[2,0,1])), (0,255,0), 4)
cv.line(img_matches, (int(scene_corners[2,0,0] + img_object.shape[1]), int(scene_corners[2,0,1])),\
(int(scene_corners[3,0,0] + img_object.shape[1]), int(scene_corners[3,0,1])), (0,255,0), 4)
cv.line(img_matches, (int(scene_corners[3,0,0] + img_object.shape[1]), int(scene_corners[3,0,1])),\
(int(scene_corners[0,0,0] + img_object.shape[1]), int(scene_corners[0,0,1])), (0,255,0), 4)
#-- Show detected matches
cv.imshow('Good Matches & Object detection', img_matches)
cv.waitKey()
@@ -0,0 +1,48 @@
from __future__ import print_function
from __future__ import division
import cv2 as cv
import argparse
alpha_slider_max = 100
title_window = 'Linear Blend'
## [on_trackbar]
def on_trackbar(val):
alpha = val / alpha_slider_max
beta = ( 1.0 - alpha )
dst = cv.addWeighted(src1, alpha, src2, beta, 0.0)
cv.imshow(title_window, dst)
## [on_trackbar]
parser = argparse.ArgumentParser(description='Code for Adding a Trackbar to our applications tutorial.')
parser.add_argument('--input1', help='Path to the first input image.', default='LinuxLogo.jpg')
parser.add_argument('--input2', help='Path to the second input image.', default='WindowsLogo.jpg')
args = parser.parse_args()
## [load]
# Read images ( both have to be of the same size and type )
src1 = cv.imread(cv.samples.findFile(args.input1))
src2 = cv.imread(cv.samples.findFile(args.input2))
## [load]
if src1 is None:
print('Could not open or find the image: ', args.input1)
exit(0)
if src2 is None:
print('Could not open or find the image: ', args.input2)
exit(0)
## [window]
cv.namedWindow(title_window)
## [window]
## [create_trackbar]
trackbar_name = 'Alpha x %d' % alpha_slider_max
cv.createTrackbar(trackbar_name, title_window , 0, alpha_slider_max, on_trackbar)
## [create_trackbar]
# Show some stuff
on_trackbar(0)
# Wait until user press some key
cv.waitKey()
@@ -0,0 +1,115 @@
import cv2 as cv
import numpy as np
W = 400
## [my_ellipse]
def my_ellipse(img, angle):
thickness = 2
line_type = 8
cv.ellipse(img,
(W // 2, W // 2),
(W // 4, W // 16),
angle,
0,
360,
(255, 0, 0),
thickness,
line_type)
## [my_ellipse]
## [my_filled_circle]
def my_filled_circle(img, center):
thickness = -1
line_type = 8
cv.circle(img,
center,
W // 32,
(0, 0, 255),
thickness,
line_type)
## [my_filled_circle]
## [my_polygon]
def my_polygon(img):
line_type = 8
# Create some points
ppt = np.array([[W / 4, 7 * W / 8], [3 * W / 4, 7 * W / 8],
[3 * W / 4, 13 * W / 16], [11 * W / 16, 13 * W / 16],
[19 * W / 32, 3 * W / 8], [3 * W / 4, 3 * W / 8],
[3 * W / 4, W / 8], [26 * W / 40, W / 8],
[26 * W / 40, W / 4], [22 * W / 40, W / 4],
[22 * W / 40, W / 8], [18 * W / 40, W / 8],
[18 * W / 40, W / 4], [14 * W / 40, W / 4],
[14 * W / 40, W / 8], [W / 4, W / 8],
[W / 4, 3 * W / 8], [13 * W / 32, 3 * W / 8],
[5 * W / 16, 13 * W / 16], [W / 4, 13 * W / 16]], np.int32)
ppt = ppt.reshape((-1, 1, 2))
cv.fillPoly(img, [ppt], (255, 255, 255), line_type)
# Only drawind the lines would be:
# cv.polylines(img, [ppt], True, (255, 0, 255), line_type)
## [my_polygon]
## [my_line]
def my_line(img, start, end):
thickness = 2
line_type = 8
cv.line(img,
start,
end,
(0, 0, 0),
thickness,
line_type)
## [my_line]
## [create_images]
# Windows names
atom_window = "Drawing 1: Atom"
rook_window = "Drawing 2: Rook"
# Create black empty images
size = W, W, 3
atom_image = np.zeros(size, dtype=np.uint8)
rook_image = np.zeros(size, dtype=np.uint8)
## [create_images]
## [draw_atom]
# 1. Draw a simple atom:
# -----------------------
# 1.a. Creating ellipses
my_ellipse(atom_image, 90)
my_ellipse(atom_image, 0)
my_ellipse(atom_image, 45)
my_ellipse(atom_image, -45)
# 1.b. Creating circles
my_filled_circle(atom_image, (W // 2, W // 2))
## [draw_atom]
## [draw_rook]
# 2. Draw a rook
# ------------------
# 2.a. Create a convex polygon
my_polygon(rook_image)
## [rectangle]
# 2.b. Creating rectangles
cv.rectangle(rook_image,
(0, 7 * W // 8),
(W, W),
(0, 255, 255),
-1,
8)
## [rectangle]
# 2.c. Create a few lines
my_line(rook_image, (0, 15 * W // 16), (W, 15 * W // 16))
my_line(rook_image, (W // 4, 7 * W // 8), (W // 4, W))
my_line(rook_image, (W // 2, 7 * W // 8), (W // 2, W))
my_line(rook_image, (3 * W // 4, 7 * W // 8), (3 * W // 4, W))
## [draw_rook]
cv.imshow(atom_window, atom_image)
cv.moveWindow(atom_window, 0, 200)
cv.imshow(rook_window, rook_image)
cv.moveWindow(rook_window, W, 200)
cv.waitKey(0)
cv.destroyAllWindows()
@@ -0,0 +1,38 @@
import cv2 as cv
import numpy as np
input_image = np.array((
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 255, 255, 255, 0, 0, 0, 255],
[0, 255, 255, 255, 0, 0, 0, 0],
[0, 255, 255, 255, 0, 255, 0, 0],
[0, 0, 255, 0, 0, 0, 0, 0],
[0, 0, 255, 0, 0, 255, 255, 0],
[0,255, 0, 255, 0, 0, 255, 0],
[0, 255, 255, 255, 0, 0, 0, 0]), dtype="uint8")
kernel = np.array((
[0, 1, 0],
[1, -1, 1],
[0, 1, 0]), dtype="int")
output_image = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel)
rate = 50
kernel = (kernel + 1) * 127
kernel = np.uint8(kernel)
kernel = cv.resize(kernel, None, fx = rate, fy = rate, interpolation = cv.INTER_NEAREST)
cv.imshow("kernel", kernel)
cv.moveWindow("kernel", 0, 0)
input_image = cv.resize(input_image, None, fx = rate, fy = rate, interpolation = cv.INTER_NEAREST)
cv.imshow("Original", input_image)
cv.moveWindow("Original", 0, 200)
output_image = cv.resize(output_image, None , fx = rate, fy = rate, interpolation = cv.INTER_NEAREST)
cv.imshow("Hit or Miss", output_image)
cv.moveWindow("Hit or Miss", 500, 200)
cv.waitKey(0)
cv.destroyAllWindows()
@@ -0,0 +1,51 @@
import sys
import cv2 as cv
def main(argv):
print("""
Zoom In-Out demo
------------------
* [i] -> Zoom [i]n
* [o] -> Zoom [o]ut
* [ESC] -> Close program
""")
## [load]
filename = argv[0] if len(argv) > 0 else 'chicky_512.png'
# Load the image
src = cv.imread(cv.samples.findFile(filename))
# Check if image is loaded fine
if src is None:
print ('Error opening image!')
print ('Usage: pyramids.py [image_name -- default ../data/chicky_512.png] \n')
return -1
## [load]
## [loop]
while 1:
rows, cols, _channels = map(int, src.shape)
## [show_image]
cv.imshow('Pyramids Demo', src)
## [show_image]
k = cv.waitKey(0)
if k == 27:
break
## [pyrup]
elif chr(k) == 'i':
src = cv.pyrUp(src, dstsize=(2 * cols, 2 * rows))
print ('** Zoom In: Image x 2')
## [pyrup]
## [pyrdown]
elif chr(k) == 'o':
src = cv.pyrDown(src, dstsize=(cols // 2, rows // 2))
print ('** Zoom Out: Image / 2')
## [pyrdown]
## [loop]
cv.destroyAllWindows()
return 0
if __name__ == "__main__":
main(sys.argv[1:])
@@ -0,0 +1,107 @@
import sys
import cv2 as cv
import numpy as np
# Global Variables
DELAY_CAPTION = 1500
DELAY_BLUR = 100
MAX_KERNEL_LENGTH = 31
src = None
dst = None
window_name = 'Smoothing Demo'
def main(argv):
cv.namedWindow(window_name, cv.WINDOW_AUTOSIZE)
# Load the source image
imageName = argv[0] if len(argv) > 0 else 'lena.jpg'
global src
src = cv.imread(cv.samples.findFile(imageName))
if src is None:
print ('Error opening image')
print ('Usage: smoothing.py [image_name -- default ../data/lena.jpg] \n')
return -1
if display_caption('Original Image') != 0:
return 0
global dst
dst = np.copy(src)
if display_dst(DELAY_CAPTION) != 0:
return 0
# Applying Homogeneous blur
if display_caption('Homogeneous Blur') != 0:
return 0
## [blur]
for i in range(1, MAX_KERNEL_LENGTH, 2):
dst = cv.blur(src, (i, i))
if display_dst(DELAY_BLUR) != 0:
return 0
## [blur]
# Applying Gaussian blur
if display_caption('Gaussian Blur') != 0:
return 0
## [gaussianblur]
for i in range(1, MAX_KERNEL_LENGTH, 2):
dst = cv.GaussianBlur(src, (i, i), 0)
if display_dst(DELAY_BLUR) != 0:
return 0
## [gaussianblur]
# Applying Median blur
if display_caption('Median Blur') != 0:
return 0
## [medianblur]
for i in range(1, MAX_KERNEL_LENGTH, 2):
dst = cv.medianBlur(src, i)
if display_dst(DELAY_BLUR) != 0:
return 0
## [medianblur]
# Applying Bilateral Filter
if display_caption('Bilateral Blur') != 0:
return 0
## [bilateralfilter]
# Remember, bilateral is a bit slow, so as value go higher, it takes long time
for i in range(1, MAX_KERNEL_LENGTH, 2):
dst = cv.bilateralFilter(src, i, i * 2, i / 2)
if display_dst(DELAY_BLUR) != 0:
return 0
## [bilateralfilter]
# Done
display_caption('Done!')
return 0
def display_caption(caption):
global dst
dst = np.zeros(src.shape, src.dtype)
rows, cols, _ch = src.shape
cv.putText(dst, caption,
(int(cols / 4), int(rows / 2)),
cv.FONT_HERSHEY_COMPLEX, 1, (255, 255, 255))
return display_dst(DELAY_CAPTION)
def display_dst(delay):
cv.imshow(window_name, dst)
c = cv.waitKey(delay)
if c >= 0 : return -1
return 0
if __name__ == "__main__":
main(sys.argv[1:])
@@ -0,0 +1,92 @@
import cv2 as cv
import numpy as np
import argparse
W = 52 # window size is WxW
C_Thr = 0.43 # threshold for coherency
LowThr = 35 # threshold1 for orientation, it ranges from 0 to 180
HighThr = 57 # threshold2 for orientation, it ranges from 0 to 180
## [calcGST]
## [calcJ_header]
## [calcGST_proto]
def calcGST(inputIMG, w):
## [calcGST_proto]
img = inputIMG.astype(np.float32)
# GST components calculation (start)
# J = (J11 J12; J12 J22) - GST
imgDiffX = cv.Sobel(img, cv.CV_32F, 1, 0, 3)
imgDiffY = cv.Sobel(img, cv.CV_32F, 0, 1, 3)
imgDiffXY = cv.multiply(imgDiffX, imgDiffY)
## [calcJ_header]
imgDiffXX = cv.multiply(imgDiffX, imgDiffX)
imgDiffYY = cv.multiply(imgDiffY, imgDiffY)
J11 = cv.boxFilter(imgDiffXX, cv.CV_32F, (w,w))
J22 = cv.boxFilter(imgDiffYY, cv.CV_32F, (w,w))
J12 = cv.boxFilter(imgDiffXY, cv.CV_32F, (w,w))
# GST components calculations (stop)
# eigenvalue calculation (start)
# lambda1 = 0.5*(J11 + J22 + sqrt((J11-J22)^2 + 4*J12^2))
# lambda2 = 0.5*(J11 + J22 - sqrt((J11-J22)^2 + 4*J12^2))
tmp1 = J11 + J22
tmp2 = J11 - J22
tmp2 = cv.multiply(tmp2, tmp2)
tmp3 = cv.multiply(J12, J12)
tmp4 = np.sqrt(tmp2 + 4.0 * tmp3)
lambda1 = 0.5*(tmp1 + tmp4) # biggest eigenvalue
lambda2 = 0.5*(tmp1 - tmp4) # smallest eigenvalue
# eigenvalue calculation (stop)
# Coherency calculation (start)
# Coherency = (lambda1 - lambda2)/(lambda1 + lambda2)) - measure of anisotropism
# Coherency is anisotropy degree (consistency of local orientation)
imgCoherencyOut = cv.divide(lambda1 - lambda2, lambda1 + lambda2)
# Coherency calculation (stop)
# orientation angle calculation (start)
# tan(2*Alpha) = 2*J12/(J22 - J11)
# Alpha = 0.5 atan2(2*J12/(J22 - J11))
imgOrientationOut = cv.phase(J22 - J11, 2.0 * J12, angleInDegrees = True)
imgOrientationOut = 0.5 * imgOrientationOut
# orientation angle calculation (stop)
return imgCoherencyOut, imgOrientationOut
## [calcGST]
parser = argparse.ArgumentParser(description='Code for Anisotropic image segmentation tutorial.')
parser.add_argument('-i', '--input', help='Path to input image.', required=True)
args = parser.parse_args()
imgIn = cv.imread(args.input, cv.IMREAD_GRAYSCALE)
if imgIn is None:
print('Could not open or find the image: {}'.format(args.input))
exit(0)
## [main_extra]
## [main]
imgCoherency, imgOrientation = calcGST(imgIn, W)
## [thresholding]
_, imgCoherencyBin = cv.threshold(imgCoherency, C_Thr, 255, cv.THRESH_BINARY)
_, imgOrientationBin = cv.threshold(imgOrientation, LowThr, HighThr, cv.THRESH_BINARY)
## [thresholding]
## [combining]
imgBin = cv.bitwise_and(imgCoherencyBin, imgOrientationBin)
## [combining]
## [main]
imgCoherency = cv.normalize(imgCoherency, None, alpha=0, beta=1, norm_type=cv.NORM_MINMAX, dtype=cv.CV_32F)
imgOrientation = cv.normalize(imgOrientation, None, alpha=0, beta=1, norm_type=cv.NORM_MINMAX, dtype=cv.CV_32F)
cv.imshow('result.jpg', np.uint8(0.5*(imgIn + imgBin)))
cv.imshow('Coherency.jpg', imgCoherency)
cv.imshow('Orientation.jpg', imgOrientation)
cv.waitKey(0)
## [main_extra]
@@ -0,0 +1,55 @@
from __future__ import print_function
from builtins import input
import cv2 as cv
import numpy as np
import argparse
# Read image given by user
## [basic-linear-transform-load]
parser = argparse.ArgumentParser(description='Code for Changing the contrast and brightness of an image! tutorial.')
parser.add_argument('--input', help='Path to input image.', default='lena.jpg')
args = parser.parse_args()
image = cv.imread(cv.samples.findFile(args.input))
if image is None:
print('Could not open or find the image: ', args.input)
exit(0)
## [basic-linear-transform-load]
## [basic-linear-transform-output]
new_image = np.zeros(image.shape, image.dtype)
## [basic-linear-transform-output]
## [basic-linear-transform-parameters]
alpha = 1.0 # Simple contrast control
beta = 0 # Simple brightness control
# Initialize values
print(' Basic Linear Transforms ')
print('-------------------------')
try:
alpha = float(input('* Enter the alpha value [1.0-3.0]: '))
beta = int(input('* Enter the beta value [0-100]: '))
except ValueError:
print('Error, not a number')
## [basic-linear-transform-parameters]
# Do the operation new_image(i,j) = alpha*image(i,j) + beta
# Instead of these 'for' loops we could have used simply:
# new_image = cv.convertScaleAbs(image, alpha=alpha, beta=beta)
# but we wanted to show you how to access the pixels :)
## [basic-linear-transform-operation]
for y in range(image.shape[0]):
for x in range(image.shape[1]):
for c in range(image.shape[2]):
new_image[y,x,c] = np.clip(alpha*image[y,x,c] + beta, 0, 255)
## [basic-linear-transform-operation]
## [basic-linear-transform-display]
# Show stuff
cv.imshow('Original Image', image)
cv.imshow('New Image', new_image)
# Wait until user press some key
cv.waitKey()
## [basic-linear-transform-display]
@@ -0,0 +1,74 @@
from __future__ import print_function
from __future__ import division
import cv2 as cv
import numpy as np
import argparse
alpha = 1.0
alpha_max = 500
beta = 0
beta_max = 200
gamma = 1.0
gamma_max = 200
def basicLinearTransform():
res = cv.convertScaleAbs(img_original, alpha=alpha, beta=beta)
img_corrected = cv.hconcat([img_original, res])
cv.imshow("Brightness and contrast adjustments", img_corrected)
def gammaCorrection():
## [changing-contrast-brightness-gamma-correction]
lookUpTable = np.empty((1,256), np.uint8)
for i in range(256):
lookUpTable[0,i] = np.clip(pow(i / 255.0, gamma) * 255.0, 0, 255)
res = cv.LUT(img_original, lookUpTable)
## [changing-contrast-brightness-gamma-correction]
img_gamma_corrected = cv.hconcat([img_original, res])
cv.imshow("Gamma correction", img_gamma_corrected)
def on_linear_transform_alpha_trackbar(val):
global alpha
alpha = val / 100
basicLinearTransform()
def on_linear_transform_beta_trackbar(val):
global beta
beta = val - 100
basicLinearTransform()
def on_gamma_correction_trackbar(val):
global gamma
gamma = val / 100
gammaCorrection()
parser = argparse.ArgumentParser(description='Code for Changing the contrast and brightness of an image! tutorial.')
parser.add_argument('--input', help='Path to input image.', default='lena.jpg')
args = parser.parse_args()
img_original = cv.imread(cv.samples.findFile(args.input))
if img_original is None:
print('Could not open or find the image: ', args.input)
exit(0)
img_corrected = np.empty((img_original.shape[0], img_original.shape[1]*2, img_original.shape[2]), img_original.dtype)
img_gamma_corrected = np.empty((img_original.shape[0], img_original.shape[1]*2, img_original.shape[2]), img_original.dtype)
img_corrected = cv.hconcat([img_original, img_original])
img_gamma_corrected = cv.hconcat([img_original, img_original])
cv.namedWindow('Brightness and contrast adjustments')
cv.namedWindow('Gamma correction')
alpha_init = int(alpha *100)
cv.createTrackbar('Alpha gain (contrast)', 'Brightness and contrast adjustments', alpha_init, alpha_max, on_linear_transform_alpha_trackbar)
beta_init = beta + 100
cv.createTrackbar('Beta bias (brightness)', 'Brightness and contrast adjustments', beta_init, beta_max, on_linear_transform_beta_trackbar)
gamma_init = int(gamma * 100)
cv.createTrackbar('Gamma correction', 'Gamma correction', gamma_init, gamma_max, on_gamma_correction_trackbar)
on_linear_transform_alpha_trackbar(alpha_init)
on_gamma_correction_trackbar(gamma_init)
cv.waitKey()
@@ -0,0 +1,80 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
src = None
erosion_size = 0
max_elem = 3
max_kernel_size = 21
title_trackbar_element_shape = 'Element:\n 0: Rect \n 1: Cross \n 2: Ellipse \n 3: Diamond'
title_trackbar_kernel_size = 'Kernel size:\n 2n +1'
title_erosion_window = 'Erosion Demo'
title_dilation_window = 'Dilation Demo'
## [main]
def main(image):
global src
src = cv.imread(cv.samples.findFile(image))
if src is None:
print('Could not open or find the image: ', image)
exit(0)
cv.namedWindow(title_erosion_window)
cv.createTrackbar(title_trackbar_element_shape, title_erosion_window, 0, max_elem, erosion)
cv.createTrackbar(title_trackbar_kernel_size, title_erosion_window, 0, max_kernel_size, erosion)
cv.namedWindow(title_dilation_window)
cv.createTrackbar(title_trackbar_element_shape, title_dilation_window, 0, max_elem, dilatation)
cv.createTrackbar(title_trackbar_kernel_size, title_dilation_window, 0, max_kernel_size, dilatation)
erosion(0)
dilatation(0)
cv.waitKey()
## [main]
# optional mapping of values with morphological shapes
def morph_shape(val):
if val == 0:
return cv.MORPH_RECT
elif val == 1:
return cv.MORPH_CROSS
elif val == 2:
return cv.MORPH_ELLIPSE
elif val == 3:
return cv.MORPH_DIAMOND
## [erosion]
def erosion(val):
erosion_size = cv.getTrackbarPos(title_trackbar_kernel_size, title_erosion_window)
erosion_shape = morph_shape(cv.getTrackbarPos(title_trackbar_element_shape, title_erosion_window))
## [kernel]
element = cv.getStructuringElement(erosion_shape, (2 * erosion_size + 1, 2 * erosion_size + 1),
(erosion_size, erosion_size))
## [kernel]
erosion_dst = cv.erode(src, element)
cv.imshow(title_erosion_window, erosion_dst)
## [erosion]
## [dilation]
def dilatation(val):
dilatation_size = cv.getTrackbarPos(title_trackbar_kernel_size, title_dilation_window)
dilation_shape = morph_shape(cv.getTrackbarPos(title_trackbar_element_shape, title_dilation_window))
element = cv.getStructuringElement(dilation_shape, (2 * dilatation_size + 1, 2 * dilatation_size + 1),
(dilatation_size, dilatation_size))
dilatation_dst = cv.dilate(src, element)
cv.imshow(title_dilation_window, dilatation_dst)
## [dilation]
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Code for Eroding and Dilating tutorial.')
parser.add_argument('--input', help='Path to input image.', default='LinuxLogo.jpg')
args = parser.parse_args()
main(args.input)
@@ -0,0 +1,22 @@
import cv2 as cv
import numpy as np
img = cv.imread(cv.samples.findFile('sudoku.png'))
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)
lines = cv.HoughLines(edges,1,np.pi/180,200)
for line in lines:
rho,theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 1000*(-b))
y1 = int(y0 + 1000*(a))
x2 = int(x0 - 1000*(-b))
y2 = int(y0 - 1000*(a))
cv.line(img,(x1,y1),(x2,y2),(0,0,255),2)
cv.imwrite('houghlines3.jpg',img)
@@ -0,0 +1,12 @@
import cv2 as cv
import numpy as np
img = cv.imread(cv.samples.findFile('sudoku.png'))
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)
lines = cv.HoughLinesP(edges,1,np.pi/180,100,minLineLength=100,maxLineGap=10)
for line in lines:
x1,y1,x2,y2 = line[0]
cv.line(img,(x1,y1),(x2,y2),(0,255,0),2)
cv.imwrite('houghlines5.jpg',img)
@@ -0,0 +1,97 @@
from __future__ import print_function
import sys
import cv2 as cv
## [global_variables]
use_mask = False
img = None
templ = None
mask = None
image_window = "Source Image"
result_window = "Result window"
match_method = 0
max_Trackbar = 5
## [global_variables]
def main(argv):
if (len(sys.argv) < 3):
print('Not enough parameters')
print('Usage:\nmatch_template_demo.py <image_name> <template_name> [<mask_name>]')
return -1
## [load_image]
global img
global templ
img = cv.imread(sys.argv[1], cv.IMREAD_COLOR)
templ = cv.imread(sys.argv[2], cv.IMREAD_COLOR)
if (len(sys.argv) > 3):
global use_mask
use_mask = True
global mask
mask = cv.imread( sys.argv[3], cv.IMREAD_COLOR )
if ((img is None) or (templ is None) or (use_mask and (mask is None))):
print('Can\'t read one of the images')
return -1
## [load_image]
## [create_windows]
cv.namedWindow( image_window, cv.WINDOW_AUTOSIZE )
cv.namedWindow( result_window, cv.WINDOW_AUTOSIZE )
## [create_windows]
## [create_trackbar]
trackbar_label = 'Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED'
cv.createTrackbar( trackbar_label, image_window, match_method, max_Trackbar, MatchingMethod )
## [create_trackbar]
MatchingMethod(match_method)
## [wait_key]
cv.waitKey(0)
return 0
## [wait_key]
def MatchingMethod(param):
global match_method
match_method = param
## [copy_source]
img_display = img.copy()
## [copy_source]
## [match_template]
method_accepts_mask = (cv.TM_SQDIFF == match_method or match_method == cv.TM_CCORR_NORMED)
if (use_mask and method_accepts_mask):
result = cv.matchTemplate(img, templ, match_method, None, mask)
else:
result = cv.matchTemplate(img, templ, match_method)
## [match_template]
## [normalize]
cv.normalize( result, result, 0, 1, cv.NORM_MINMAX, -1 )
## [normalize]
## [best_match]
_minVal, _maxVal, minLoc, maxLoc = cv.minMaxLoc(result, None)
## [best_match]
## [match_loc]
if (match_method == cv.TM_SQDIFF or match_method == cv.TM_SQDIFF_NORMED):
matchLoc = minLoc
else:
matchLoc = maxLoc
## [match_loc]
## [imshow]
cv.rectangle(img_display, matchLoc, (matchLoc[0] + templ.shape[1], matchLoc[1] + templ.shape[0]), (0,0,0), 2, 8, 0 )
cv.rectangle(result, matchLoc, (matchLoc[0] + templ.shape[1], matchLoc[1] + templ.shape[0]), (0,0,0), 2, 8, 0 )
cv.imshow(image_window, img_display)
cv.imshow(result_window, result)
## [imshow]
pass
if __name__ == "__main__":
main(sys.argv[1:])

Some files were not shown because too many files have changed in this diff Show More