【问题标题】:Color and Texture-Based Shadow Detection基于颜色和纹理的阴影检测
【发布时间】:2015-07-12 19:53:40
【问题描述】:

我正在做一个关于视频监控中的跟踪和对象分类的项目,我在去除前景对象的阴影方面遇到了一些困难。 问题是我不能只使用我想要的任何方法,我必须使用本文中描述的相同方法Shadow removal with blob based morphological reconstruction

在文章中,他们使用了混合阴影去除方法——基于 RGB 颜色的检测和基于纹理的检测。基于颜色和纹理的过程并行使用,然后是结合两者结果的断言过程。

所以我想获得一些关于阴影去除 Matlab 代码的帮助。

到目前为止我的代码

function Tracking_Objects()

% Create System objects used for reading video, detecting moving objects,
% and displaying the results.
obj = setupSystemObjects();

tracks = initializeTracks(); % Create an empty array of tracks.

nextId = 1; % ID of the next track

% Detect moving objects, and track them across video frames.
while ~isDone(obj.reader)
    frame = readFrame();
    [centroids, bboxes, mask] = detectObjects(frame);
    predictNewLocationsOfTracks();
    [assignments, unassignedTracks, unassignedDetections] = ...
        detectionToTrackAssignment();

    updateAssignedTracks();
    updateUnassignedTracks();
    deleteLostTracks();
    createNewTracks();

    displayTrackingResults();
end


%% Create System Objects

    function obj = setupSystemObjects()
        % Initialize Video I/O
        % Create objects for reading a video from a file, drawing the tracked
        % objects in each frame, and playing the video.

        % Create a video file reader.
        obj.reader = vision.VideoFileReader('input.avi');

        % Create two video players, one to display the video,
        % and one to display the foreground mask.
        obj.videoPlayer = vision.VideoPlayer('Position', [10, 250, 700, 400]);
        obj.maskPlayer = vision.VideoPlayer('Position', [720, 250, 700, 400]);


        obj.detector = vision.ForegroundDetector('NumGaussians', 3, ...
            'NumTrainingFrames', 40, 'MinimumBackgroundRatio', 0.7);


        obj.blobAnalyser = vision.BlobAnalysis('BoundingBoxOutputPort', true, ...
            'AreaOutputPort', true, 'CentroidOutputPort', true, ...
            'MinimumBlobArea', 75);
    end

%% Initialize Tracks

     function tracks = initializeTracks()
        % create an empty array of tracks
        tracks = struct(...
            'id', {}, ...
            'bbox', {}, ...
            'kalmanFilter', {}, ...
            'age', {}, ...
            'totalVisibleCount', {}, ...
            'consecutiveInvisibleCount', {});
    end

%% Read a Video Frame
% Read the next video frame from the video file.
    function frame = readFrame()
        frame = obj.reader.step();
    end

%% Detect Objects

    function [centroids, bboxes, mask] = detectObjects(frame)

        % Detect foreground.
        mask = obj.detector.step(frame);

        % Apply morphological operations to remove noise and fill in holes.
        mask = imopen(mask, strel('rectangle', [3,3]));
        mask = imclose(mask, strel('rectangle', [15, 15])); 
        mask = imfill(mask, 'holes');

        % Perform blob analysis to find connected components.
        [~, centroids, bboxes] = obj.blobAnalyser.step(mask);
    end

%% Predict New Locations of Existing Tracks

    function predictNewLocationsOfTracks()
        for i = 1:length(tracks)
            bbox = tracks(i).bbox;

            % Predict the current location of the track.
            predictedCentroid = predict(tracks(i).kalmanFilter);

            % Shift the bounding box so that its center is at 
            % the predicted location.
            predictedCentroid = int32(predictedCentroid) - bbox(3:4) / 2;
            tracks(i).bbox = [predictedCentroid, bbox(3:4)];
        end
    end

