How to count the pixels of a certain color with OpenCV?

Multi tool use
I'm trying to calculate the percentage of pixels in a certain color range in a picture.
I'm pretty new to OpenCV and python in general. What I've done is using the cv2.inRange()
function to create a mask which I have as output. Right now I'm trying to do this with GRB color values between (0, 0, 130) and (80, 80, 255) and consider "red" every pixel whose color is in this range. So the output I get has two colors: black and red.
I used then this numpy function to get the number of non zero pixels which at this point I expected to be the number of red pixels: red_pixel = np.count_nonzero(output)
.
Here is the full code:
import cv2
import numpy as np
img_name = input("What's the name of the picture? ")
img = cv2.imread(img_name)
# boundaries for the color red
boundaries = [
([0, 0, 130], [80, 80, 255])
]
for(lower, upper) in boundaries:
# creates numpy array from boundaries
lower = np.array(lower, dtype = "uint8")
upper = np.array(upper, dtype = "uint8")
# finds colors in boundaries a applies a mask
mask = cv2.inRange(img, lower, upper)
output = cv2.bitwise_and(img, img, mask = mask)
# saves the image
cv2.imwrite('2'+img_name, output)
tot_pixel = output.size
red_pixel = np.count_nonzero(output)
percentage = round(red_pixel * 100 / tot_pixel, 2)
print("Red pixels: " + str(red_pixel))
print("Total pixels: " + str(tot_pixel))
print("Percentage of red pixels: " + str(percentage) + "%")
I tested my code with four different pictures:
sea.jpg
which I'd expect to contain 0% of red. I run the program, as output I get a completely black image and the percentage is 0.00. Which is fine.
I tried then this one:
sample.jpg
I run the program and what I get for the percentage is 13.76 which I don't know if it's correct but could still be.
I tried a completely red image then: total-red.jpg
and I get 100.00 which is correct.
The strange thing happens when I try with this image:
almost-red.png
What I get running the program is this output:
2almost-red.png
which is what I expected. The percentage of non zero pixels though, is 33.07%
and I have no idea why.
Could you please help me figure out what I'm doing wrong and how I could correct the program? Thank you very much.
python opencv
add a comment |
I'm trying to calculate the percentage of pixels in a certain color range in a picture.
I'm pretty new to OpenCV and python in general. What I've done is using the cv2.inRange()
function to create a mask which I have as output. Right now I'm trying to do this with GRB color values between (0, 0, 130) and (80, 80, 255) and consider "red" every pixel whose color is in this range. So the output I get has two colors: black and red.
I used then this numpy function to get the number of non zero pixels which at this point I expected to be the number of red pixels: red_pixel = np.count_nonzero(output)
.
Here is the full code:
import cv2
import numpy as np
img_name = input("What's the name of the picture? ")
img = cv2.imread(img_name)
# boundaries for the color red
boundaries = [
([0, 0, 130], [80, 80, 255])
]
for(lower, upper) in boundaries:
# creates numpy array from boundaries
lower = np.array(lower, dtype = "uint8")
upper = np.array(upper, dtype = "uint8")
# finds colors in boundaries a applies a mask
mask = cv2.inRange(img, lower, upper)
output = cv2.bitwise_and(img, img, mask = mask)
# saves the image
cv2.imwrite('2'+img_name, output)
tot_pixel = output.size
red_pixel = np.count_nonzero(output)
percentage = round(red_pixel * 100 / tot_pixel, 2)
print("Red pixels: " + str(red_pixel))
print("Total pixels: " + str(tot_pixel))
print("Percentage of red pixels: " + str(percentage) + "%")
I tested my code with four different pictures:
sea.jpg
which I'd expect to contain 0% of red. I run the program, as output I get a completely black image and the percentage is 0.00. Which is fine.
I tried then this one:
sample.jpg
I run the program and what I get for the percentage is 13.76 which I don't know if it's correct but could still be.
I tried a completely red image then: total-red.jpg
and I get 100.00 which is correct.
The strange thing happens when I try with this image:
almost-red.png
What I get running the program is this output:
2almost-red.png
which is what I expected. The percentage of non zero pixels though, is 33.07%
and I have no idea why.
Could you please help me figure out what I'm doing wrong and how I could correct the program? Thank you very much.
python opencv
add a comment |
I'm trying to calculate the percentage of pixels in a certain color range in a picture.
I'm pretty new to OpenCV and python in general. What I've done is using the cv2.inRange()
function to create a mask which I have as output. Right now I'm trying to do this with GRB color values between (0, 0, 130) and (80, 80, 255) and consider "red" every pixel whose color is in this range. So the output I get has two colors: black and red.
I used then this numpy function to get the number of non zero pixels which at this point I expected to be the number of red pixels: red_pixel = np.count_nonzero(output)
.
Here is the full code:
import cv2
import numpy as np
img_name = input("What's the name of the picture? ")
img = cv2.imread(img_name)
# boundaries for the color red
boundaries = [
([0, 0, 130], [80, 80, 255])
]
for(lower, upper) in boundaries:
# creates numpy array from boundaries
lower = np.array(lower, dtype = "uint8")
upper = np.array(upper, dtype = "uint8")
# finds colors in boundaries a applies a mask
mask = cv2.inRange(img, lower, upper)
output = cv2.bitwise_and(img, img, mask = mask)
# saves the image
cv2.imwrite('2'+img_name, output)
tot_pixel = output.size
red_pixel = np.count_nonzero(output)
percentage = round(red_pixel * 100 / tot_pixel, 2)
print("Red pixels: " + str(red_pixel))
print("Total pixels: " + str(tot_pixel))
print("Percentage of red pixels: " + str(percentage) + "%")
I tested my code with four different pictures:
sea.jpg
which I'd expect to contain 0% of red. I run the program, as output I get a completely black image and the percentage is 0.00. Which is fine.
I tried then this one:
sample.jpg
I run the program and what I get for the percentage is 13.76 which I don't know if it's correct but could still be.
I tried a completely red image then: total-red.jpg
and I get 100.00 which is correct.
The strange thing happens when I try with this image:
almost-red.png
What I get running the program is this output:
2almost-red.png
which is what I expected. The percentage of non zero pixels though, is 33.07%
and I have no idea why.
Could you please help me figure out what I'm doing wrong and how I could correct the program? Thank you very much.
python opencv
I'm trying to calculate the percentage of pixels in a certain color range in a picture.
I'm pretty new to OpenCV and python in general. What I've done is using the cv2.inRange()
function to create a mask which I have as output. Right now I'm trying to do this with GRB color values between (0, 0, 130) and (80, 80, 255) and consider "red" every pixel whose color is in this range. So the output I get has two colors: black and red.
I used then this numpy function to get the number of non zero pixels which at this point I expected to be the number of red pixels: red_pixel = np.count_nonzero(output)
.
Here is the full code:
import cv2
import numpy as np
img_name = input("What's the name of the picture? ")
img = cv2.imread(img_name)
# boundaries for the color red
boundaries = [
([0, 0, 130], [80, 80, 255])
]
for(lower, upper) in boundaries:
# creates numpy array from boundaries
lower = np.array(lower, dtype = "uint8")
upper = np.array(upper, dtype = "uint8")
# finds colors in boundaries a applies a mask
mask = cv2.inRange(img, lower, upper)
output = cv2.bitwise_and(img, img, mask = mask)
# saves the image
cv2.imwrite('2'+img_name, output)
tot_pixel = output.size
red_pixel = np.count_nonzero(output)
percentage = round(red_pixel * 100 / tot_pixel, 2)
print("Red pixels: " + str(red_pixel))
print("Total pixels: " + str(tot_pixel))
print("Percentage of red pixels: " + str(percentage) + "%")
I tested my code with four different pictures:
sea.jpg
which I'd expect to contain 0% of red. I run the program, as output I get a completely black image and the percentage is 0.00. Which is fine.
I tried then this one:
sample.jpg
I run the program and what I get for the percentage is 13.76 which I don't know if it's correct but could still be.
I tried a completely red image then: total-red.jpg
and I get 100.00 which is correct.
The strange thing happens when I try with this image:
almost-red.png
What I get running the program is this output:
2almost-red.png
which is what I expected. The percentage of non zero pixels though, is 33.07%
and I have no idea why.
Could you please help me figure out what I'm doing wrong and how I could correct the program? Thank you very much.
python opencv
python opencv
asked Jan 3 at 9:02
AezysAezys
34
34
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Your image has three channels. Only one channel is in range in your third example almost-red.png.
Thus we can deduct that at most 33% of the image is in range. As there is some border it has to be even less. 33.07% sounds plausible.
If you want to check if any of the channels for each pixel is in range you have to sum up the three channels and than check for non-zero entries.
Thank you for the explanation, could you please suggest me a way to sum the three channels?
– Aezys
Jan 3 at 9:17
summed = np.sum(output, axis=2)
should do the trick. Do it before counting the total pixels.
– Mailerdaimon
Jan 3 at 9:19
Awesome, it worked! Thank you a lot
– Aezys
Jan 3 at 9:27
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54019108%2fhow-to-count-the-pixels-of-a-certain-color-with-opencv%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Your image has three channels. Only one channel is in range in your third example almost-red.png.
Thus we can deduct that at most 33% of the image is in range. As there is some border it has to be even less. 33.07% sounds plausible.
If you want to check if any of the channels for each pixel is in range you have to sum up the three channels and than check for non-zero entries.
Thank you for the explanation, could you please suggest me a way to sum the three channels?
– Aezys
Jan 3 at 9:17
summed = np.sum(output, axis=2)
should do the trick. Do it before counting the total pixels.
– Mailerdaimon
Jan 3 at 9:19
Awesome, it worked! Thank you a lot
– Aezys
Jan 3 at 9:27
add a comment |
Your image has three channels. Only one channel is in range in your third example almost-red.png.
Thus we can deduct that at most 33% of the image is in range. As there is some border it has to be even less. 33.07% sounds plausible.
If you want to check if any of the channels for each pixel is in range you have to sum up the three channels and than check for non-zero entries.
Thank you for the explanation, could you please suggest me a way to sum the three channels?
– Aezys
Jan 3 at 9:17
summed = np.sum(output, axis=2)
should do the trick. Do it before counting the total pixels.
– Mailerdaimon
Jan 3 at 9:19
Awesome, it worked! Thank you a lot
– Aezys
Jan 3 at 9:27
add a comment |
Your image has three channels. Only one channel is in range in your third example almost-red.png.
Thus we can deduct that at most 33% of the image is in range. As there is some border it has to be even less. 33.07% sounds plausible.
If you want to check if any of the channels for each pixel is in range you have to sum up the three channels and than check for non-zero entries.
Your image has three channels. Only one channel is in range in your third example almost-red.png.
Thus we can deduct that at most 33% of the image is in range. As there is some border it has to be even less. 33.07% sounds plausible.
If you want to check if any of the channels for each pixel is in range you have to sum up the three channels and than check for non-zero entries.
answered Jan 3 at 9:14


