Use Parfor on a greenscreen picture
4 次查看(过去 30 天)
显示 更早的评论
I have this piece of code, which compares the pixels of a picture with a greenscreen background. If a pixel with a higher green value than the value of the threshold is found, the pixel has to be replaced with a pixel of another picture
function [outPic] = thresholdFilter(green_pic,background, threshold)
[m,n,p] = size(green_pic);
outPic = green_pic;
tic
for i = 1:m
for k = 1:n
if green_pic(i,k,2) >= threshold;
outPic(i,k,1) = background(i,k,1);
outPic(i,k,2) = background(i,k,2);
outPic(i,k,3) = background(i,k,3);
end
end
end
toc
end
Now, i'm trying to reduce the execution time by using parfor. However, when i display the picture, the background is still unedited and it only shows the greenscreen picture.
function [outPic] = thresholdFilter2_0(green_pic,background, threshold)
[m,n,p] = size(green_pic);
outPic = green_pic;
tic
parfor i = 1:m
pic = green_pic;
for k = 1:n
if green_pic(i,k,2) >= threshold;
pic(i,k,1) = background(i,k,1);
pic(i,k,2) = background(i,k,2);
pic(i,k,3) = background(i,k,3);
end
end
outPic = pic(i,:,:);
end
toc
end
How can i get the same results as the first example by using Parfor ?
采纳的回答
Edric Ellis
2021-4-30
The comment on your question by @Daniel Pollard is probably the most productive way forward. But to answer your parfor query specifically - the problem here is that inside the parfor loop, outPic is being treated as a "loop temporary variable". To make a value available after the parfor loop, it has to be either a sliced or a reduction output.
Your original for loop is very close to working as a parfor loop. The only tweak necessary is to make a single assignment into outPic to satisfy the constraints for a sliced output variable.
% Dummy data:
green_pic = rand(10,10,3);
background = rand(10,10,3);
threshold = 0.5;
% Very slightly modified code:
[m,n,p] = size(green_pic);
outPic = green_pic;
parfor i = 1:m
for k = 1:n
if green_pic(i,k,2) >= threshold;
% Make a single assignment into outPic so that
% it can be "sliced"
outPic(i,k,:) = background(i,k,:);
end
end
end
disp('Success!');
Of course, the vectorised way to do this is as follows:
% Dummy inputs
green_pic = rand(10,10,3);
background = rand(10,10,3);
threshold = 0.5;
[m,n,p] = size(green_pic);
% Starting point for outPic
outPic = green_pic;
% Find all locations where threshold is exceeded. exceedsThreshold will be
% m-by-n logical array.
exceedsThreshold = green_pic(:,:,2) > threshold;
% We want to copy all planes of "background" into "outPic", so we need
% to duplicate "exceedsThreshold" into the third dimension
exceedsThreshold = repmat(exceedsThreshold, 1, 1, p);
% Copy appropriate pieces of background
outPic(exceedsThreshold) = background(exceedsThreshold);
2 个评论
Edric Ellis
2021-5-4
I'm not really surprised that parfor is slower than for in this case. There are overheads to running in parfor - specifically you have to transfer the data to different processes to operate on it, and then transfer it back. In this case, the work you're doing is much less time-consuming than the transfer. I suspect you will have more luck trying to use the vectorised approach.
更多回答(0 个)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Matrix Indexing 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!