Calculate the minimum and maximum in cvInRangeS - opencv

cvCvtColor(frame, hsv_frame, CV_BGR2HSV);
cvInRangeS(hsv_frame, hsv_min, hsv_max, thresholded);
I try to follow blue ball. To determine the maximum and minimum I open a picture I took with the camera, open it MS paint and doubles at (180/240) result out of me in H
And (255/240) the result of S and L
then i recive the next values:
108 113 115 112 105 H
145 40 107 129 143 S
97 129 96 102 124 L
So I chose the next values:
CvScalar hsv_min = cvScalar( 105, 40, 96 );
CvScalar hsv_max = cvScalar( 115, 140, 130);
But when I try to follow it hardly ever see him
Am I wrong calculation? or what can i do to improve the result?

First of all why do you convert your image to HSV and then talk about HSL? If I'm not mistaken they are different color spaces.
To determinate blue color using HSV color space use this range:
Min (H/S/V): 90, 50, 50
Max (H/S/V): 130, 255, 255
Also this online converter should help you.
And don't forget that Hue value after converting image to HSV using CV_BGR2HSV code is in range [0..180], while using CV_BGR2HSV_FULL will give you range [0..360].

Related

Overlaping raw thermal image and embedded image from FLIR

I have two images: a thermal image from FLIR e an embedded image which I extract from the metadata embedded in the thermal image. Example:
All metadata available in the thermal image are:
File Name: FLIR2721.jpg
File Size: 1000 kB
File Type: JPEG
File Type Extension: jpg
Mime Type: image/jpeg
Jfif Version: 1.01
Exif Byte Order: Little-endian (Intel, II)
Make: FLIR Systems AB
Model: FLIR T620
Orientation: Horizontal (normal)
X Resolution: 72
Y Resolution: 72
Resolution Unit: inches
Software: 4.8.2
Modify Date: 2017:11:29 08:34:08
Y Cb Cr Positioning: Centered
Exposure Time: 1/46
Exif Version: 220
Create Date: 2017:11:29 08:34:08
Components Configuration: -, Cr, Cb, Y
Subject Distance: 1 m
Focal Length: 41.3 mm
Image Temperature Max: 332
Image Temperature Min: 235
Flashpix Version: 100
Color Spaces: RGB
Exif Image Width: 640
Exif Image Height: 480
Digital Zoom Ratio: 1
Image Unique Id: DF9BB2EBB15922366AB9059A1D8D53A9
Gps Version Id: 2.2.0.0
Gps Altitude Ref: Above Sea Level
Gps Time Stamp: 11:48:03
Gps Satellites: 0
Gps Img Direction Ref: Magnetic North
Gps Img Direction: 160
Compression: JPEG (old-style)
Thumbnail Offset: 2172
Thumbnail Length: 5973
Emissivity: 0.75
Object Distance: 1.00 m
Reflected Apparent Temperature: 20.0 C
Atmospheric Temperature: 28.0 C
Ir Window Temperature: 20.0 C
Ir Window Transmission: 1
Relative Humidity: 60.0 %
Planck R: 115965.437
Planck B: 1417.1
Planck F: 1
Atmospheric Trans Alpha1: 0.006569
Atmospheric Trans Alpha2: 0.01262
Atmospheric Trans Beta1: -0.002276
Atmospheric Trans Beta2: -0.00667
Atmospheric Trans X: 1.9
Camera Temperature Range Max: 150.0 C
Camera Temperature Range Min: -40.0 C
Camera Temperature Max Clip: 160.0 C
Camera Temperature Min Clip: -60.0 C
Camera Temperature Max Warn: 150.0 C
Camera Temperature Min Warn: -40.0 C
Camera Temperature Max Saturated: 180.0 C
Camera Temperature Min Saturated: -60.0 C
Camera Model: FLIR T620
Camera Part Number: 55903-5022
Camera Serial Number: 55906523
Camera Software: 25.0.0
Lens Model: FOL41
Lens Part Number: T197524
Lens Serial Number: 56702775
Field Of View: 15.0 deg
Planck O: -3949
Planck R: 20.01401533
Raw Value Range Min: 5427
Raw Value Range Max: 56178
Raw Value Median: 13350
Raw Value Range: 10060
Date Time Original: 2017:11:29 08:34:08.131+00:00
Focus Step Count: 5925
Focus Distance: 8.9 m
Frame Rate: 30
Palette Colors: 224
Above Color: 170 128 128
Below Color: 50 128 128
Overflow Color: 67 216 98
Underflow Color: 41 110 240
Isotherm1 Color: 100 128 128
Isotherm2 Color: 100 110 240
Palette Method: 0
Palette Stretch: 2
Palette File Name: \FlashBFS\system\iron.pal
Palette Name: Iron
Palette: (Binary data 672 bytes)
Raw Thermal Image Width: 640
Raw Thermal Image Height: 480
Raw Thermal Image Type: PNG
Raw Thermal Image: (Binary data 362104 bytes)
Real2 Ir: 3.7806735038757
Offset X: -35
Offset Y: -131
Pi Px1: 160
Pi Px2: 479
Pi Py1: 120
Pi Py2: 359
Gps Valid: Yes
Gps Latitude Ref: South
Gps Longitude Ref: West
Gpsdop: 0.53
Gps Map Datum: WGS84
Embedded Image Width: 2592
Embedded Image Height: 1944
Embedded Image Type: JPG
Embedded Image: (Binary data 600954 bytes)
Image Width: 640
Image Height: 480
Encoding Process: Baseline DCT, Huffman coding
Bits Per Sample: 8
Color Components: 3
Y Cb Cr Sub Sampling: YCbCr4:2:0 (2 2)
Gps Altitude: 0 m Above Sea Level
Gps Latitude: 26 deg 18' 1.14" S
Gps Longitude: 48 deg 51' 2.82" W
Gps Position: 26 deg 18' 1.14" S, 48 deg 51' 2.82" W
Image Size: 640x480
Megapixels: 0.307
Peak Spectral Sensitivity: 10.2 um
Shutter Speed: 1/46
Thumbnail Image: (Binary data 5973 bytes)
Focal Length35Efl: 41.3 mm
Category: image
Raw Header: FF D8 FF E0 00 10 4A 46 49 46 00 01 01 00 00 01 00 01 00 00 FF E1 1F BC 45 78 69 66 00 00 49 49 2A 00 08 00 00 00 0B 00 0F 01 02 00 10 00 00 00 92 00 00 00 10 01 02 00 0A 00 00 00 A2 00 00 00
I want to "overlap" the thermal image in the embedded image but I don't know how to do this since the thermal image is not centered with the embedded image.
I've tried to use matchTemplate form OpenCV but the result is not quite good.
Any suggestions about how to solve it?
I think here is all data you need:
Raw Thermal Image Width: 640
Raw Thermal Image Height: 480
Raw Thermal Image Type: PNG
Raw Thermal Image: (Binary data 362104 bytes)
Real2 Ir: 3.7806735038757
Offset X: -35
Offset Y: -131
Real2 Ir value looks like zoom ratio of raw IR image to JPEG photo. 640x480*3.7806735038757=2420x1815 which is very close to 2592x1944. So you just need to test some combinations of what Pi Px/y coordinates and Offset X/Y means. Enlarge IR image (or reduce JPEG), center both images manually in graphics editor and check what X/Y distance between upper left corners of both images is. I think it will be same as some of these values.
I have found a solution but have no ideia of why it works.
Sample code:
import math
import cv2
emb_img = cv2.imread(<path_to_embedded_image>, cv2.IMREAD_COLOR)
emb_height, emb_width, emb_channels = emb_img.shape
emb_center = {
'x': math.floor(emb_width / 2),
'y': math.floor(emb_height / 2)
}
raw_img = cv2.imread(<path_to_raw_image>, cv2.IMREAD_GRAYSCALE)
raw_height, raw_width = raw_img.shape
raw_center = {
'x': math.floor(raw_width / 2),
'y': math.floor(raw_height / 2)
}
j = {
'OffsetX': <some number>,
'OffsetY': <some number>
}
x = emb_center.get('x') - raw_center.get('x') + j.get('OffsetX') - 45
y = emb_center.get('y') - raw_center.get('y') + j.get('OffsetY') - 45
cropped_img = emb_img[y:y+540, x:x+720, :]
cropped_img = cv2.resize(cropped_img, (640, 480))
cv2.imwrite('path_you_want.jpg', cropped_img)
I have no ideia why to write cropped_img = emb_img[y:y+540, x:x+720, :] instead of cropped_img = emb_img[y:y+480, x:x+680, :] since raw size is 680x540. Another thing, 45 came from where??? I just know it worked.
I've been playing with Photoshop and the embedded image, i believe this may work:
import cv2
import flirimageextractor
flir = flirimageextractor.FlirImageExtractor()
flir.process_image('C:\Temp\FLIR14107.jpg',RGB=True)
c = flir.get_metadata('C:\Temp\FLIR1234.jpg')
img = flir.extract_embedded_image()
Scale = c['Real2IR']
OffsetX = c['OffsetX']
OffsetY = c['OffsetY']
PiPX1 = c['PiPX1']
PiPX2 = c['PiPX2']
PiPY1 = c['PiPY1']
PiPY2 = c['PiPY2']
Width = c['EmbeddedImageWidth']
Height = c['EmbeddedImageHeight']
scaled_img = cv2.resize(img.astype('uint8'), (int(Width * Scale), int(Height *
Scale)), interpolation=cv2.INTER_AREA)
ct = [int(scaled_img.shape[1] / 2), int(scaled_img.shape[0] / 2)]
cx = ct[0] + OffsetX * Scale
cy = ct[1] + OffsetY * Scale
img1 = scaled_img[int(cy - Height/2):int(cy + Height/2),
int(cx - Width/2):int(cx + Width/2)]
cv2.imshow('1',cv2.resize(img1,(PiPX1 + PiPX2,PiPY1 +
PiPY2),interpolation=cv2.INTER_AREA))
cv2.waitKey(0)

I am gettig an error in my program of face recognition. (-215:Assertion failed) !empty() in function 'cv::CascadeClassifier::detectMultiScale'

I am using LBPH algorithm for face detection. The part of collecting the data and training is working fine but in the testing part, there is an error
This is code for testing
import cv2
import numpy as np
import webbrowser
face_classifier = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
def face_detector(img, size=0.5):
faces = ()
# Convert image to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow('Printe1r', gray )
if np.count_nonzero(gray) >= 0:
print("in face detector")
faces = face_classifier.detectMultiScale(gray, 1.3, 5)
if faces is ():
return img, []
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,255),2)
roi = img[y:y+h, x:x+w]
roi = cv2.resize(roi, (200, 200))
return img, roi
# Open Webcam
cap = cv2.VideoCapture(0)
print("WebCam opened")
while True:
ret, frame = cap.read()
cv2.imshow('Printe1rwer', frame )
image, face = face_detector(frame)
cv2.imshow('Printe1aas r', image )
print(face)
try:
print("hell1o")
face = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY)
print("hello")
# Pass face to prediction model
# "results" comprises of a tuple containing the label and the confidence value
results = model.predict(face)
print("Helo",results)
if results[1] < 500:
print("in results < 500")
confidence = int( 100 * (1 - (results[1])/400) )
display_string = str(confidence) + '% Confident it is User'
cv2.putText(face, display_string, (100, 120), cv2.FONT_HERSHEY_COMPLEX, 1, (255,120,150), 2)
if confidence > 75:
print("in confidence < 75")
cv2.putText(face, "Hey Vimal", (250, 450), cv2.FONT_HERSHEY_COMPLEX, 1, (0,255,0), 2)
cv2.imshow('Face Recognition', face )
webbrowser.open('')
break
else:
print("in else")
cv2.putText(face, "Locked", (250, 450), cv2.FONT_HERSHEY_COMPLEX, 1, (0,0,255), 2)
cv2.imshow('Face Recognition', face )
except Exception as e:
print(e)
cv2.putText(frame, "No Face Found", (220, 120) , cv2.FONT_HERSHEY_COMPLEX, 1, (0,0,255), 2)
cv2.putText(frame, "Locked", (250, 450), cv2.FONT_HERSHEY_COMPLEX, 1, (0,0,255), 2)
cv2.imshow('Face Recognition', frame )
pass
if cv2.waitKey(1) == 13: #13 is the Enter Key
break
cap.release()
cv2.destroyAllWindows()
The error I am getting is:
---------------------------------------------------------------------------
error Traceback (most recent call last)
<ipython-input-1-3a076399e5b1> in <module>
34 ret, frame = cap.read()
35 cv2.imshow('Printe1rwer', frame )
---> 36 image, face = face_detector(frame)
37 cv2.imshow('Printe1aas r', image )
38 print(face)
<ipython-input-1-3a076399e5b1> in face_detector(img, size)
14 if np.count_nonzero(gray) >= 0:
15 print("in face detector")
---> 16 faces = face_classifier.detectMultiScale(gray, 1.3, 5)
17
18 if faces is ():
error: OpenCV(4.2.0) C:\projects\opencv-python\opencv\modules\objdetect\src\cascadedetect.cpp:1689:
error: (-215:Assertion failed) !empty() in function 'cv::CascadeClassifier::detectMultiScale'`
Could somebody help me out??
I am using the OpenCV version 4.2.0
One thing is the value of the variable gray in the face detector function is always a numpy array with all values as zero. I have checked that but it is always zero.
I've tested the first part of your code. It seems to be working, printing gray I get:
TEMP.py:20: SyntaxWarning: "is" with a literal. Did you mean "=="?
if faces is ():
WebCam opened
[[162 162 162 ... 97 97 97]
[161 161 160 ... 95 95 95]
[159 159 161 ... 95 95 95]
...
[252 252 252 ... 164 164 164]
[236 233 229 ... 165 164 164]
[164 158 153 ... 164 164 164]]
Apart from correcting () with == as suggested by the interpreter, I would check:
That the img that comes in face detector is nonzero (just print it, mine is ok).
That you're actually loading the right input source in cap = cv2.VideoCapture(0) (do you have multiple webcams attached?)
Try inserting a if frame: block just after ret, frame = cap.read(). Probably only the first frame is None and it is giving you all the problems.
If the above are ok, the only suspect remains gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)...
A side note: ret, frame = cap.read() reads all the input continuously from the camera, but the pc may be slower than your algorithm in processing every frame. I usually avoid the creation of a long buffer using a trick. After you solve the above, have a look at this.
I tried changing the file path for "haarcascade_frontalface_default.xml" and it worked for me. I mean I provided the exact path for the location.

How to calculate png size based on dimension and bit depth

I'm trying to generate white png (jpg, gif as well) files using imagemagick. I have to calculate image's dimension based on size(kb) and bit depth(1).
I'm using this command on my windows machine:
magick -size "width" x "height" canvas:black white.png
I'm getting the following results
1 x 1 = 258 bytes;
2 x 2 = 260;
9 x 9 = 262;
17 x 17 = 263;
33 x 33 = 264;
40 x 40 = 263;
41 x 41 = 265;
65 x 65 = 267;
66 x 66 = 268;
What I understood from the results above is that minimal size is 256 + 1 (width) + 1 (height). So 1 x 1 file's size would be 258, 2 x 2 = 260. Results that goes next to these two seems not logical for me, why 33x33 is bigger than 40x40?
I have read png specification but couldn't figure out the formula how to calculate png (or other formats) size?

What Linear Mapping Function

What linear mapping function is required to map a gray image from [30-200] to [0, 255]?
I have already done some work and this is what I have come up with, but I would like to know if it's the correct way to do it:
min : 30, want to map to 0
mid : 85, want to map to 128
max : 200, want to map to 255
if (i <= mid), M(i) = 127*(i - min)/(mid - min)
if (i > mid), M(i) = 128 + (255 - 128)*(i - mid - 1)/(max - mid - 1);
This appears to be correct to me because:
if i = 30, it should map to 0. Plugging the information in:
M(30) = 127*(30-30)/(85 - 30) = 0
If i = 85, it should map to 127:
M(85) = 127*(85 - 30) / (85 - 30) = 127
If i = 200, it should map to 200:
M(200) = 128 + (255 - 128)*(200 - 85 - 1)/(200 - 85 - 1) = 255
Thank you.
If you apply a linear mapping, the middle of the first interval will be automatically mapped to the middle of the second interval (you can see it as Thales principle). So you need to apply only one equation: y=a.x+b
To solve this equation you have two information: a.30+b=0, and
a.200+b=255.
Then you solve this and you obtain: a=1.5, and b=-45.
And be careful, the middle of [30, 200] is not 85 but 115 (=30+85).
Finally you can check, if you apply 1.5*x-45=y, you successfully obtain: 30->0, 200->255, and 115->127.5

Number of Channels-Matlab vs Opencv

I am using an image, the details of which I got using imfinfo in matlab are as follows:
Filename: 'dog.jpg'
FileModDate: '25-Mar-2011 15:54:00'
FileSize: 8491
Format: 'jpg'
FormatVersion: ''
Width: 194
Height: 206
BitDepth: 24
ColorType: 'truecolor'
FormatSignature: ''
NumberOfSamples: 3
CodingMethod: 'Huffman'
CodingProcess: 'Sequential'
Comment: {}
NewSubFileType: 0
BitsPerSample: [8 8 8]
PhotometricInterpretation: 'RGB'
ImageDescription: [1x13 char]
StripOffsets: 154
SamplesPerPixel: 3
RowsPerStrip: 206
StripByteCounts: 119892
It shows number of channels =3(NumberOfSamples: 3) but when I find the number of channels in opencv using the following code, I get No. of channels = 1
Mat img = imread("dog.jpg", 0);
printf("No. of Channels = %d\n", img.channels());
Why so?? Please explain.
As #berak commented, by using 0 as the second parameter of imread(), you are loading it as a grayscale image. Try to load it by passing it a negative value <0 in order to return the loaded image as is (with alpha channel) or a positive value >0 to return a 3-channel color image.
Like:
Mat img = imread("dog.jpg", -1); // <0 Return the loaded image as is
^^

Resources