如何将数字0到n均匀分布到m个不同的容器中

时间:2015-06-11 20:37:56

标签: c++ opencv math

我正在尝试为程序编写算法,以在图像上绘制均匀的垂直渐变。即我想沿着图像的m行更改像素颜色从0到255,但是找不到一个好的通用算法。

我尝试使用opencv实现类似的功能,但它似乎无法正常工作

[{"id":2,"company_name":"Test Company","address1":"abc","address2":"def","po_box":"1234","city_id":2,"email":"lklk@lklk.com","phone":"9898","fax_no":9798,"website":"www.jgjh.com","corporate_code":null,"contact_person_first_name":"First","contact_person_last_name":"Last","contact_person_phone":"98989","contact_person_email":"kjskdjk@kjdkaj.com"},{"id":3,"company_name":"Test Company","address1":"abc","address2":"def","po_box":"1234","city_id":2,"email":"lklk@lklk.com","phone":"9898","fax_no":9798,"website":"www.jgjh.com","corporate_code":null,"contact_person_first_name":"First","contact_person_last_name":"Last","contact_person_phone":"98989","contact_person_email":"kjskdjk@kjdkaj.com"},{"id":4,"company_name":"Test Company","address1":"abc","address2":"def","po_box":"1234","city_id":2,"email":"lklk@lklk.com","phone":"9898","fax_no":9798,"website":"www.jgjh.com","corporate_code":"17","contact_person_first_name":"First","contact_person_last_name":"Last","contact_person_phone":"98989","contact_person_email":"kjskdjk@kjdkaj.com"},{"id":5,"company_name":"Test Company","address1":"abc","address2":"def","po_box":"1234","city_id":2,"email":"lklk@lklk.com","phone":"9898","fax_no":9798,"website":"www.jgjh.com","corporate_code":"17","contact_person_first_name":"First","contact_person_last_name":"Last","contact_person_phone":"98989","contact_person_email":"kjskdjk@kjdkaj.com"},{"id":6,"company_name":"Test Company","address1":"abc","address2":"def","po_box":"1234","city_id":2,"email":"lklk@lklk.com","phone":"9898","fax_no":9798,"website":"www.jgjh.com","corporate_code":"18","contact_person_first_name":"First","contact_person_last_name":"Last","contact_person_phone":"98989","contact_person_email":"kjskdjk@kjdkaj.com"},{"id":7,"company_name":"Test Company","address1":"abc","address2":"def","po_box":"1234","city_id":2,"email":"lklk@lklk.com","phone":"9898","fax_no":9798,"website":"www.jgjh.com","corporate_code":"19","contact_person_first_name":"First","contact_person_last_name":"Last","contact_person_phone":"98989","contact_person_email":"kjskdjk@kjdkaj.com"},{"id":8,"company_name":"Test Company","address1":"abc","address2":"def","po_box":"1234","city_id":2,"email":"lklk@lklk.com","phone":"9898","fax_no":9798,"website":"www.jgjh.com","corporate_code":"20","contact_person_first_name":"First","contact_person_last_name":"Last","contact_person_phone":"98989","contact_person_email":"kjskdjk@kjdkaj.com"},{"id":9,"company_name":"Test Company","address1":"abc","address2":"def","po_box":"1234","city_id":2,"email":"lklk@lklk.com","phone":"9898","fax_no":9798,"website":"www.jgjh.com","corporate_code":"21","contact_person_first_name":"First","contact_person_last_name":"Last","contact_person_phone":"98989","contact_person_email":"kjskdjk@kjdkaj.com"},{"id":10,"company_name":"Test Company","address1":"abc","address2":"def","po_box":"1234","city_id":2,"email":"lklk@lklk.com","phone":"9898","fax_no":9798,"website":"www.jgjh.com","corporate_code":"22","contact_person_first_name":"First","contact_person_last_name":"Last","contact_person_phone":"98989","contact_person_email":"kjskdjk@kjdkaj.com"},{"id":11,"company_name":"Test Company","address1":"abc","address2":"def","po_box":"1234","city_id":2,"email":"lklk@lklk.com","phone":"9898","fax_no":9798,"website":"www.jgjh.com","corporate_code":"23","contact_person_first_name":"First","contact_person_last_name":"Last","contact_person_phone":"98989","contact_person_email":"kjskdjk@kjdkaj.com"}]

2 个答案:

答案 0 :(得分:3)

解决这个问题需要了解三个简单的技巧:

<强> 1。插值:

从一个值逐渐变为另一个值的过程称为interpolation。插值颜色值有多种方法:最简单的方法是线性插入每个组件,即以下列形式:

interpolated = start * (1-t) + dest * t

其中

  • start是您要向值dest进行插值的值。
  • t表示内插值与目标值dest的接近程度,其范围为010为纯start {1}}颜色和1是纯dest颜色。

您会发现RGB色彩空间中的线性插值不会产生自然色彩路径。作为高级步骤,您可以使用HSV颜色空间。有关颜色插值的详细信息,请参阅this question

<强> 2。离散化:

不幸的是,插值产生实数。因此,我们必须使它们离散,以便能够将它们用作整数颜色值。执行此操作的最佳方法是使用例如舍入到最接近的整数。 C ++中的round()

第3。找到插值点:

现在,我们只需要在图像的每一行都有一个实值插值点t。我们可以通过分析我们想要看到的输出来推断出这个公式:

  • 对于最下面一行(第1行),我们希望t == 0,因为这是我们希望我们的纯启动颜色出现的地方。
  • 对于最上面的行(行m),我们希望t == 1,因为这是我们希望显示纯目标颜色的地方。
  • 对于我们希望t每隔一行线性缩放到最底行的距离。

实现这一结果的公式是:

t = rowIndex / m

通过适当改变这个公式,该方法可以很容易地适应其他梯度方向。

示例代码(使用线性插值,C ++):

#include <algorithm>
#include <cmath>

Color interpolateRGB(Color from, Color to, float t)
{
    // Clamp __t__ to range [0,1]
    t = std::max(std::min(0.f, t), 1.f);

    // Interpolate each RGB component
    uint8_t r = std::roundf(from.r * (1-t) + to.r * t);
    uint8_t g = std::roundf(from.g * (1-t) + to.g * t);
    uint8_t b = std::roundf(from.b * (1-t) + to.b * t);

    return Color(r, g, b);
}

void fillWithGradient(Image& img, Color from, Color to)
{
    for(size_t row = 0; row < img.numRows(); ++row)
    {
        Color value = interpolateRGB(from, to, row / (img.numRows()-1));

        // Set all pixels of this row to __value__
        for(size_t col = 0; col < img.numCols(); ++col)
        {
            img.setPixel(row, col, value);
        }
    }
}

答案 1 :(得分:2)

基本想法是使用r的其余部分n/(m-1),并在每次迭代时将其添加到n

#include <iostream>
#include <vector>
using namespace std;

vector<int> gradient( int n, int m ) {
  div_t q { 0, 0 };
  vector<int> grad(m);
  for( int i=1 ; i<m ; ++i ) {
    q = div( n + q.rem, m-1 );
    grad[i] = grad[i-1] + q.quot;
  }
  return grad;
}

int main() {
  for( int i : gradient(255,10) ) cout << i << ' ';
  cout << '\n';
  return 0;
}

输出:

0 28 56 85 113 141 170 198 226 255