Remove pixel whose value is below given threshold
古いコメントを表示
Hello, how can i remove pixels from an image whose values are below/above a given threshold value? As far as I know images in MATLAB are rectangular. So is this even possible? How most efficiently can this be achieved, or something close to this?
Say I have an image A, my threshold is 4. So i want ot remove A(i,j) <= 4 .
I looked at this post, but i think the title is a bit misleading, they are more like changing the value of the pixel. I want total removal/deletion if possible. So in the end i expect the resulting/output image to have different dimensions from the original input. So its more like customized croping.
Thank you very much.
5 件のコメント
How in your mind would common image manipulation routines even handle a non-rectangular image?
What would it mean to sum the rows of an image in which pixels are "missing"? If the missing pixels are not to be included in the sum, why not just set the pixels to zero?
What does an image with deleted pixels look like when displayed? Would the missing pixels be black? If so, why again is it insufficient simply to set the pixels to zero or NaN?
If your goal is to actually remove the elements (i.e. for each removed pixel, the image has one fewer element), then the question becomes how should the image be reshaped? Is it still necessary to preserve local image content? Consider the examples:
% get a basic test image
A = imread('cameraman.tif');
A = A*0.7 + 0.3*255;
s = size(A);
imshow(A)
% this image should be easy enough to deal with. this is basically just cropping
B1 = zeros(s,'uint8');
B1(50:end-50,50:end-50) = A(50:end-50,50:end-50);
imshow(B1)
% but how would this image be reshaped?
B2 = A;
B2(100:end-100,100:end-100) = 0;
nnz(B2~=0) % pixels that are to be preserved
imshow(B2)
% what about this?
B3 = A;
idx = randi([1 prod(s)],1,500);
B3(idx) = 0;
nnz(B3~=0) % pixels that are to be preserved
imshow(B3)
Note the counts of the good pixels. The original image is 255x255 (65025px). Even if image content is abandoned and the output of B2 is just reshaped into a rectangle, there are only a handful of rectangles that contain 62287px.
>> factor2(62287)
ans =
1 62287
199 313
313 199
62287 1
Similarly with B3:
>> factor2(65038)
ans =
1 65038
2 32519
31 2098
62 1049
1049 62
2098 31
32519 2
65038 1
Would any of those geometries be acceptable? If the masked regions are the consequence of some random or natural process, there's nothing stopping you from having a prime number of pixels left in your image.
MatlabEnthusiast
2022 年 3 月 2 日
If some sort of best-fit box approach were implemented, would it be acceptable for some of the bad pixels to be left if it would allow for local content preservation? On the other hand, would it be acceptable to discard some good pixels?
Would it be better to keep the image rigid, or would some amount of shearing be acceptable? Using reshape() tends to progressively displace content, but a vectorwise approach may be less destructive:
% get a basic test image
A = imread('cameraman.tif');
A = A*0.7 + 0.3*255;
s = size(A);
% same noisy image
B3 = A;
idx = randi([1 prod(s)],1,1000);
B3(idx) = 0;
imshow(B3)
C = zeros(s,'uint8');
for col = 1:s(2)
thisvec = B3(:,col);
thisvec = thisvec(thisvec~=0); % select only good pixels
C(1:numel(thisvec),col) = thisvec;
end
imshow(C)
At which point, you could choose to crop off as much of the bottom of the image as you need (again, the remark about whether it's okay to leave bad pixels or discard good pixels). Similar can obviously be done on rows.
Regarding a fit-box and preserving some bad pixels:
% get a basic test image
A = imread('cameraman.tif');
A = A*0.7 + 0.3*255;
s = size(A);
% generate a noisy image
% this uses MIMT tools, so ignore that.
BG = zeros(s,'uint8');
alph = radgrad(s,[0.5 0.5],0.5,[255;0],'cosine','uint8') + 100;
FG = cat(3,A,alph);
B = imblend(FG,BG,1,'normal',1,'dissolvezf');
B = B(:,:,1);
% obviously i can't use MIMT here, so i just attached B
% B = imread('noisyb.png');
imshow(B)
% try to find some sort of mask that describes the least-noisy region
mask = B~=0;
mask = imopen(mask,strel('disk',20,0));
imshow(mask)
% find the extents of the blob and crop the image to it
S = regionprops(mask,'boundingbox');
C = imcrop(B,S.BoundingBox);
imshow(C)
採用された回答
その他の回答 (3 件)
DGM
2022 年 3 月 2 日
0 投票
If you're trying to automatically crop borders off an image, you might be able to use the comments from ImageAnalyst and myself on this thread:
I give a comparison of a few different methods.
Alternatively, this is an extension from my comment above. If image content preservation is not important, the images can be reshaped. I'm not sure why this would be necessary though. In most cases, I assume that it would suffice to simply vectorize the image instead.
A = imread('cameraman.tif');
A = A*0.7 + 0.3*255;
s = size(A);
% central black region
B2 = A;
B2(100:end-100,100:end-100) = 0;
% find bad pixels and reshape to the most-square geometry possible
mask = B2~=0;
goodpx = nnz(mask);
npf = factor2(goodpx,'ordered',false);
B2r = reshape(B2(mask),npf(end,:));
imshow(B2r)
% random pixel locations
B3 = A;
idx = randi([1 prod(s)],1,500);
B3(idx) = 0;
% find bad pixels and reshape to the most-square geometry possible
mask = B3~=0;
goodpx = nnz(mask);
npf = factor2(goodpx,'ordered',false);
B3r = reshape(B3(mask),npf(end,:));
imshow(B3r)
Attached is the tool used for finding candidate geometries.
Here's another silly answer based on my last two comments. In this case, we're accepting minor local distortion in order to sift the pixels toward the least-noisy region in order facilitate subsequent cropping. This really would only work well in cases where the noise density is largely non-convex. In the example with a square hole in the middle of the image, the distortion would be significantly increased.
% % get a basic test image
% A = imread('cameraman.tif');
% A = A*0.7 + 0.3*255;
% s = size(A);
%
% % generate a noisy image
% % this uses MIMT tools, so ignore that.
% BG = zeros(s,'uint8');
% alph = radgrad(s,[0.5 0.5],0.5,[255;0],'cosine','uint8') + 100;
% FG = cat(3,A,alph);
% B = imblend(FG,BG,1,'normal',1,'dissolvezf');
% B = B(:,:,1);
% obviously i can't use MIMT here, so i just attached B
B = imread('noisyb.png');
s = size(B);
imshow(B)
% create a mask that describes the least-noisy region
mask = B~=0;
mask = imopen(mask,strel('disk',20,0));
mask = bwareafilt(mask,1);
imshow(mask)
% find center
S = regionprops(mask,'centroid');
cen = round(S.Centroid); % center of good region
% sift radially toward the center
for d = 1:4
for c = 2:s(1)-1
linemask = logical(xwline(s,[cen(1) 1],[cen(2) c])); % create a mask
sampvec = B(linemask); % sample B along that line
outvec = zeros(size(sampvec),'uint8'); % allocate
sampvec = sampvec(sampvec~=0); % only get good pixels
outvec(end-numel(sampvec)+1:end) = sampvec; % sift vector
B(linemask) = outvec; % replace
end
B = rot90(B);
s = size(B);
end
imshow(B)
At this point, it's up to the user to decide whether to crop off all the bad pixels (discarding some good pixels) or do crop only bad pixels (keeping some bad pixels).
This is probably a hilariously inefficient way to do this, but consider it a proof of concept.
カテゴリ
ヘルプ センター および File Exchange で Image Processing Toolbox についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!













