当前位置:首页 > 编程笔记 > 正文
已解决

图层混合算法(二)

来自网友在路上 11178117提问 提问时间:2023-09-26 08:29:08阅读次数: 117

最佳答案 问答题库1178位专家为你答疑解惑

混合后图像变亮

变亮模式(lighten)

        变亮模式跟变暗模式是相对的,它是通过混合色与基色的相关数值进行比较,选择较大的数值作为结果色。因此结果色会更亮,同时颜色也会变化。(位置互换不发生变化)

void layerblend_lightness(Mat &base,Mat &blend,Mat &dst)
{if (base.rows != blend.rows ||base.cols != blend.cols ||base.type() != blend.type())return;dst = Mat::zeros(base.rows,base.cols,base.type());for (int h = 0;h < base.rows;h ++){uchar *d1 = base.ptr<uchar>(h);uchar *d2 = blend.ptr<uchar>(h);uchar *d3 = dst.ptr<uchar>(h);for (int w = 0;w < base.cols;w ++){int cw = w * base.channels();for (int c = 0;c < base.channels();c ++)d3[cw + c] = d1[cw + c] > d2[cw + c] ? d1[cw + c] : d2[cw + c];}}
}

滤色模式(screen)

        滤色模式与正片叠底模式相对。它的计算公式是:255 - 混合色的补色 * 基色补色 / 255。得到的数据会比混合及基色更大,因此结果色会更亮。从计算公式也可以看出基色或混合色任何一项为255也就是白色,结果色数值就是255为白色。任何一项数值为0,也就是为黑色的话,结果色就跟数值不为0的一致。

void layerblend_screen(Mat &base,Mat &blend,Mat &dst)
{if (base.rows != blend.rows ||base.cols != blend.cols ||base.type() != blend.type())return;dst = Mat::zeros(base.rows,base.cols,base.type());for (int h = 0;h < base.rows;h ++){uchar *d1 = base.ptr<uchar>(h);uchar *d2 = blend.ptr<uchar>(h);uchar *d3 = dst.ptr<uchar>(h);for (int w = 0;w < base.cols;w ++){int cw = w * base.channels();for (int c = 0;c < base.channels();c ++)d3[cw + c] = 255 - (255.0f - d1[cw + c]) * (255.0f - d2[cw + c]) / 255;}}
}

颜色减淡(color light)

        颜色减淡是通过混合色及基色的各通道颜色值进行对比,减少二者的对比度使基色的变亮来反映混合色。它的计算公式:结果色 = 基色 + (混合色 * 基色) / (255 - 混合色)。混合色为黑色,结果色就等于基色,混合色为白色结果色就为白色。基色为黑色结果色就为黑色.

void layerblend_color_light(Mat &base,Mat &blend,Mat &dst)
{if (base.rows != blend.rows ||base.cols != blend.cols ||base.type() != blend.type())return;dst = Mat::zeros(base.rows,base.cols,base.type());for (int h = 0;h < base.rows;h ++){uchar *d1 = base.ptr<uchar>(h);uchar *d2 = blend.ptr<uchar>(h);uchar *d3 = dst.ptr<uchar>(h);for (int w = 0;w < base.cols;w ++){int cw = w * base.channels();for (int c = 0;c < base.channels();c ++){int res = 0;if (d2[cw + c] == 0)res = 255;elseres = d1[cw + c] + (1.0f * d1[cw + c] * d2[cw + c]) / (255.0f - d2[cw + c]);d3[cw + c] = saturate_cast<uchar>(res);}}}
}

颜色线性减淡(color linear light)

        颜色线性减淡是通过查看每个通道的颜色信息,并通过增加亮度使基色变亮以反映混合色。它的计算公式:结果色 = 基色 + 混合色,其中基色与混合色的数值大于255,系统就默认为最大值也就是255。由公式可以分析出混合色为黑色结果色就等于基色,混合色为白色结果色就为白色。基色也一样。我们颠倒混合色及基色的位置,结果色也不会变化。(位置互换不发生变化)

void layerblend_color_linear_light(Mat &base,Mat &blend,Mat &dst)
{if (base.rows != blend.rows ||base.cols != blend.cols ||base.type() != blend.type())return;dst = Mat::zeros(base.rows,base.cols,base.type());for (int h = 0;h < base.rows;h ++){uchar *d1 = base.ptr<uchar>(h);uchar *d2 = blend.ptr<uchar>(h);uchar *d3 = dst.ptr<uchar>(h);for (int w = 0;w < base.cols;w ++){int cw = w * base.channels();for (int c = 0;c < base.channels();c ++){d3[cw + c] = saturate_cast<uchar>(d1[cw + c] + d2[cw + c]);}}}
}

