For a university assignment I have to take an image of size 512x512 and then apply an effect to particular blocks of the image, as displayed in the image below.
I have managed to achieve this by accessing particular regions of the image using indexing, like this:
w1_region = [DCTImage(1:imageSizeQuarter, imageSizeQuarter+1:imageSizeHalf)];
This is repeated for w2 and w3. These regions are all of size 128x128 and need to be written back into the original image.
However now what I need to do is overwrite the blocks of the original image with the edited blocks, so that I have a full image with 3 blocks w1, w2, w3 that have been modified.
How can I go about overwriting the matrix that defines the original image with the modified blocks? Is there a way that I can effectively say "Overwrite the values held in the matrix starting at X"?
I feel like there is some kind of matrix operation that would allow me to do this but I'm not entirely sure which.
You can use for example:
BlockFunc = #(block_struct) YourFunction(block_struct);
block_size = [128 128];
block_edges = blockproc(file_name,block_size,BlockFunc);
You should just create a function with Name of YourFunction. The input of this function is block_struct and you can access to your block position and its data.
Moreover you can use global variable to handle between YourFunction and your main script.
Related
I am trying using MATLAB activecontour code to segment the region. the example was used grayscale image while i am using binary image. it turn out ok when i run the code by calling the binary image. however, when i combined the code, nothing happen. it skips the iteration part, and generate the sama binary image. for your reference, below is my code.
%% snake
figure
x = imread('1.jpg');
threshold = 160;
I = rgb2gray(x);
I = Igray>threshold;
imshow (I);
I = imresize(I,.5);
imshow(I)
title('Original Image')
mask = zeros(size(I));
mask(25:end-25,25:end-25) = 1;
imshow(mask)
title('Initial Contour Location')
bw = activecontour(I,mask,1300);
imshow(bw)
title('Segmented Image, 300 Iterations')
no process happen starting from snake's code. it eventually only generate binary image. I hope someone could try run this and help me to find my mistake. Thank you in advance
Matlab's activecontour function uses the Chan–Vese (active contours without edges) method by default, like Cris said. The implementation "uses the Sparse-Field level-set method, similar to the method described in [3]", citing Whitaker, "A level-set approach to 3d reconstruction from range data". (Besides Chan–Vese, activecontour has an optional method arg that can be set to 'edge' to use an alternative "edge-based model" based on the (older) geodesic active contours method of Caselles, Kimmel, and Sapiro.)
The Chan–Vese method segments a grayscale image by looking for a binary image equal to "c1" inside the contour and "c2" outside the contour that both has a smooth contour and is a good approximation to the original image. The method optimizes c1, c2, and the shape of the contour, beginning from some initial contour and evolving it by an iterative process.
If you'll excuse a self-citation, you can find an article, open source C code, and online demo about Chan–Vese on the IPOL journal at http://www.ipol.im/pub/art/2012/g-cv/, which you may find helpful.
So why is it not working in your case? Some thoughts:
In your use, since the input image is already binary, it is clearly tempting for the method to simply set c1=0, c2=1, and the contour to the edges of the input, so "nothing happens". Try setting the optional 'SmoothFactor' arg (possibly to a large value) to force the method to look for a smoother contour.
It's conceivably a datatype problem, since image I is passed as a logical array to activecontour, but normally the function takes a numeric array. Try casting I to a double array before passing.
Is there a way if I want to apply medfilt2 function to the specific pixel locations rather than the whole image? The pixel locations can be represented using a binary image called IMask.
The lazy method is to just apply medfilt2 on the whole image and then copy the specific locations. E.g.
A = magic(10); % sample matrix
IMask = logical(randi([0 1],10)); % sample locations
B = medfilt2(A);
A(IMask) = B(IMask);
Not very elegant, but will do the job unless your matrix is gigantic and IMask is mostly false.
I do not see the point but if you define the matrix you are passing to medfilt2 is a subset of your image that you want being processed but you have to take care of the padding (zeros/symmetric/etc values at the boundaries).
Afterwards, you just have to replace the processed matrix within the image at the right position.
I have a segmented image. I wish to extract the middle pixel(s) of each segmentation. The goal is to extract the mean color from the middle pixel.
The following diagram illustrates what I mean by 'middle pixel':
The alternative middle pixels are also acceptable.
What algorithms/functions are available in Matlab to achieve something similar to this? Thanks.
If I'm understanding what you want correctly, you're looking for the centroid. MATLAB has the regionprops function which measures the properties of separate binary objects as long as the objects.
You can use the Centroid property. Assuming your image is stored in im and is binary, something like this will do:
out = regionprops(im, 'Centroid');
The output will be a structure array of N elements where N corresponds to the total number of objects found in the image. To access the ith object's centroid, simply do:
cen = out(i).Centroid;
If you wish to collect all centroids and place them perhaps in a N x 2 numeric array, something like this would work:
out = reshape([out.Centroid], 2, []).';
Each row would be the centroid of an object found in the image. Take note that an object is considered to be a blob of white pixels that are connected to each other.
I am struggling to find a good contour detection function that would count the number of contour in bw images that I have processed using some previous tools. As you can see, my profile picture is an example of such images,
,
In this image, ideally, I wish to have a function which counts four closed contour.
I don't mind if it also detects the really tiny contours in between, or the entire shape itself as extra contours. As long as it counts the medium sized ones, I can fix the rest by applying area threshold. My problem is that any function I have tried detects only one contour - the entire shape, as it cannot separate it to the su-conours which are connected to one another.
Any suggestions?
Here is my shot at this, although your question might get closed because it's off-topic, too broad or a possible duplicate. Anyhow I propose another way to count the number of contours. You could also do it using bwboundaries as was demonstrated in the link provided by #knedlsepp in the possible duplicate. Just for the sake of it here is another way.
The idea is to apply a morphological closure of your image and actually count the number of enclosed surfaces instead instead of contours. That might end up being the same thing but I think it's easier to visualize surfaces.
Since the shapes in your image look like circle (kind of...) the structuring element used to close the image is a disk. The size (here 5) is up to you but for the image you provided its fine. After that, use regionprops to locate image regions (here the blobs) and count them, which comes back to counting contours I guess. You can provide the Area parameter to filter out shapes based on their area. Here I ask the function to provide centroids to plot them.
Whole code:
clear
clc
close all
%// Read, threshold and clean up the image
Im = im2bw(imread('ImContour.png'));
Im = imclearborder(Im);
%// Apply disk structuring element to morphologically close the image.
%// Play around with the size to alter the output.
se = strel('disk',5);
Im_closed = imclose(Im,se);
%// Find centroids of circle-ish shapes. Youcan also get the area to filter
%// out those you don't want.
S = regionprops(~Im_closed,'Centroid','Area');
%// remove the outer border of the image (1st output of regioprops).
S(1) = [];
%// Make array with centroids and show them.
Centro = vertcat(S.Centroid);
imshow(Im)
hold on
scatter(Centro(:,1),Centro(:,2),40,'filled')
And the output:
So as you see the algorithm detected 5 regions, but try playing a bit with the parameters and you will see which ones to change to get the desired output of 4.
Have fun!
I have an image that was read in using the imread function. My goal is to collect pairs of pixels in an image in MATLAB. Specifically, I have read a paper, and I am trying to recreate the following scenario:
First, the original image is grouped into pairs of pixel values. A pair consists of two neighboring pixel values or two with a small difference value. The pairing could be done horizontally by pairing the pixels on the same row and consecutive columns, or vertically, or by a key-based specific pattern. The pairing could be through all pixels of the image or just a portion of it.
I am looking to recreate the horizontal pairing scenario. I'm not quite sure how I would do this in MATLAB.
Assuming your image is grayscale, we can easily generate a 2D grid of co-ordinates using ndgrid. We can use these to create one grid, then shift the horizontal co-ordinates to the right to make another grid and then use sub2ind to convert the 2D grid into linear indices. We can finally use these linear indices to create our pixel pairings that you have described in your comments (you should really add that to your post BTW). What's important is that you need to skip over every other column in a row to ensure unique pixel pairings.
I'm also going to assume that your image is grayscale. If we go to colour, this will be slightly more complicated, and I'll leave that to you as a learning exercise. Therefore, assuming your image was read in through imread and is stored in im, do something like this:
[rows,cols] = size(im);
[X,Y] = ndgrid(1:rows,1:2:cols);
ind = sub2ind(size(im), X, Y);
ind_shift = sub2ind(size(im), X, Y+1);
pixels1 = im(ind);
pixels2 = im(ind_shift);
pixels = [pixels1(:) pixels2(:)];
pixels will be a 2D array, where each row gives you the pixel intensities of a particular pairing in the image. Bear in mind that I processed each row independently. As such, as soon as we are done with one row, we simply move on to the next row and continue the procedure. This also assumes that your image has an even number of columns. Should it not, you have a decision to make. You need to either pad the image with one column at the end, and this column can be anything you want, or you can remove this column from the image before processing. If you want to fill in this column, you can either make it all zeroes, or perhaps replicate the last column and place this beside the last column in the original image. Therefore, an appropriate pre-processing step may look something like this:
if mod(cols,2) ~= 0
im = im(:,1:end-1);
end
The above code simply removes the last column in the image if the number of columns is odd. Once you run through this code, you can run the first bit of code that I had above.
Good luck!