%% Assign Detections to Tracks

    function [assignments, unassignedTracks, unassignedDetections] = ...
            detectionToTrackAssignment()

        nTracks = length(tracks);
        nDetections = size(centroids, 1);

        % Compute the cost of assigning each detection to each track.
        cost = zeros(nTracks, nDetections);
        for i = 1:nTracks
            cost(i, :) = distance(tracks(i).kalmanFilter, centroids);
        end

        % Solve the assignment problem.
        costOfNonAssignment = 20;
        [assignments, unassignedTracks, unassignedDetections] = ...
            assignDetectionsToTracks(cost, costOfNonAssignment);
    end

%% Update Assigned Tracks

    function updateAssignedTracks()
        numAssignedTracks = size(assignments, 1);
        for i = 1:numAssignedTracks
            trackIdx = assignments(i, 1);
            detectionIdx = assignments(i, 2);
            centroid = centroids(detectionIdx, :);
            bbox = bboxes(detectionIdx, :);

            % Correct the estimate of the object's location
            % using the new detection.
            correct(tracks(trackIdx).kalmanFilter, centroid);

            % Replace predicted bounding box with detected
            % bounding box.
            tracks(trackIdx).bbox = bbox;

            % Update track's age.
            tracks(trackIdx).age = tracks(trackIdx).age + 1;

            % Update visibility.
            tracks(trackIdx).totalVisibleCount = ...
                tracks(trackIdx).totalVisibleCount + 1;
            tracks(trackIdx).consecutiveInvisibleCount = 0;
        end
    end

%% Update Unassigned Tracks
% Mark each unassigned track as invisible, and increase its age by 1.

    function updateUnassignedTracks()
        for i = 1:length(unassignedTracks)
            ind = unassignedTracks(i);
            tracks(ind).age = tracks(ind).age + 1;
            tracks(ind).consecutiveInvisibleCount = ...
                tracks(ind).consecutiveInvisibleCount + 1;
        end
    end

%% Delete Lost Tracks

    function deleteLostTracks()
        if isempty(tracks)
            return;
        end

        invisibleForTooLong = 20;
        ageThreshold = 8;

        % Compute the fraction of the track's age for which it was visible.
        ages = [tracks(:).age];
        totalVisibleCounts = [tracks(:).totalVisibleCount];
        visibility = totalVisibleCounts ./ ages;

        % Find the indices of 'lost' tracks.
        lostInds = (ages < ageThreshold & visibility < 0.6) | ...
            [tracks(:).consecutiveInvisibleCount] >= invisibleForTooLong;

        % Delete lost tracks.
        tracks = tracks(~lostInds);
    end

%% Create New Tracks

    function createNewTracks()
        centroids = centroids(unassignedDetections, :);
        bboxes = bboxes(unassignedDetections, :);

        for i = 1:size(centroids, 1)

            centroid = centroids(i,:);
            bbox = bboxes(i, :);

            % Create a Kalman filter object.
            kalmanFilter = configureKalmanFilter('ConstantVelocity', ...
                centroid, [200, 50], [100, 25], 100);

            % Create a new track.
            newTrack = struct(...
                'id', nextId, ...
                'bbox', bbox, ...
                'kalmanFilter', kalmanFilter, ...
                'age', 1, ...
                'totalVisibleCount', 1, ...
                'consecutiveInvisibleCount', 0);

            % Add it to the array of tracks.
            tracks(end + 1) = newTrack;

            % Increment the next id.
            nextId = nextId + 1;
        end
    end

%% Display Tracking Results
% The |displayTrackingResults| function draws a bounding box and label ID 
% for each track on the video frame and the foreground mask. It then 
% displays the frame and the mask in their respective video players. 

    function displayTrackingResults()
        % Convert the frame and the mask to uint8 RGB.
        frame = im2uint8(frame);
        mask = uint8(repmat(mask, [1, 1, 3])) .* 255;

        minVisibleCount = 8;
        if ~isempty(tracks)

            % Noisy detections tend to result in short-lived tracks.
            % Only display tracks that have been visible for more than 
            % a minimum number of frames.
            reliableTrackInds = ...
                [tracks(:).totalVisibleCount] > minVisibleCount;
            reliableTracks = tracks(reliableTrackInds);

            % Display the objects. If an object has not been detected
            % in this frame, display its predicted bounding box.
            if ~isempty(reliableTracks)
                % Get bounding boxes.
                bboxes = cat(1, reliableTracks.bbox);

                % Get ids.
                ids = int32([reliableTracks(:).id]);

                % Create labels for objects indicating the ones for 
                % which we display the predicted rather than the actual 
                % location.
                labels = cellstr(int2str(ids'));
                predictedTrackInds = ...
                    [reliableTracks(:).consecutiveInvisibleCount] > 0;
                isPredicted = cell(size(labels));
                isPredicted(predictedTrackInds) = {' predicted'};
                labels = strcat(labels, isPredicted);

                % Draw the objects on the frame.
                frame = insertObjectAnnotation(frame, 'rectangle', ...
                    bboxes, labels);

                % Draw the objects on the mask.
                mask = insertObjectAnnotation(mask, 'rectangle', ...
                    bboxes, labels);
            end
        end

        % Display the mask and the frame.
        obj.maskPlayer.step(mask);        
        obj.videoPlayer.step(frame);
    end

end

【问题讨论】:

  • 您能具体说明您的问题吗?
  • 我已经编辑了这个问题,也许现在会更清楚。问题是我的代码必须基于我所附的文章,我不希望人们阅读这篇文章,所以想总结一下。
  • 请不要玷污你的问题,因为这不尊重其他人试图回答它所付出的努力。
  • 不要以这种方式编辑问题。我不明白你的目的。这个社区是为了每个人的利益。

标签: matlab image-processing computer-vision video-processing matlab-cvst


【解决方案1】:

看来您需要使用代码修改detectObjects 函数以消除阴影。目前,它所做的只是从背景减法 (vision.ForegroundDetector) 中获取前景蒙版,去除一些噪音并使用形态学填充小间隙,然后找到连接的组件,也就是“斑点”。通常,斑点确实包含阴影。

如果您的阴影去除算法在单个帧上运行,那么这就是它的代码所在。

【讨论】:

    【解决方案2】:

    我认为您的问题在于您的对象检测。您的代码使用imopenimclose。但我认为你想使用imdilateimerode

    %% Detect Objects
    
    function [centroids, bboxes, mask] = detectObjects(frame)
    
        % Detect foreground.
        mask = obj.detector.step(frame);
    
        % Apply morphological operations to remove noise and fill in holes.
    
        %this makes the white space smaller to remove small dots/noise
        mask = imerode(mask, strel('rectangle', [3,3]));
    
        %this makes the white regions larger to restore the original size
        mask = imclose(mask, strel('rectangle', [15, 15])); 
    
        mask = imfill(mask, 'holes');
    
        % Perform blob analysis to find connected components.
        [~, centroids, bboxes] = obj.blobAnalyser.step(mask);
    end
    

    我更改了您的imopenimclose,您可能还需要更改您的结构元素。如果您查看matlab documentation imopen 与腐蚀后跟膨胀相同,或者imopened = imdilate(imerode(im,se))); Imclose 是膨胀后腐蚀或imcloseed = imerode(imdilate(im,se))

    论文使用先腐蚀后膨胀(imopen 操作)。这就是我在代码中输入的内容。如果您想对两个操作使用相同的结构元素,您可以更改

        %this makes the white space smaller to remove small dots/noise
        mask = imerode(mask, strel('rectangle', [3,3]));
    
        %this makes the white regions larger to restore the original size
        mask = imclose(mask, strel('rectangle', [15, 15])); 
    

        mask = imopen(mask,strel('rectangle',[15 15]));
    

    由于您没有包含您的图片,所以我无法尝试,但我认为在您使用 strel 功能后它应该可以工作

    【讨论】:

    • 谢谢,我什至没有注意到那个错误。但是我的问题是别的,也许我不够清楚。我想在我的代码中添加一个阴影去除算法。我不能包含图片,因为我是新来的,您需要声誉才能包含图片。
    猜你喜欢
    • 1970-01-01
    • 2018-09-10
    • 2011-10-04
    • 2020-09-19
    • 1970-01-01
    • 2021-01-01
    • 2012-09-18
    • 1970-01-01
    • 2011-12-19
    相关资源
    最近更新 更多