It sounds like the goal is to set the pixels inside the mask to 1 and those outside to 0. Here are a few adjustments that can be made to achieve this:
1. Remove the line msk = msk - mean(msk(:)); as it drives the pixels towards normalized values rather than exactly 1 or 0.
2. Ensure that the means are calculated only for the relevant pixels by changing the following lines:
mns = mean(extractdata(zp(msk <= 0)));
mxs = mean(extractdata(zp(msk > 0)));
Update the equations for mxs(i+1) and mns(i+1) accordingly.
3. It's preferable for the cost function to be convex with a unique minimum. The minimum should correspond to the 2D matrix elements matching the desired image msk. An example cost function is:
cost1 = sum((x - msk).^2, 1:2);
This cost function becomes zero when the current image x matches the desired image msk elementwise.
Also, remember to modify the plotting line for the second figure accordingly. For x defined as an integer array going -10 to 10 (i.e. x=-10:10), the figures are as follows after 20 iterations:
I have attached the modified code for reference. For further verification, the result can be checked using fmincon. Here are some useful links for more information: