图片边缘采样

普通采样

 const getEdgeColors = (img) => {
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');
    canvas.width = img.width;
    canvas.height = img.height;
    try {
      context.drawImage(img, 0, 0);

    // 获取左边缘颜色
      const leftPixel = context.getImageData(0, Math.floor(img.height / 2), 1, 1).data;
      const leftColor = `rgb(${leftPixel[0]}, ${leftPixel[1]}, ${leftPixel[2]})`;

    // 获取右边缘颜色
      const rightPixel = context.getImageData(img.width - 1, Math.floor(img.height / 2), 1, 1).data;
      const rightColor = `rgb(${rightPixel[0]}, ${rightPixel[1]}, ${rightPixel[2]})`;
      console.log('获取图片边缘颜色成功:', leftColor, rightColor);
      return { leftColor, rightColor };
    } catch (error) {
      console.error('获取图片边缘颜色失败:', error);
      return { leftColor: '#ffffff', rightColor: '#ffffff' };
    }
  };

优化:

1)采样多个点而不是只取中间一点,提高颜色准确性;
2)实现边缘区域的平均采样,避免单点采样可能带来的颜色偏差;
3)添加颜色增强处理,使背景色更加美观;
4)优化错误处理机制,确保在各种情况下都能返回合适的颜色值;
5)添加颜色平滑过渡效果,使轮播切换时背景色变化更加自然。

  // 获取图片边缘颜色 - 优化版本
  const getEdgeColors = (img) => {
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');
    canvas.width = img.width;
    canvas.height = img.height;
    
    try {
      context.drawImage(img, 0, 0);
      
      // 采样点数量和区域大小
      const samplePoints = 5; // 垂直方向采样点数量
      const sampleWidth = 10;  // 水平方向采样宽度
      const sampleHeight = Math.floor(img.height / samplePoints); // 每个采样点的高度间隔
      
      // 左边缘颜色采样
      let leftR = 0, leftG = 0, leftB = 0;
      for (let i = 0; i < samplePoints; i++) {
        // 计算当前采样点的垂直位置
        const y = Math.floor(sampleHeight * (i + 0.5));
        
        // 获取左边缘区域的平均颜色
        const leftData = context.getImageData(0, y, sampleWidth, 1).data;
        for (let j = 0; j < sampleWidth * 4; j += 4) {
          leftR += leftData[j];
          leftG += leftData[j + 1];
          leftB += leftData[j + 2];
        }
      }
      
      // 计算左边缘平均颜色
      leftR = Math.floor(leftR / (samplePoints * sampleWidth));
      leftG = Math.floor(leftG / (samplePoints * sampleWidth));
      leftB = Math.floor(leftB / (samplePoints * sampleWidth));
      
      // 右边缘颜色采样
      let rightR = 0, rightG = 0, rightB = 0;
      for (let i = 0; i < samplePoints; i++) {
        // 计算当前采样点的垂直位置
        const y = Math.floor(sampleHeight * (i + 0.5));
        
        // 获取右边缘区域的平均颜色
        const rightData = context.getImageData(img.width - sampleWidth, y, sampleWidth, 1).data;
        for (let j = 0; j < sampleWidth * 4; j += 4) {
          rightR += rightData[j];
          rightG += rightData[j + 1];
          rightB += rightData[j + 2];
        }
      }
      
      // 计算右边缘平均颜色
      rightR = Math.floor(rightR / (samplePoints * sampleWidth));
      rightG = Math.floor(rightG / (samplePoints * sampleWidth));
      rightB = Math.floor(rightB / (samplePoints * sampleWidth));
      
      // 颜色增强处理 - 适当提高饱和度
      const enhanceColor = (r, g, b) => {
        // 计算亮度
        const brightness = (r + g + b) / 3;
        
        // 如果颜色太暗或太亮,适当调整
        if (brightness < 30) {
          // 提亮暗色
          return {
            r: Math.min(255, r + 30),
            g: Math.min(255, g + 30),
            b: Math.min(255, b + 30)
          };
        } else if (brightness > 220) {
          // 降低过亮的颜色
          return {
            r: Math.max(0, r - 20),
            g: Math.max(0, g - 20),
            b: Math.max(0, b - 20)
          };
        } else {
          // 适当提高饱和度
          const max = Math.max(r, g, b);
          const min = Math.min(r, g, b);
          const delta = max - min;
          
          if (delta > 10) { // 有一定色差才增强饱和度
            const saturationFactor = 1.2;
            const newR = r + (r - brightness) * saturationFactor;
            const newG = g + (g - brightness) * saturationFactor;
            const newB = b + (b - brightness) * saturationFactor;
            
            return {
              r: Math.min(255, Math.max(0, Math.round(newR))),
              g: Math.min(255, Math.max(0, Math.round(newG))),
              b: Math.min(255, Math.max(0, Math.round(newB)))
            };
          }
          
          return { r, g, b };
        }
      };
      
      // 应用颜色增强
      const enhancedLeft = enhanceColor(leftR, leftG, leftB);
      const enhancedRight = enhanceColor(rightR, rightG, rightB);
      
      // 生成最终颜色
      const leftColor = `rgb(${enhancedLeft.r}, ${enhancedLeft.g}, ${enhancedLeft.b})`;
      const rightColor = `rgb(${enhancedRight.r}, ${enhancedRight.g}, ${enhancedRight.b})`;
      
      console.log('获取图片边缘颜色成功:', leftColor, rightColor);
      return { leftColor, rightColor };
    } catch (error) {
      console.error('获取图片边缘颜色失败:', error);
      // 返回一个柔和的默认颜色,而不是纯白色
      return { leftColor: '#f5f5f5', rightColor: '#f5f5f5' };
    }
  };

采用切片的方案进行循环填充

// 创建边缘切片的canvas
export const createEdgeSlice = (img: HTMLImageElement, isLeft: boolean): string => {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  const sliceWidth = 1; // 切片宽度

  canvas.width = sliceWidth;
  canvas.height = img.height;

  if (isLeft) {
    if (ctx) {
      ctx.drawImage(img, 0, 0, sliceWidth, img.height, 0, 0, sliceWidth, img.height);
    } else {
      // 如果ctx为null则抛出错误
      throw new Error('无法获取canvas上下文');
    }
  } else {
    if (ctx) {
      ctx.drawImage(img, img.width - sliceWidth, 0, sliceWidth, img.height, 0, 0, sliceWidth, img.height);
    } else {
      // 如果ctx为null则抛出错误
      throw new Error('无法获取canvas上下文');
    }
  }
  console.log('获取到了边缘切片 base64')
  return canvas.toDataURL();
};

采样某个点进行渐变

export const getEdgeColors = (img) => {
  const canvas = document.createElement('canvas');
  const context = canvas.getContext('2d');
  canvas.width = img.width;
  canvas.height = img.height;
  try {
    // 检查 context 是否为 null
    if (!context) {
      throw new Error('无法获取 canvas context');
    }
    context.drawImage(img, 0, 0);

    // 获取顶部中间位置的左右边缘颜色
    const middleX = Math.floor(img.width / 2);
    // 使用中间点位即可
    const middlePixel = context.getImageData(middleX, 0, 1, 1).data;
    // const leftPixel = context.getImageData(0, 0, 1, 1).data;
    // const rightPixel = context.getImageData(img.width - 1, 0, 1, 1).data;
    const leftPixel = middlePixel;
    const rightPixel = middlePixel;
    // 创建渐变色字符串
    const createGradient = (color, direction) => {
      const [r, g, b] = color;
      // direction: 渐变方向,可以是'right'或'left'
      // r,g,b: RGB颜色值
      // 渐变包含6个颜色节点:
      // 1. 0%位置: 完全不透明的原始颜色
      // 2. 20%位置: 85%透明度
      // 3. 40%位置: 60%透明度
      // 4. 60%位置: 35%透明度
      // 5. 80%位置: 15%透明度
      // 6. 100%位置: 完全透明
      return `linear-gradient(to ${direction}, rgb(${r}, ${g}, ${b}) 0%, rgba(${r}, ${g}, ${b}, 0.85) 20%, rgba(${r}, ${g}, ${b}, 0.6) 40%, rgba(${r}, ${g}, ${b}, 0.35) 60%, rgba(${r}, ${g}, ${b}, 0.15) 80%, rgba(${r}, ${g}, ${b}, 0) 100%)`;
    };

    const leftColor = createGradient([leftPixel[0], leftPixel[1], leftPixel[2]], 'right');
    const rightColor = createGradient([rightPixel[0], rightPixel[1], rightPixel[2]], 'left');

    console.log('获取图片边缘渐变颜色成功:', leftColor, rightColor);
    return { leftColor, rightColor };
  } catch (error) {
    console.error('获取图片边缘颜色失败:', error);
    // 返回柔和的默认渐变颜色
    const defaultColor = [245, 245, 245]; // #f5f5f5
    return {
      leftColor: `linear-gradient(to right, rgb(${defaultColor.join(',')}) 0%, rgba(${defaultColor.join(',')}, 0) 100%)`,
      rightColor: `linear-gradient(to left, rgb(${defaultColor.join(',')}) 0%, rgba(${defaultColor.join(',')}, 0) 100%)`
    };
  }
};