MailerdaimonMailerdaimon
4,64112539
4,64112539
Thank you for the explanation, could you please suggest me a way to sum the three channels?
– Aezys
Jan 3 at 9:17
summed = np.sum(output, axis=2)
should do the trick. Do it before counting the total pixels.
– Mailerdaimon
Jan 3 at 9:19
Awesome, it worked! Thank you a lot
– Aezys
Jan 3 at 9:27
add a comment |
Thank you for the explanation, could you please suggest me a way to sum the three channels?
– Aezys
Jan 3 at 9:17
summed = np.sum(output, axis=2)
should do the trick. Do it before counting the total pixels.
– Mailerdaimon
Jan 3 at 9:19
Awesome, it worked! Thank you a lot
– Aezys
Jan 3 at 9:27
Thank you for the explanation, could you please suggest me a way to sum the three channels?
– Aezys
Jan 3 at 9:17
Thank you for the explanation, could you please suggest me a way to sum the three channels?
– Aezys
Jan 3 at 9:17
summed = np.sum(output, axis=2)
should do the trick. Do it before counting the total pixels.– Mailerdaimon
Jan 3 at 9:19
summed = np.sum(output, axis=2)
should do the trick. Do it before counting the total pixels.– Mailerdaimon
Jan 3 at 9:19
Awesome, it worked! Thank you a lot
– Aezys
Jan 3 at 9:27
Awesome, it worked! Thank you a lot
– Aezys
Jan 3 at 9:27
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54019108%2fhow-to-count-the-pixels-of-a-certain-color-with-opencv%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3k8dMLT0v f2IVkdszleavqrL