浅色模式

        浅色模式比较好理解:它是通过计算混合色与基色所有通道的数值总和,哪个数值大就选为结果色。因此结果色只能在混合色与基色中选择,不会产生第三种颜色。与深色模式刚好相反。

叠加模式(overlay)

        叠加模式比较特别,它是通过分析基色个通道的数值,对颜色进行正片叠加或滤色混合,结果色保留基色的明暗对比,因此结果色以基色为主导。
计算公式:
基色 < = 128:结果色 = 混合色 * 基色 / 128;基色 > 128:结果色 = 255 - (255 - 混合色)* (255 - 基色) / 128。

void layerblend_overlay(Mat &base,Mat &blend,Mat &dst)
{if (base.rows != blend.rows ||base.cols != blend.cols ||base.type() != blend.type())return;dst = Mat::zeros(base.rows,base.cols,base.type());for (int h = 0;h < base.rows;h ++){uchar *d1 = base.ptr<uchar>(h);uchar *d2 = blend.ptr<uchar>(h);uchar *d3 = dst.ptr<uchar>(h);for (int w = 0;w < base.cols;w ++){int cw = w * base.channels();for (int c = 0;c < base.channels();c ++){int res = 0;res = ((d1[cw + c]  <= 128) ? (1.0f * d2[cw + c] * d1[cw + c]  / 128):(255 - (255.0f - d2[cw + c]) * (255.0f - d1[cw + c]) / 128));d3[cw + c] = saturate_cast<uchar>(res);}}}
}

柔光模式(soft light)

        柔光模式是较为常用的模式,它是根据混合色的通道数值选择不同的公式计算混合色。数值大于128的时候,结果色就比基色稍亮;数值小于或等于128,结果色就比基色稍暗。柔光模式是以基色为主导,混合色只相应改变局部明暗。其中混合色为黑色,结果色不会为黑色,只比结果色稍暗,混合色为中性色,结果色跟基色一样。
计算公式:
混合色 <=128:结果色 = 基色 + (2 * 混合色 - 255) * (基色 - 基色 * 基色 / 255) / 255;
混合色 >128: 结果色 = 基色 + (2 * 混合色 - 255) * (Sqrt(基色/255)*255 - 基色)/255。

如果基色=混合色,则可优化为256的表smoothlight,公式变形如下:

res = x + (2x-255)*(x-x*x/255)/255;

res = x+(2x-255)*(255*sqrt(x/255)-x)/255;

void layerblend_soft_light(Mat &base,Mat &blend,Mat &dst)
{if (base.rows != blend.rows ||base.cols != blend.cols ||base.type() != blend.type())return;dst = Mat::zeros(base.rows,base.cols,base.type());for (int h = 0;h < base.rows;h ++){uchar *d1 = base.ptr<uchar>(h);uchar *d2 = blend.ptr<uchar>(h);uchar *d3 = dst.ptr<uchar>(h);for (int w = 0;w < base.cols;w ++){int cw = w * base.channels();for (int c = 0;c < base.channels();c ++){int res = 0,temp1,temp2;temp1 = ((int)((float)d1[cw + c]+((float)d2[cw + c]+(float)d2[cw + c]-255.0f)*((sqrt((float)d1[cw + c]/255.0f))*255.0f-(float)d1[cw + c])/255.0f));temp2 = ((int)((float)d1[cw + c]+((float)d2[cw + c]+(float)d2[cw + c]-255.0f)*((float)d1[cw + c]-(float)d1[cw + c]*(float)d1[cw + c]/255.0f)/255.0f));res = d2[cw + c] > 128 ? temp1 : temp2;d3[cw + c] = saturate_cast<uchar>(res);}}}
}

强光模式(strong light)

        强光模式跟叠加模式十分类似,只是在计算的时候需要通过混合色来控制,混合色的数值小于或等于128的时候,颜色会变暗;混合色的数值大于128的时候,颜色会变亮。混合色为白色,结果色就为白色;混合色为黑色,结果为黑色。混合色起到主导作用。
计算公式:
混合色 <= 128:结果色 = 混合色 * 基色 / 128;
混合色 > 128 :结果色 = 255 - (255 - 混合色) * (255 - 基色) / 128.

void layerblend_strong_light(Mat &base,Mat &blend,Mat &dst)
{if (base.rows != blend.rows ||base.cols != blend.cols ||base.type() != blend.type())return;dst = Mat::zeros(base.rows,base.cols,base.type());for (int h = 0;h < base.rows;h ++){uchar *d1 = base.ptr<uchar>(h);uchar *d2 = blend.ptr<uchar>(h);uchar *d3 = dst.ptr<uchar>(h);for (int w = 0;w < base.cols;w ++){int cw = w * base.channels();for (int c = 0;c < base.channels();c ++){int res = 0;res = d2[cw + c] <= 128.0f ? ((float)d2[cw + c] * d1[cw + c] / 128.0f):(255.0f - (255.0f - d2[cw + c]) * (255.0f - d1[cw + c]) / 128.0f);d3[cw + c] = saturate_cast<uchar>(res);}}}
}

亮光模式(hight light)

        亮光模式是通过增加或减少对比度是颜色变暗或变亮,具体取决于混合色的数值。混合色比中性灰色暗,结果色就相应的变暗,混合色比中性灰色亮,结果色就相应的变亮。有点类似颜色加深或颜色减淡。
计算公式:

A---基色;B—混合色

C=A-(255-A)*(255-2B)/2B 当混合色>128时 

C=A+[A*(2B-255)]/[255-(2B-255)

void layerblend_hight_light(Mat &base,Mat &blend,Mat &dst)
{if (base.rows != blend.rows ||base.cols != blend.cols ||base.type() != blend.type())return;dst = Mat::zeros(base.rows,base.cols,base.type());for (int h = 0;h < base.rows;h ++){uchar *d1 = base.ptr<uchar>(h);uchar *d2 = blend.ptr<uchar>(h);uchar *d3 = dst.ptr<uchar>(h);for (int w = 0;w < base.cols;w ++){int cw = w * base.channels();for (int c = 0;c < base.channels();c ++){int res = 0;if (d2[cw + c] <= 128)res = d2[cw + c] == 0 ? d1[cw + c] : (d1[cw + c] - (255.0f - d1[cw + c])*(255.0f -2.0f * d2[cw + c]) / (2.0f * d2[cw + c]));elseres = d2[cw + c] == 255 ? d1[cw + c] : d1[cw + c]+ (d1[cw + c]*(2.0f * d2[cw + c]-255.0f))/(255.0f - (2.0f * d2[cw + c] - 255.0f));d3[cw + c] = saturate_cast<uchar>(res);}}}
}

线性光(linear light)

        线性光:通过减少或增加亮度,来使颜色加深或减淡。具体取决于混合色的数值。混合色数值比中性灰色暗的时候进行相应的加深混合;混合色的数值比中性灰色亮的时候进行减淡混合。这里的加深及减淡时线性加深或线性减淡。
计算公式:结果色 = 2 * 混合色 + 基色 -255。数值大于255取255。

void layerblend_linear_light(Mat &base,Mat &blend,Mat &dst)
{if (base.rows != blend.rows ||base.cols != blend.cols ||base.type() != blend.type())return;dst = Mat::zeros(base.rows,base.cols,base.type());for (int h = 0;h < base.rows;h ++){uchar *d1 = base.ptr<uchar>(h);uchar *d2 = blend.ptr<uchar>(h);uchar *d3 = dst.ptr<uchar>(h);for (int w = 0;w < base.cols;w ++){int cw = w * base.channels();for (int c = 0;c < base.channels();c ++){int res = 2 * d2[cw + c] + d1[cw + c] - 255;d3[cw + c] = saturate_cast<uchar>(res);}}}
}

点光(point light)

        点光模式:它会根据混合色的颜色数值替换相应的颜色。如果混合色数值小于中性灰色,那么就替换比混合色亮的像素;相反混合色的数值大于中性灰色,则替换比混合色暗的像素,因此混合出来的颜色对比较大。
计算公式:
基色 < 2 * 混合色 - 255:结果色 = 2 * 混合色 - 255;
2 * 混合色 - 255 < 基色 < 2 * 混合色 :结果色 = 基色;
基色 > 2 * 混合色:结果色 = 2 * 混合色。

查看全文

99%的人还看了

相似问题

猜你感兴趣

版权申明

本文"图层混合算法(二)":http://eshow365.cn/6-13827-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!