虽然给定引用中未提及图片自适应采样的相关内容,但以下为关于图片自适应采样原理、方法及应用的介绍: ### 原理 图片自适应采样的核心原理是根据图像的局部特征动态调整采样率。图像不同区域的信息丰富程度存在差异,例如在纹理复杂、细节丰富的区域,包含了更多有价值信息,需要较高的采样率来准确捕捉这些细节;而在平滑、变化缓慢的区域,信息变化较小,较低的采样率就可以满足对图像特征的描述,同时减少数据量。通过自适应地调整采样点的分布和密度,使得在保证图像质量的前提下,尽可能地减少冗余采样,提高采样效率。 ### 方法 - **基于梯度的自适应采样**:计算图像的梯度,梯度表示图像局部的变化率。梯度值大的区域对应着图像中变化剧烈的部分,如边缘和纹理,在这些区域增加采样点;梯度值小的区域为平滑区域,适当减少采样点。例如,在进行图像重建时,可以使用 Sobel 算子计算图像的梯度强度,根据梯度强度图确定采样点的分布。 ```python import cv2 import numpy as np # 读取图像 image = cv2.imread(&#39;your_image.jpg&#39;, cv2.IMREAD_GRAYSCALE) # 计算 x 和 y 方向的梯度 sobelx = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3) sobely = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3) # 计算梯度强度 gradient_magnitude = np.sqrt(sobelx**2 + sobely**2) ``` - **基于块的自适应采样**:将图像划分为若干个小块,对每个小块进行特征分析,如计算小块的方差、熵等统计量。方差大或熵值高的小块表示该区域信息丰富,采用较高的采样率;反之则采用较低的采样率。例如,将图像分成 8x8 的小块,计算每个小块的方差,根据方差阈值决定采样率。 ```python block_size = 8 height, width = image.shape for i in range(0, height, block_size): for j in range(0, width, block_size): block = image[i:i+block_size, j:j+block_size] variance = np.var(block) # 根据方差决定采样率 if variance > threshold: # 高采样率处理 pass else: # 低采样率处理 pass ``` ### 应用 - **图像压缩**:通过自适应采样减少图像数据量,去除冗余信息,在保证一定图像质量的前提下,降低存储和传输成本。例如,在 JPEG 2000 图像压缩标准中,就采用了自适应采样技术,能够根据图像内容动态调整采样率,提高压缩比。 - **图像重建**:在图像重建过程中,自适应采样可以根据图像的特征有针对性地采集数据,提高重建的精度和效率。例如,在医学影像重建、遥感图像重建等领域,能够更准确地恢复图像的细节信息。 - **实时图像处理**:在实时图像处理系统中,如视频监控、自动驾驶等场景,由于处理资源和时间的限制,需要快速处理图像。自适应采样可以在不损失关键信息的前提下,减少处理的数据量,提高处理速度,保证系统的实时性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值