I have a tif image that has transparent pixels (I can see them in paint.net as transparent pixels).
I am trying to read them into a Mat in openCV and I am using this code:
Mat image=imread(imagePathname,CV_LOAD_IMAGE_UNCHANGED);
auto x=image.channels();
based on I my understanding, since the input image has transparency, channels() should return 4, but it return 3.
How can I read a tif image with transparent pixels and checking if a pixel is transparent in opencv?
edit1
Result of running imagemagick:
Image: layer0003.tif
Format: TIFF (Tagged Image File Format)
Mime type: image/tiff
Class: DirectClass
Geometry: 10000x5000+0+0
Resolution: 150x150
Print size: 66.6667x33.3333
Units: PixelsPerInch
Type: TrueColorAlpha
Base type: TrueColor
Endianess: MSB
Colorspace: sRGB
Depth: 8-bit
Channel depth:
red: 8-bit
green: 8-bit
blue: 8-bit
alpha: 1-bit
Channel statistics:
Red:
min: 0 (0)
max: 255 (1)
mean: 23.6472 (0.0927342)
standard deviation: 37.6851 (0.147785)
kurtosis: 8.93054
skewness: 2.28009
Green:
min: 0 (0)
max: 255 (1)
mean: 22.8353 (0.0895504)
standard deviation: 37.6516 (0.147653)
kurtosis: 10.4255
skewness: 2.52881
Blue:
min: 0 (0)
max: 255 (1)
mean: 22.798 (0.0894041)
standard deviation: 37.6575 (0.147677)
kurtosis: 10.9059
skewness: 2.58999
Alpha:
min: 0 (0)
max: 255 (1)
mean: 89.055 (0.349235)
standard deviation: 121.566 (0.476728)
kurtosis: -1.59995
skewness: -0.632496
Image statistics:
Overall:
min: 0 (0)
max: 255 (1)
mean: 58.8064 (0.230613)
standard deviation: 68.9821 (0.270518)
kurtosis: 8.35337
skewness: 3.53852
Alpha: none #00000000
Rendering intent: Perceptual
Gamma: 0.454545
Chromaticity:
red primary: (0.64,0.33)
green primary: (0.3,0.6)
blue primary: (0.15,0.06)
white point: (0.3127,0.329)
Background color: white
Border color: srgba(223,223,223,1)
Matte color: grey74
Transparent color: none
Interlace: None
Intensity: Undefined
Compose: Over
Page geometry: 10000x5000+0+0
Dispose: Undefined
Iterations: 0
Compression: LZW
Orientation: TopLeft
Properties:
date:create: 2014-03-01T13:11:12+00:00
date:modify: 2014-02-28T17:48:41+00:00
signature: dfa3e35c35345ef3440ff15d15ad37222f9cf0376bed7b7710dd95f4e537e210
tiff:alpha: unassociated
tiff:endian: lsb
tiff:photometric: RGB
tiff:rows-per-strip: 1
tiff:timestamp: 2014:02:28 17:48:38
xmp:CreatorTool: Microsoft Windows Live Photo Gallery 15.4.3555.308
Profiles:
Profile-xmp: 12702 bytes
Artifacts:
filename: layer0003.tif
verbose: true
Tainted: False
Filesize: 20.42MB
Number pixels: 50M
Pixels per second: 60.24MB
User time: 0.827u
Elapsed time: 0:01.829
Version: ImageMagick 6.8.8-7 Q16 x64 2014-02-13 http://www.imagemagick.org
I just had some time to revisit this :-)
Basically, I think the issue is that ImageMagick will adopt the most economical, in terms of file size, when writing its output files. So, if your image is basically greyscale but the alpha (opacity) channel is only 0 or 1, ImageMagick will encode that with 16-bit greyscale for the data and single-bit alpha channel. I guess that is beyond OpenCV as it seems to expect the alpha to be encoded with the same depth as the data.
So, the question becomes... "How can you force the combination you need of data/alpha (both 8-bit, not 8-bit plus 1-bit) greyscale/colour (8-bit greyscale or 8-bit colour)?"
There may be other ways, but for now, I can envisage adding a row across the bottom of the image that forces ImageMagick's hand and which you can hopefully readily remove once it has done the trick for you in OpenCV.
So, let's create a 16-bit greyscale image with a single-bit alpha where it makes the square transparent hole in the middle:
convert -size 300x300 gradient:black-white -alpha set -region 100x100+100+100 -alpha transparent image.tif
Let's check what we have:
identify -verbose image.tif | head -14
Image: image.tif
Format: TIFF (Tagged Image File Format)
Mime type: image/tiff
Class: DirectClass
Geometry: 300x300+0+0
Units: PixelsPerInch
Type: GrayscaleAlpha
Base type: Grayscale
Endianess: LSB
Colorspace: Gray
Depth: 16-bit
Channel depth:
gray: 16-bit <--- 16-bit greyscale data
alpha: 1-bit <--- 1-bit alpha
Now let's force it to 8-bit alpha and 8-bit data:
# Force to at least 8-bit greyscale (but maybe RGB depending on rest of image) plus 8-bit alpha...
# ... by adding a line across the bottom with alpha varying from 0 to 1 (i=x coordinate,w=width)
convert image.tif \
\( +clone -resize x1! -channel A -fx "i/w" \) \
-append -depth 8 result.tif
Let's check it worked:
identify -verbose result.tif | head -16
Image: result.tif
Format: TIFF (Tagged Image File Format)
Mime type: image/tiff
Class: DirectClass
Geometry: 300x301+0+0 <--- one extra row
Units: PixelsPerInch
Type: GrayscaleAlpha
Base type: Grayscale
Endianess: LSB
Colorspace: Gray
Depth: 8-bit
Channel depth:
gray: 8-bit <--- 8-bit data
alpha: 8-bit <--- 8-bit alpha
Now let's force 8-bit RGB plus 8-bit alpha:
# Force to 8-bit RGB plus 8-bit alpha...
# ... by adding a coloured line across the bottom with alpha varying from 0 to 1 (i=x coordinate,w=width)
convert image.tif \
\( +clone -resize x1! -channel RGBA -fx "rand()" \) \
-append -depth 8 result.tif
And let's check again:
Image: result.tif
Format: TIFF (Tagged Image File Format)
Mime type: image/tiff
Class: DirectClass
Geometry: 300x301+0+0 <--- 1 extra row
Units: PixelsPerInch
Type: TrueColorAlpha
Base type: TrueColor <--- Truecolour
Endianess: LSB
Colorspace: sRGB <--- RGB
Depth: 8-bit
Channel depth:
red: 8-bit <--- 8-bit red
green: 8-bit <--- 8-bit green
blue: 8-bit <--- 8-bit blue
alpha: 8-bit <--- 8-bit alpha
Related
I'm working on a small personal project that converts images from different formats for ML purposes - specifically with multi-threading in mind.
Initially, everything was working smoothly: PNGs were being converted into JPGs as expected. I then added more images to the test batch which resulted in errors.
Apologies if my grammar is off or if I'm missing any info, I'm heavily sleep deprived as I type this lol.
I attempted to add more image types to the boost::gil::any_image keyword, which did help with the majority of the test batch, but I'm now left with 3 files that will not convert.
Code being run: -> int main()
using namespace boost::gil;
any_image<gray1_image_t, gray4_image_t, gray8_image_t, gray16_image_t, gray32_image_t, gray64f_image_t, rgb8_image_t, rgb16_image_t, rgb32_image_t, rgb64f_image_t, rgba8_image_t, rgba16_image_t, rgba32_image_t, rgba64f_image_t> img;
for (int i = 0; i < f_cache_size; i++) {
std::string tmp_png = R"()" + final_cache[i];
read_image(tmp_png, img, png_tag());
container.png_to_jpg(tmp_png, img, 95);
}
-> Convert.cpp
// Converts PNG files into JPG files
void Convert::png_to_jpg(std::string fileName, boost::gil::any_image<boost::gil::gray1_image_t, boost::gil::gray4_image_t, boost::gil::gray8_image_t, boost::gil::gray16_image_t, boost::gil::gray32_image_t, boost::gil::gray64f_image_t, boost::gil::rgb8_image_t, boost::gil::rgb16_image_t, boost::gil::rgb32_image_t, boost::gil::rgb64f_image_t, boost::gil::rgba8_image_t, boost::gil::rgba16_image_t, boost::gil::rgba32_image_t, boost::gil::rgba64f_image_t> image, int quality)
{
using namespace boost::gil;
std::string jpg = R"(.jpg)";
std::string png = R"(.png)";
fileName = remove_postfix_from_string(fileName, png, jpg);
write_view(fileName, view(image), image_write_info<jpeg_tag>(quality));
}
Error code after attempting to run the program:
terminate called after throwing an instance of 'std::ios_base::failure[abi:cxx11]'
what(): dynamic_io: unsupported view type for the given file format: iostream error
Aborted (core dumped)
Extra information on 3 different image files:
Image:
Filename: rebarchi_ - pog.png
Permissions: rw-r--r--
Format: PNG (Portable Network Graphics)
Mime type: image/png
Class: DirectClass
Geometry: 898x677+0+0
Units: Undefined
Colorspace: sRGB
Type: TrueColorAlpha
Endianness: Undefined
Depth: 8-bit
Channel depth:
Red: 8-bit
Green: 8-bit
Blue: 8-bit
Alpha: 1-bit
Channel statistics:
Pixels: 607946
Red:
min: 0 (0)
max: 255 (1)
mean: 230.031 (0.902081)
median: 254 (0.996078)
standard deviation: 53.3536 (0.20923)
kurtosis: 4.84342
skewness: -2.35946
entropy: 0.430811
Green:
min: 0 (0)
max: 255 (1)
mean: 220.531 (0.864827)
median: 251 (0.984314)
standard deviation: 60.4584 (0.237092)
kurtosis: 2.50953
skewness: -1.91354
entropy: 0.461063
Blue:
min: 0 (0)
max: 255 (1)
mean: 200.472 (0.786166)
median: 233 (0.913725)
standard deviation: 60.5139 (0.237309)
kurtosis: 1.31362
skewness: -1.62729
entropy: 0.581842
Alpha:
min: 255 (1)
max: 255 (1)
mean: 255 (1)
median: 255 (1)
standard deviation: 0 (0)
kurtosis: 1.6384e+52
skewness: 9.375e+35
entropy: 0
Image statistics:
Overall:
min: 0 (0)
max: 255 (1)
mean: 226.509 (0.888269)
median: 248.25 (0.973529)
standard deviation: 43.5815 (0.170908)
kurtosis: 4.43874
skewness: -2.3037
entropy: 0.368429
Rendering intent: Perceptual
Gamma: 0.454545
Chromaticity:
red primary: (0.64,0.33)
green primary: (0.3,0.6)
blue primary: (0.15,0.06)
white point: (0.3127,0.329)
Matte color: grey74
Background color: white
Border color: srgb(223,223,223)
Transparent color: black
Interlace: None
Intensity: Undefined
Compose: Over
Page geometry: 898x677+0+0
Dispose: Undefined
Iterations: 0
Compression: Zip
Orientation: Undefined
Profiles:
Profile-icc: 672 bytes
Properties:
date:create: 2023-01-23T21:48:17+00:00
date:modify: 2023-01-23T21:48:17+00:00
date:timestamp: 2023-01-23T22:41:00+00:00
icc:copyright: Public Domain
icc:description: GIMP built-in sRGB
icc:manufacturer: GIMP
icc:model: sRGB
png:bKGD: chunk was found (see Background color, above)
png:cHRM: chunk was found (see Chromaticity, above)
png:iCCP: chunk was found
png:IHDR.bit-depth-orig: 8
png:IHDR.bit_depth: 8
png:IHDR.color-type-orig: 6
png:IHDR.color_type: 6 (RGBA)
png:IHDR.interlace_method: 0 (Not interlaced)
png:IHDR.width,height: 898, 677
png:text: 8 tEXt/zTXt/iTXt chunks were found
png:text-encoded profiles: 1 were found
signature: 4c66ed2e90b6170ec6aa73f893b89d8007d0df621c15f78aab89891fe086a942
Artifacts:
verbose: true
Tainted: False
Filesize: 885759B
Number pixels: 607946
Pixel cache type: Memory
Pixels per second: 46.257MP
User time: 0.020u
Elapsed time: 0:01.013
Version: ImageMagick 7.1.0-58 Q16-HDRI x86_64 20802 https://imagemagick.org
Image:
Filename: insane.png
Permissions: rwxr-xr-x
Format: PNG (Portable Network Graphics)
Mime type: image/png
Class: DirectClass
Geometry: 753x770+0+0
Resolution: 28.34x28.34
Print size: 26.5702x27.1701
Units: PixelsPerCentimeter
Colorspace: sRGB
Type: TrueColorAlpha
Endianness: Undefined
Depth: 8-bit
Channel depth:
Red: 8-bit
Green: 8-bit
Blue: 8-bit
Alpha: 8-bit
Channel statistics:
Pixels: 579810
Red:
min: 0 (0)
max: 255 (1)
mean: 73.6133 (0.28868)
median: 0 (0)
standard deviation: 100.617 (0.394577)
kurtosis: -0.917795
skewness: 0.925
entropy: 0.381909
Green:
min: 0 (0)
max: 255 (1)
mean: 66.3444 (0.260174)
median: 0 (0)
standard deviation: 91.5125 (0.358873)
kurtosis: -0.879259
skewness: 0.938695
entropy: 0.386062
Blue:
min: 0 (0)
max: 255 (1)
mean: 62.6174 (0.245558)
median: 0 (0)
standard deviation: 83.5006 (0.327453)
kurtosis: -0.967664
skewness: 0.854211
entropy: 0.380587
Alpha:
min: 0 (0)
max: 255 (1)
mean: 113.83 (0.446393)
median: 0 (0)
standard deviation: 126.362 (0.495537)
kurtosis: -1.94916
skewness: 0.21525
entropy: 0.152762
Image statistics:
Overall:
min: 0 (0)
max: 255 (1)
mean: 79.1013 (0.310201)
median: 0 (0)
standard deviation: 100.498 (0.39411)
kurtosis: -1.19736
skewness: 0.773146
entropy: 0.32533
Alpha: none #00000000
Rendering intent: Perceptual
Gamma: 0.454545
Chromaticity:
red primary: (0.64,0.33)
green primary: (0.3,0.6)
blue primary: (0.15,0.06)
white point: (0.3127,0.329)
Matte color: grey74
Background color: white
Border color: srgb(223,223,223)
Transparent color: black
Interlace: None
Intensity: Undefined
Compose: Over
Page geometry: 753x770+0+0
Dispose: Undefined
Iterations: 0
Compression: Zip
Orientation: Undefined
Properties:
date:create: 2023-01-23T20:57:57+00:00
date:modify: 2023-01-23T20:57:57+00:00
date:timestamp: 2023-01-23T20:59:30+00:00
png:IHDR.bit-depth-orig: 8
png:IHDR.bit_depth: 8
png:IHDR.color-type-orig: 6
png:IHDR.color_type: 6 (RGBA)
png:IHDR.interlace_method: 0 (Not interlaced)
png:IHDR.width,height: 753, 770
png:pHYs: x_res=2834, y_res=2834, units=1
signature: d2aab82c02f789a4830019216e2ec4946d2535fc211fc003b7737831221c6de2
Artifacts:
verbose: true
Tainted: False
Filesize: 204968B
Number pixels: 579810
Pixel cache type: Memory
Pixels per second: 62.2394MP
User time: 0.020u
Elapsed time: 0:01.009
Version: ImageMagick 7.1.0-58 Q16-HDRI x86_64 20802 https://imagemagick.org
[blink#MythOS TEST]$ identify -verbose insane.png
Image:
Filename: insane.png
Permissions: rw-r--r--
Format: PNG (Portable Network Graphics)
Mime type: image/png
Class: DirectClass
Geometry: 753x770+0+0
Resolution: 28.34x28.34
Print size: 26.5702x27.1701
Units: PixelsPerCentimeter
Colorspace: sRGB
Type: TrueColorAlpha
Endianness: Undefined
Depth: 8-bit
Channel depth:
Red: 8-bit
Green: 8-bit
Blue: 8-bit
Alpha: 8-bit
Channel statistics:
Pixels: 579810
Red:
min: 0 (0)
max: 255 (1)
mean: 73.6133 (0.28868)
median: 0 (0)
standard deviation: 100.617 (0.394577)
kurtosis: -0.917795
skewness: 0.925
entropy: 0.381909
Green:
min: 0 (0)
max: 255 (1)
mean: 66.3444 (0.260174)
median: 0 (0)
standard deviation: 91.5125 (0.358873)
kurtosis: -0.879259
skewness: 0.938695
entropy: 0.386062
Blue:
min: 0 (0)
max: 255 (1)
mean: 62.6174 (0.245558)
median: 0 (0)
standard deviation: 83.5006 (0.327453)
kurtosis: -0.967664
skewness: 0.854211
entropy: 0.380587
Alpha:
min: 0 (0)
max: 255 (1)
mean: 113.83 (0.446393)
median: 0 (0)
standard deviation: 126.362 (0.495537)
kurtosis: -1.94916
skewness: 0.21525
entropy: 0.152762
Image statistics:
Overall:
min: 0 (0)
max: 255 (1)
mean: 79.1013 (0.310201)
median: 0 (0)
standard deviation: 100.498 (0.39411)
kurtosis: -1.19736
skewness: 0.773146
entropy: 0.32533
Alpha: none #00000000
Rendering intent: Perceptual
Gamma: 0.454545
Chromaticity:
red primary: (0.64,0.33)
green primary: (0.3,0.6)
blue primary: (0.15,0.06)
white point: (0.3127,0.329)
Matte color: grey74
Background color: white
Border color: srgb(223,223,223)
Transparent color: black
Interlace: None
Intensity: Undefined
Compose: Over
Page geometry: 753x770+0+0
Dispose: Undefined
Iterations: 0
Compression: Zip
Orientation: Undefined
Properties:
date:create: 2023-01-23T21:48:17+00:00
date:modify: 2023-01-23T21:48:17+00:00
date:timestamp: 2023-01-23T21:48:27+00:00
png:bKGD: chunk was found (see Background color, above)
png:cHRM: chunk was found (see Chromaticity, above)
png:IHDR.bit-depth-orig: 8
png:IHDR.bit_depth: 8
png:IHDR.color-type-orig: 6
png:IHDR.color_type: 6 (RGBA)
png:IHDR.interlace_method: 0 (Not interlaced)
png:IHDR.width,height: 753, 770
png:pHYs: x_res=2834, y_res=2834, units=1
png:text: 3 tEXt/zTXt/iTXt chunks were found
signature: d2aab82c02f789a4830019216e2ec4946d2535fc211fc003b7737831221c6de2
Artifacts:
verbose: true
Tainted: False
Filesize: 204437B
Number pixels: 579810
Pixel cache type: Memory
Pixels per second: 62.4627MP
User time: 0.020u
Elapsed time: 0:01.009
Version: ImageMagick 7.1.0-58 Q16-HDRI x86_64 20802 https://imagemagick.org
Image:
Filename: smooth_brain.png
Permissions: rwxr-xr-x
Format: PNG (Portable Network Graphics)
Mime type: image/png
Class: DirectClass
Geometry: 557x556+0+0
Resolution: 37.79x37.79
Print size: 14.7393x14.7129
Units: PixelsPerCentimeter
Colorspace: sRGB
Type: TrueColorAlpha
Endianness: Undefined
Depth: 8-bit
Channel depth:
Red: 8-bit
Green: 8-bit
Blue: 8-bit
Alpha: 1-bit
Channel statistics:
Pixels: 309692
Red:
min: 0 (0)
max: 255 (1)
mean: 186.136 (0.729945)
median: 220 (0.862745)
standard deviation: 68.4489 (0.268427)
kurtosis: 2.4105
skewness: -1.97795
entropy: 0.68527
Green:
min: 0 (0)
max: 236 (0.92549)
mean: 176.377 (0.691674)
median: 209 (0.819608)
standard deviation: 71.0393 (0.278586)
kurtosis: 1.32263
skewness: -1.63417
entropy: 0.688323
Blue:
min: 0 (0)
max: 255 (1)
mean: 181.988 (0.713678)
median: 211 (0.827451)
standard deviation: 65.9658 (0.258689)
kurtosis: 2.31119
skewness: -1.87115
entropy: 0.696014
Alpha:
min: 255 (1)
max: 255 (1)
mean: 255 (1)
median: 255 (1)
standard deviation: 0 (0)
kurtosis: 1.6384e+52
skewness: 9.375e+35
entropy: 0
Image statistics:
Overall:
min: 0 (0)
max: 255 (1)
mean: 199.875 (0.783824)
median: 223.75 (0.877451)
standard deviation: 51.3635 (0.201425)
kurtosis: 3.02315
skewness: -1.95237
entropy: 0.517402
Rendering intent: Perceptual
Gamma: 0.45455
Chromaticity:
red primary: (0.64,0.33)
green primary: (0.3,0.6)
blue primary: (0.15,0.06)
white point: (0.3127,0.329)
Matte color: grey74
Background color: white
Border color: srgb(223,223,223)
Transparent color: black
Interlace: None
Intensity: Undefined
Compose: Over
Page geometry: 557x556+0+0
Dispose: Undefined
Iterations: 0
Compression: Zip
Orientation: Undefined
Properties:
date:create: 2023-01-23T20:57:57+00:00
date:modify: 2023-01-23T20:57:57+00:00
date:timestamp: 2023-01-23T20:58:24+00:00
png:cHRM: chunk was found (see Chromaticity, above)
png:gAMA: gamma=0.45455 (See Gamma, above)
png:IHDR.bit-depth-orig: 8
png:IHDR.bit_depth: 8
png:IHDR.color-type-orig: 6
png:IHDR.color_type: 6 (RGBA)
png:IHDR.interlace_method: 0 (Not interlaced)
png:IHDR.width,height: 557, 556
png:pHYs: x_res=3779, y_res=3779, units=1
png:sRGB: intent=0 (Perceptual Intent)
signature: c5a4758ce0030fa4dcba3c8de843cb8a89157563cd4bc305d7c887301e813ddf
Artifacts:
verbose: true
Tainted: False
Filesize: 225641B
Number pixels: 309692
Pixel cache type: Memory
Pixels per second: 65.1504MP
User time: 0.000u
Elapsed time: 0:01.004
Version: ImageMagick 7.1.0-58 Q16-HDRI x86_64 20802 https://imagemagick.org
First of all, I realize there are existing questions about converting an RGB image to an HSV image out there; I used one of those questions to help me write my code. However, I am getting values for HSV that don't make sense to me.
What I know about HSV I have gotten from this website. From this colorpicker, I have inferred that H is a number ranging from 0-360 degrees, S is a number ranging from 0-100%, and V is a number ranging from 0-100%. Therefore, I had assumed that my code (as follows) would return an H value between 0 and 360, and S/V values between 0 and 100. However, this is not the case.
I plugged my program's output into the above color picker, which all S/V values down to 100 when they exceeded 100. As you can see, the output is close to what it should be, but is not accurate. I feel like this is because I am interpreting the HSV values incorrectly.
For contex, I am going to establish a range for each color on the cube and from there look at the other faces and fill out the current setup of the cube in another program I have.
My code:
void get_color(Mat img, int x_offset, int y_offset)
{
Rect outline(x_offset - 2, y_offset - 2, 5, 5);
rectangle(img, outline, Scalar(255, 0, 0), 2);
Rect sample(x_offset, y_offset, 1, 1);
Mat rgb_image = img(sample);
Mat hsv_image;
cvtColor(rgb_image, hsv_image, CV_BGR2HSV);
Vec3b hsv = hsv_image.at<Vec3b>(0, 0);
int hue = hsv.val[0];
int saturation = hsv.val[1];
int value = hsv.val[2];
printf("H: %d, S: %d, V: %d \n", hue, saturation, value);
}
Output of the program:
H: 21, S: 120, V: 191 // top left cubie
H: 1, S: 180, V: 159 // top center cubie
H: 150, S: 2, V: 142 // top right cubie
H: 86, S: 11, V: 159 // middle left cubie
H: 75, S: 12, V: 133 // middle center cubie
H: 5, S: 182, V: 233 // middle right cubie
H: 68, S: 7, V: 156 // bottom left cubie
H: 25, S: 102, V: 137 // bottom center cubie
H: 107, S: 155, V: 69 // bottom right cubie
Starting image (pixel being extracted # center of each blue square):
Resulting colors (as the above color picker gave):
As you can see, the red and white is fairly accurate, but the orange and yellow are not correct and the blue is blatantly wrong; it is impossible for the pixel I looked at to actually be that color. What am I doing wrong? Any help would be greatly appreciated.
OpenCV has a funny way of representing its colors.
Hue - Represented as a number from 0-179 instead of 0-360. Therefore, multiply the H value by two before plugging it into a traditional color picker.
Saturation/Value - Represented as a number from 0-255. To get a percentage, divide given answer by 255 and multiply by 100 to get a percentage.
Everything works much more sensibly now. See this website for more details on OpenCV and HSV.
I installed OpenCV in my Windows OS and successfully configure a correpond Visual Studio project. But when I use imread to read a tiff image file, the Mat object would be empty. If I convert the file to bmp format, the program works. I wonder how can OpenCV do tiff I/O in windows.
My OpenCV version is 2.4.13 and I am using VS 2013.
After running "magick identify", the output is:
Image: TBAL2015032700100902012.tif
Format: TIFF (Tagged Image File Format)
Mime type: image/tiff
Class: DirectClass
Geometry: 2502x1505+0+0
Resolution: 300x300
Print size: 8.34x5.01667
Units: PixelsPerInch
Type: TrueColor
Endianess: LSB
Colorspace: sRGB
Depth: 8-bit
Channel depth:
Red: 8-bit
Green: 8-bit
Blue: 8-bit
Channel statistics:
Pixels: 3765510
Red:
min: 0 (0)
max: 255 (1)
mean: 199.179 (0.781094)
standard deviation: 44.2111 (0.173377)
kurtosis: 9.97873
skewness: -3.17169
entropy: 0.774441
Green:
min: 0 (0)
max: 255 (1)
mean: 204.13 (0.800508)
standard deviation: 41.8485 (0.164112)
kurtosis: 9.24617
skewness: -3.00098
entropy: 0.77394
Blue:
min: 0 (0)
max: 255 (1)
mean: 156.85 (0.615098)
standard deviation: 41.3859 (0.162298)
kurtosis: 1.57158
skewness: -1.13336
entropy: 0.89716
Image statistics:
Overall:
min: 0 (0)
max: 255 (1)
mean: 186.72 (0.732233)
standard deviation: 47.5017 (0.186281)
kurtosis: 3.30247
skewness: -1.81231
entropy: 0.81518
Rendering intent: Perceptual
Gamma: 0.454545
Chromaticity:
red primary: (0.64,0.33)
green primary: (0.3,0.6)
blue primary: (0.15,0.06)
white point: (0.3127,0.329)
Matte color: grey74
Background color: white
Border color: srgb(223,223,223)
Transparent color: none
Interlace: None
Intensity: Undefined
Compose: Over
Page geometry: 2502x1505+0+0
Dispose: Undefined
Iterations: 0
Compression: JPEG
Orientation: TopLeft
Properties:
comment:
date:create: 2017-12-08T16:15:53+08:00
date:modify: 2015-03-27T10:25:22+08:00
jpeg:sampling-factor: 2x1
signature: 70f8c75014e79eb786765d727ccb564688c3da3c3d5f9f0b4c56f259e2d88625
tiff:alpha: unspecified
tiff:artist: SysAdmin
tiff:document: DN0P46158952 0000000022000000053700000.----!--
tiff:endian: lsb
tiff:make: Eastman Kodak
tiff:model: Kodak Scanner: i1405
tiff:photometric: YCBCR
tiff:rows-per-strip: 1505
tiff:software: KODAK Capture Desktop 1.2
tiff:timestamp: 2015.03.27 10:25:22
Artifacts:
verbose: true
Tainted: False
Filesize: 619460B
Number pixels: 3765510
Pixels per second: 83.6779MB
User time: 0.047u
Elapsed time: 0:01.045
Version: ImageMagick 7.0.7-14 Q16 x64 2017-12-06 http://www.imagemagick.org
The convolutional kernel in prototxt file needs only setting height and weight of image and the third dimension can be automatically set.
But how do I set 4-D kernel in prototxt file ?
In the figure
the input video is 4-D.
The the work
says the dimension of first convoltional layer is 4-D.
I have stuck in the issue for two weeks and I'm kind of desperate.
Can anyone help me ?
Thank you
Caffe supports blobs with more than 4 dimensions. If you want to perform temporal convolutions, I suppose you'll need to feed caffe with 5D input blobs with dimensions batch-channels-time-height-width. With this kind of input you can have temporal convolutions simply by changing the default axis argument in the convolution_param. For example:
input: "data"
input_shape: { dim: 5 dim: 15 dim: 3 dim: 227 dim: 227 }
layer {
name: "temporal_conv"
type: "Convolution"
bottom: "data"
top: "temporal_conv"
param { lr_mult: 1 decay_mult: 1 }
param { lr_mult: 2 decay_mult: 0 }
convolution_param {
num_output: 32
kernel_size: 3 kernel_size: 5 kernel_size: 5
pad: 1 pad: 2 pad: 2
stride: 1 stride: 2 stride: 2
axis: 1
}
}
This "temporal_conv" layer uses 3x5x5 kernel (pads the input accordingly) and stride 2 in the spatial domain and 1 in the temporal dimension.
#Shai Thank you for replying! I use HDF5 fromat in data layer for training. Tha data store as five dimensions with the order batch-channels-time-height-width. The prototxt part is
layer {
name: "data"
type: "HDF5Data"
top: "data"
top: "label"
include: {
phase: TRAIN
}
hdf5_data_param {
source: "path/to/txt"
batch_size: 50
}
}
and I got the error
I0520 21:39:35.705278 30447 net.cpp:84] Creating Layer conv1
I0520 21:39:35.705286 30447 net.cpp:381] conv1 <- data
I0520 21:39:35.705294 30447 net.cpp:339] conv1 -> conv1
I0520 21:39:35.705307 30447 net.cpp:113] Setting up conv1
F0520 21:39:35.705329 30447 base_conv_layer.cpp:14] Check failed: 4 == bottom[0]->num_axes() (4 vs. 5) Input must have 4 axes, corresponding to (num, channels, height, width)
It seems the input blob dimension should be 4. Is there any solution?
I am working on a project with a TFT touch screen. With this screen there is an included library. But after some reading, I still don't get something. In the library there are some defines regarding colors:
/* some RGB color definitions */
#define Black 0x0000 /* 0, 0, 0 */
#define Navy 0x000F /* 0, 0, 128 */
#define DarkGreen 0x03E0 /* 0, 128, 0 */
#define DarkCyan 0x03EF /* 0, 128, 128 */
#define Maroon 0x7800 /* 128, 0, 0 */
#define Purple 0x780F /* 128, 0, 128 */
#define Olive 0x7BE0 /* 128, 128, 0 */
#define LightGrey 0xC618 /* 192, 192, 192 */
#define DarkGrey 0x7BEF /* 128, 128, 128 */
#define Blue 0x001F /* 0, 0, 255 */
#define Green 0x07E0 /* 0, 255, 0 */
#define Cyan 0x07FF /* 0, 255, 255 */
#define Red 0xF800 /* 255, 0, 0 */
#define Magenta 0xF81F /* 255, 0, 255 */
#define Yellow 0xFFE0 /* 255, 255, 0 */
#define White 0xFFFF /* 255, 255, 255 */
#define Orange 0xFD20 /* 255, 165, 0 */
#define GreenYellow 0xAFE5 /* 173, 255, 47 */
#define Pink 0xF81F
Those are 16-bit colors. But how do they go from: 0, 128, 128(dark cyan) to 0x03EF. I mean, how do you convert a 16-bit color to a uint16? This doesn't need to have an answer in code, because I just want to add some colors in the library. A link to a online converter (which I could not find) would be okay as well :)
Thanks
From these one can easily find out the formula:
#define Red 0xF800 /* 255, 0, 0 */
#define Magenta 0xF81F /* 255, 0, 255 */
#define Yellow 0xFFE0 /* 255, 255, 0 */
F800 has 5 MSB bits set and FFE0 has 5 LSB not set.
0xF81F has obviously both 5 LSB's and 5 MSB's set, which proves the format to be RGB565.
The formula to convert a value 173 to Red is not as straightforward as it may look -- you can't simply drop the 3 least significant bits, but have to linearly interpolate to make 255 to correspond to 31 (or green 255 to correspond to 63).
NewValue = (31 * old_value) / 255;
(And this is still just a truncating division -- proper rounding could be needed)
With proper rounding and scaling:
Uint16_value = (((31*(red+4))/255)<<11) |
(((63*(green+2))/255)<<5) |
((31*(blue+4))/255);
EDIT Added parenthesis to as helpfully suggested by JasonD.
You need to know the exact format of the display, just "16-bit" is not enough.
There's RGB555, in which each of the three components get 5 bits. This drops the total color space to just 32,768 colors, wasting one bit but it's very simple to manage since the there's the same number of shades for each component.
There's also RGB565, in which the green component is given 6 bits (since the human eye is more sensitive to green). This might be the format you're having, since the "dark green" example is 0x03e0 which in binary is 0b0000 0011 1110 0000. Since there's 6 bits set to 1 there, I guess that's the total allocation for the green component and showing it's maximum value.
It's like this, then (with spaces separating every four bits and re-using the imaginary 0b prefix):
0bRRRR RGGG GGGB BBBB
Of course, the bit ordering can differ too, in the word.
The task of converting a triplet of numbers into a bit-packed word is quite easily done in typically programming languages that have bit manipulation operators.
In C, it's often done in a macro, but we can just as well have a function:
#include <stdint.h>
uint16_t rgb565_from_triplet(uint8_t red, uint8_t green, uint8_t blue)
{
red >>= 3;
green >>= 2;
blue >>= 3;
return (red << 11) | (green << 5) | blue;
}
note that the above assumes full 8-bit precision for the components, so maximum intensity for a component is 255, not 128 as in your example. If the color space really is using 7-bit components then some additional scaling would be necessary.
It looks like you're using RGB565, first 5 bits for Red, then 6 bits for Green, then 5 bits for Blue.
You should mask with 0xF800 and shift right 11 bits to get the red component (or shift 8 bits to get a value from 0-255).
Mask with 0x07E0 and shift right 5 bits to get green component (or 3 to get a 0-255 value).
Mask with 0x001F to get the blue component (and shift left 3 bits to get 0-255).
Your colours are in 565 format. It would be more obvious if you wrote them out in binary.
Blue, (0,0,255) is 0x001f, which is 00000 000000 11111
Green, (0, 255, 0) is 0x07e0, which is 00000 111111 00000
Red, (255, 0, 0) is 0xf800, which is 11111 000000 00000
To convert a 24 bit colour to 16 bit in this format, simply mask off the upper bits needed from each component, shift into position, and OR together.
The convert back into 24 bit colour from 16 bit, mask each component, shift into position, and then duplicate the upper bits into the lower bits.
In your examples it seems that some colours have been scaled and rounded rather than shifted.
I strongly recommend using the bit-shift method rather than scaling by a factor like 31/255, because the bit-shifting is not only likely to be faster, but should give better results.
The 3-part numbers you’re showing are applicable to 24-bit color. 128 in hex is 0x7f, but in your color definitions, it's being represented as 0x0f. Likewise, 255 is 0xff, but in your color definitions, it's being represented as 0x1f. This suggests that you need to take the 3-part numbers and shift them down by 3 bits (losing 3 bits of color data for each color). Then combine them into a single 16-bit number:
uint16 color = ((red>>3)<<11) | ((green>>2)<<5) | (blue>>3);
...revised from earlier because green uses 6 bits, not 5.
You need to know how many bits there are per colour channel. So yes, there are 16 bits for a colour, but the RGB components are each some subset of those bits. In your case, red is 5 bits, green is 6, and blue is 5. The format in binary would look like so:
RRRRRGGG GGGBBBBB
There are other 16 bit colour formats, such as red, green, and blue each being 5 bits and then use the remaining bit for an alpha value.
The range of values for both the red and blue channels will be from 0 to 2^5-1 = 31, while the range for green will be 0 to 2^6-1 = 63. So to convert from colours in the form of (0->255),(0->255),(0->255) you will need to map values from one to the other. For example, a red value of 128 in the range 0->255 will be mapped to (128/255) * 31 = 15.6 in the red channel with range 0-31. If we round down, we get 15 which is represented as 01111 in five bits. Similarly, for the green channel (with six bits) you will get 011111. SO the colour (128,128,128) will map to 01111011 11101111 which is 0x7BEF in hexadecimal.
You can apply this to the other values too: 0,128,128 becomes 00000011 11101111 which is 0x03EF.
Those colours shown in your code are RGB565. As shown by
#define Blue 0x001F /* 0, 0, 255 */
#define Green 0x07E0 /* 0, 255, 0 */
#define Red 0xF800 /* 255, 0, 0 */
If you simply want to add some new colours to this #defined list, the simplest way to convert from 16bit UINT per channel is just to shift your values down to loose the the low order bits and then shift and (or) them into position in the 16bitRGB value.
This could well produce banding artefacts though, and there may well be a better conversion method.
i.e.
UINT16 blue = 0xFF;
UINT16 green = 0xFF;
UINT16 red = 0xFF;
blue >>= 11; // top 5 bits
green >>= 10; // top 6 bits
red >>= 11; // top 5 bits
UINT16 RGBvalue = blue | (green <<5) | (red << 11)
You may need to mask of any unwanted stray bits after the shifts, as I am unsure how this works, but I think the code above should work.
Building on unwind's answer, specifically for the Adafruit GFX library using the Arduino 2.8" TFT Touchscreen(v2), you can add this function to your Arduino sketch and use it inline to calculate colors from rgb:
uint16_t getColor(uint8_t red, uint8_t green, uint8_t blue)
{
red >>= 3;
green >>= 2;
blue >>= 3;
return (red << 11) | (green << 5) | blue;
}
Now you can use it inline as so, illustrated with a function that creates a 20x20 square at x0,y0:
void setup() {
tft.begin();
makeSquare(getColor(20,157,217));
}
unsigned long makeSquare(uint16_t color1) {
tft.fillRect(0, 0, 20, 20, color1);
}
Docs for the Adafruit GFX library can be found here