Why does `cv2.threshold` only takes grayscale image? - image

I am working on some projects related to OpenCV and came across cv2.threshold function. Why does this function only take grayscale images only? Can anybody make this clear to me?

UPDATE:
See comments on this question instead of reading it.
I agree with #Cris as he said in the comments "nobody has found it useful to implement it for color images".
There are plenty of functions to achieve the same in much concise way which depend on your use-case.
But it's still a general curiousity question from a newcomer. So one easy approach for the same would be:
def bgr_threshold(src_bgr, thresh_bgr, maxval_bgr, type_bgr):
b, g, r = cv2.split(src_bgr)
thresh_b, thresh_g, thresh_r = thresh_bgr
maxval_b, maxval_g, maxval_r = maxval_bgr
type_b, type_g, type_r = type_bgr
ret_b, thresh_img_b = cv2.threshold(b, thresh_b, maxval_b, type_b)
ret_g, thresh_img_g = cv2.threshold(g, thresh_g, maxval_g, type_g)
ret_r, thresh_img_r = cv2.threshold(r, thresh_r, maxval_r, type_r)
thresh_img_bgr = cv2.merge((thresh_img_b, thresh_img_g, thresh_img_r))
return ((ret_b, ret_g, ret_r), thresh_img_bgr)
ret, th = bgr_threshold(image, (127, )*3, (255, )*3, (cv2.THRESH_BINARY, )*3)
Although this makes it take almost 3 times slower from optimisation point of view.

Related

Is there a way to automatically align function arguments?

In RStudio is there a way to automatically align the equal signs in function arguments?
Similar to the following:
objective = obj,
eta = params$eta[i],
gamma = params$gamma[i],
max_depth = params$max_depth[i],
colsample_bytree = params$colsample_bytree[i],
colsample_bylevel = params$colsample_bylevel[i],
lambda = params$lambda[i],
alpha = params$alpha[i],
subsample = params$subsample[i])
I find this much easier to read. If it is not available in RStudio is there a different editor which has this capability?
I found a solution in the AlignAssign RStudio addin: https://github.com/seasmith/AlignAssign
Another option is {remedy}, which is also on CRAN.
That package include addins for aligning equal signs = and assignments <-, plus other addins for working with markdown documents.

Remove small objects in a mask and generate a new binary mask out of for loop

I appreciate your help;
This part of the code allows me to plot what I want but I need to assign the outcome(a binary image with >500 area objects) to a variable for further processing
Improved_label = np.zeros_like(label_image)
#props = regionprops(label_image)
for R in regionprops(label_image):
if R.area > 500:
# draw the region (I'm sure there's a more efficient way of doing it)
for c in R.coords:
Improved_label[c[0], c[1]] = 1
#Improved_labe1 = Improved_label > 1
Apparently, there is something wrong with the name "improved" at the beginning of the variable name(not sure why). but anyhow, here are two solutions for this issue. I hope this will be helpful for people with the background in Matlab:
-------------Option A--------------
label2_test = np.zeros_like(label_image)
for R in regionprops(label_image):
if R.area > 1000:
# draw the region (I'm sure there's a more efficient way of doing it)
for c in R.coords:
label2_test[c[0], c[1]] = 1
label2_test = label2_test > 0
plt.imshow(labe2_test)
----------------Option B-----------------
from skimage import morphology
labe1_improved = morphology.remove_small_objects(label_image, min_size=1000)

Terminal dashboard in golang using "termui"

