Dimming an Image with a new max?

조회 수: 5(최근 30일)
Ray 2014년 10월 20일
편집: DGM 2022년 12월 2일
function [dimmed] = dimImage(orig, new_max)
Write a function called dim Image which takes two inputs: a 3 D matrix representing a color image , and a new maximum brightness . This function should return a 3 D matrix with its value range reduced to fit between 0 and the new maximum brightness ( new_max )
I feel as though I am doing this properly as my code looks like:
dimmed = min(orig, new_max-1)
But when I run a sample image, it is not dimmed, but there is another alteration. Can someone give me direction?


Image Analyst
Image Analyst 2014년 10월 21일
Try this:
function [dimmed] = dimImage(grayImage, new_max)
% Clip to the value they specify
pixelsToClip = grayImage > new_max;
grayImage(pixelsToClip) = new_max;
dimmed = grayImage;
A full blown demo is attached below the following image, which it will create.

DGM 2022년 12월 2일
편집: DGM 2022년 12월 2일
The intent seems terribly obvious to me. OP wants an image "reduced to a new maximum", and data truncation is specifically described as an example of what they don't want because it "is not dimmed" but instead affected in other negative ways.
This is a basic levels adjustment. It can be done with imadjust() or basic arithmetic to effect linear rescaling. My goal here is to demonstrate the difference in effect on the image, not to write a function demo for a homework assignment.
% read an image (RGB,uint8)
inpict = imread('peppers.png');
% new output white value
wvout = 0.7;
% truncate image to fit within [0 wvout]*255
% this is what both prior examples do
outpictnonlin = min(inpict,wvout*255);
% linearly rescale image to fit within [0 wvout]*255
outpictlin = imadjust(inpict,[0 1],[0 wvout]);
% compare
imshow([inpict; outpictnonlin; outpictlin])
Obviously, truncation is conspicuously destructive to image regions which are above the threshold. Avoid it unless your goal is to discard information. Image regions below the threshold aren't altered.
The rescaled image is dimmer overall. Brightness and global contrast are reduced, but details are preserved.
Bear in mind that this rescaling is done with respect to the nominal data range, and is independent of the actual extrema of the input image. In other words, the new global maximum would only be the specified value if it were maximized (e.g. 255 for uint8) prior to the adjustment. This is the typical behavior for simple image adjustment tools. If the goal were to scale the image such that its original extrema correspond to [0 wvout], then the second argument to imadjust() should be those extrema, represented in unit-scale. One can use stretchlim() to obtain those values.
Now that that's done, we're back to the assignment. There are multiple copies of this assignment that have been posted. While it's clear that it's a basic scaling, I still haven't found one that unambiguously describes the intended behavior regarding the input limits. Since nobody can communicate what they want, nobody will get what they want. Here is a collage of code that should be sufficient to construct all that I assume might be required.
% an image
inpict = imread('peppers.png');
% cast to floating point
% scale to some standard scale (i.e. [0 1])
% that way the code works regardless of input class
inpict = im2double(inpict);
% it's up to you to define levels and choose _how_ and _where_ they get defined
inrange = [0 1];
outrange = [0 1];
% cast to floating point
% scale to a standard scale (i.e. [0 1])
% that way the code works regardless of input class
inpict = im2double(inpict);
outpict = (inpict-inrange(1))./range(inrange); % adjust input levels
outpict = outpict.*range(outrange) + outrange(1); % adjust output levels
% boldly presume that the output should always be uint8
outpict = im2uint8(outpict);
If the goal is to scale the input to the original extrema as discussed, then inrange needs to be calculated somehow. For a two-term result, you could do:
% you could take the naive approach
inrange = [min(inpict(:)) max(inpict(:))]; % find extrema
% or if you want to emulate stretchlim(), it gets more complicated.
For a 6-term result, you could do the following, but it would obviously require changes to the math above.
% if you want the input levels to be independent per channel:
inrange = permute([min(inpict,[],[1 2]) max(inpict,[],[1 2])],[2 3 1]);

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by