I am working on drawing graphs on the terminal itself from inside a go code.I found this (https://github.com/gizak/termui) in golang. And used this(https://github.com/gizak/termui/blob/master/_example/gauge.go) to draw graph in my code.
Problem is this , as we can see in the code( https://github.com/gizak/termui/blob/master/_example/gauge.go ), they are passing g0,g1,g2,g3 all together in the end "termui.Render(g0, g1, g2, g3, g4)".
In my case I don't know how many gauges to draw before hand so I used a list to store gauge objects and then tried to pass list to render.
termui.Render(chartList...)
But it creates only one gauge.
This is how I am appending elements in the list.
for i := 0; i < 5; i++ {
g0 := termui.NewGauge()
g0.Percent = i
g0.Width = 50
g0.Height = 3
g0.BorderLabel = "Slim Gauge"
chartList = append(chartList, g0)
}
what I am getting is a gauge for i=4 only. when I am doing termui.Render(chartList...)
Am I doing something wrong?
PS - I have modified question based on the answer I got in this question.
Here is a good read on Variadic Functions
Take a look at the function signature of Render, https://github.com/gizak/termui/blob/master/render.go#L161
func Render(bs ...Bufferer) {
All you need to do is
termui.Render(chatList...)
assuming chartList is a []Bufferer
Edit
You are only seeing one because they are stacking on top of one-another. To see this add
g0.Height = 3
g0.Y = i * g0.Height // <-- add this line
g0.BorderLabel = "Slim Gauge"
From a quick review of the project, it appears there are ways for auto-arranging that have to do with creating rows (and probably columns). So you might want to explore that, or you will need to manually position your elements.

Creating Movie for each Generation of Data [duplicate]

This question already has an answer here:
How to create movies on each generation of a for loop in Matlab plot
(1 answer)
Closed 9 years ago.
I have the following code:
figure;
contour(X1,X2,f);
hold on
plot(top(1:size(top,1)), 'rx');
EDIT
figure;
for i = 1: G
contour(X1,X2,f);
hold on
plot(top(1:size(top,1)), 'rx');
end
NB: G is the maximum generation.
This is supposed to plot contours of sphere superimposed with selected individuals. In each iteration of the individuals, the best individuals is selected and these going on until the global optimum is reached. I need to show this in a movie form as shown in this below:
When you runs each stage of the iteration is indicated in the slides attached. This is what i am trying to do. Any idea please?
OK, I am just copying and pasting now, from here.
However I added FrameRate (per second) since you might want to use (or ask) it later.
writerObj = VideoWriter('Your_video.avi');
writerObj .FrameRate = 1; % 1 frames per second animation.
open(writerObj);
fig_h = figure;
for i = 1: G
contour(X1,X2,f);
hold on
plot(top(1:size(top,1)), 'rx');
frame = getframe(fig_h); % or frame = getframe; since getframe gets gcf.
writeVideo(writerObj, frame);
end
close(writerObj);
Now you will have a Your_video.avi file in your working directory.
If VideoWriter is not supported by your matlab, you could use use avifile same as mentioned in this answer (or in mathwork documentaion example here) like this:
aviobj = avifile('Your_video.avi','compression','None', 'fps', 1);
fig_h = figure;
for i = 1:G
contour(X1,X2,f);
hold on
plot(top(1:size(top,1)), 'rx');
frame = getframe(fig_h); % or frame = getframe; since getframe gets gcf.
aviobj = addframe(aviobj, frame);
end
aviobj = close(aviobj);
EDIT
A problem may occur as pointed out by this question also, which is the captured frame is a constant image. If you are running Matlab on windows, this problem may be caused by conjunction of windows in with certain graphics drivers, and may be solved as mentioned in this answer.

RGB to norm rgb transformation. Vectorizing

I'm writing a piece of code that has to transform from an RGB image to an rgb normalized space. I've got it working with a for format but it runs too slow and I need to evaluate lots of images. I'm trying to vectorize the full function in order to faster it. What I have for the moment is the following:
R = im(:,:,1);
G = im(:,:,2);
B = im(:,:,3);
r=reshape(R,[],1);
g=reshape(G,[],1);
b=reshape(B,[],1);
clear R G B;
VNormalizedRed = r(:)/(r(:)+g(:)+b(:));
VNormalizedGreen = g(:)/(r(:)+g(:)+b(:));
VNormalizedBlue = b(:)/(r(:)+g(:)+b(:));
NormalizedRed = reshape(VNormalizedRed,height,width);
NormalizedGreen = reshape(VNormalizedGreen,height,width);
NormalizedBlue = reshape(VNormalizedBlue,height,width);
The main problem is that when it arrives at VNormalizedRed = r(:)/(r(:)+g(:)+b(:)); it displays an out of memory error (wich is really strange because i just have freed three vectors of the same size). Were is the error? (solved)
Its possible to do the same process in a more efficiently way?
Edit:
After using Martin sugestions I found the reshape function was not necessary, being able to do the same with a simple code:
R = im(:,:,1);
G = im(:,:,2);
B = im(:,:,3);
NormalizedRed = R(:,:)./sqrt(R(:,:).^2+G(:,:).^2+B(:,:).^2);
NormalizedGreen = G(:,:)./sqrt(R(:,:).^2+G(:,:).^2+B(:,:).^2);
NormalizedBlue = B(:,:)./sqrt(R(:,:).^2+G(:,:).^2+B(:,:).^2);
norm(:,:,1) = NormalizedRed(:,:);
norm(:,:,2) = NormalizedGreen(:,:);
norm(:,:,3) = NormalizedBlue(:,:);
I believe you want
VNormalizedRed = r(:)./(r(:)+g(:)+b(:));
Note the dot in front of the /, which specifies an element-by-element divide. Without the dot, you're solving a system of equations -- which is likely not what you want to do. This probably also explains why you're seeing the high memory consumption.
Your entire first code can be rewritten in one vectorized line:
im_normalized = bsxfun(#rdivide, im, sum(im,3,'native'));
Your second slightly modified version as:
im_normalized = bsxfun(#rdivide, im, sqrt(sum(im.^2,3,'native')));
BTW, you should be aware of the data type used for the image, otherwise one can get unexpected results (due to integer division for example). Therefore I would convert the image to double before performing the normalization calculations:
im = im2double(im);

Resources