添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
func main ( ) { params := [ ] int { gocv . IMWriteJpegQuality , 1 } srcFile , err := os . Open ( "/Users/xxx/GolandProjects/xxx/image-encoder/demo/quality/3.png" ) if err != nil { fmt . Printf ( "%v" , err ) return defer srcFile . Close ( ) imageBuf , err := io . ReadAll ( srcFile ) if err != nil { fmt . Printf ( "%v" , err ) return mat , err := gocv . IMDecode ( imageBuf , gocv . IMReadUnchanged ) if err != nil { fmt . Printf ( "%v" , err ) return buf , err := gocv . IMEncodeWithParams ( gocv . JPEGFileExt , mat , params ) //buf, err := gocv.IMEncodeWithParams(gocv.JPEGFileExt, mat, params) if err != nil { fmt . Printf ( "%v" , err ) return os . WriteFile ( "/Users/xxx/GolandProjects/xxx/image-encoder/demo/quality/33.jpg" , buf . GetBytes ( ) , os . ModePerm ) if err != nil { fmt . Printf ( "%v" , err ) return println ( "DONE....." )

接着尝试将我本地其他的PNG图片转换为JPG,发现可以转换成功。表示这个代码是可以将PNG转换为JPG的。

于是,开始排查是否是客户图片有破损,比如图片的文件头已经损坏,导致它不是一个标准的PNG图片。

通过查阅资料后发现PNG的头部为 89 50 4E 47 0D 0A 1A 0A
在这里插入图片描述

package main
import (
	"encoding/hex"
	"fmt"
func main() {
	filePath := "/Users/xsky/GolandProjects/xxx/image-encoder/demo/quality/11.png" // 替换为你的 PNG 图片文件路径
	file, err := os.Open(filePath)
	if err != nil {
		fmt.Println("Error opening file:", err)
		return
	defer file.Close()
	header := make([]byte, 8)
	_, err = file.Read(header)
	if err != nil {
		fmt.Println("Error reading file:", err)
		return
	fmt.Println("PNG 文件头的16进制信息:")
	//89504e470d0a1a0a
	//89504e470d0a1a0a
	fmt.Println(hex.EncodeToString(header))

最终验证发现,客户的PNG图片与我本地PNG图片一致,文件头都是符合PNG格式的。

2.2 Alpha图像通道问题(shooting)

接着想着客户图像是灰白色的,而我之前验证的本地图片为彩色,加上我自己gocv处理图片的参数选择的是gocv.IMReadUnchanged。点进去查看源码,发现还有其他的参数,于是尝试替换其他参数。

//我之前代码的用法
mat, err := gocv.IMDecode(imageBuf, gocv.IMReadUnchanged)
// IMReadUnchanged return the loaded image as is (with alpha channel,
//otherwise it gets cropped).
IMReadUnchanged IMReadFlag = -1 # 处理带有Alpha参数的图像
// IMReadColor always converts image to the 3 channel BGR color image.
IMReadColor IMReadFlag = 1 # 将图片转换为BGR三色通道
// IMReadAnyColor the image is read in any possible color format.
IMReadAnyColor IMReadFlag = 4 # 根据图像自动识别任何可能的格式

知道这个参数之后,我将gocv.IMDecode(imageBuf, gocv.IMReadUnchanged)中的IMReadUnchanged改为IMReadAnyColor,最后验证,成功处理客户图片。

目前可以知道,我的图像处理参数选择有问题。于是开始查这几种参数有什么区别。其实点进去看源码就可以知道这几种参数的区别。

这个时候如果对图像处理不熟悉的朋友可能会问,Alpha通道是什么意思,其实大家可以简单的理解为和图像的透明度有关。

为了验证这个结论是否正确,我尝试读取客户的PNG和我本地的彩色PNG的颜色Model是否不同:

//color.RGBAModel # 我自己的图像
//color.Gray16Model # 客户的图像

至此,猜想成立,可以知道是我图像的处理颜色的参数选择有误。

3 拓展:图像color.Model

色彩模型(RGB,RGBA,CMYK灰度)
matplotlib中的色彩定义主要用到了RGB、RGBA、CMYK、灰色四种模型。

  • 这里我主要介绍RGBA模型

对这块感兴趣的朋友可以去看这边文章:https://blog.csdn.net/mighty13/article/details/113616772

3.1 color.RGBAModel:三色+Alpha

带有alpha[RGBA 表示传统的32位预处理 Alpha 色,每个颜色都有8位,分别表示红色,绿色,蓝色和阿尔法。 ]

type RGBA struct {
	R, G, B, A uint8

3.2 color.RGBA64Model:64位表示三色+Alpha的值

带有alpha:64位数来表示每个通道的值

type RGBA64 struct {
	R, G, B, A uint16

3.3 color.NRGBAModel:其他颜色不预乘Alpha的值

NRGBA 表示非 Alpha 预乘32位颜色(非 alpha 预乘表示在进行颜色合成时,颜色值不会提前乘以 alpha 通道的值)

  • 预乘:什么是预乘?假设一个像素点,用RGBA四个分量来表示,记做(R,G,B,A),那预乘后的像素就是(RA,GA,B*A, A),这里A的取值范围是[0,1]。所以,预乘就是每个颜色分量都与该像素的alpha分量预先相乘。可以发现,对于一个没有透明度,或者说透明度为1的像素来说,预乘不预乘结果都是一样的。
  • NRGBA代表一个没有32位透明度加乘的颜色。每个红,绿,蓝和透明度都是8bit的数值
type NRGBA struct {
	R, G, B, A uint8

3.4 color.NRGBA64:非预乘Alpha,其他颜色用64位表示

NRGBA64 表示非 alpha 预乘 64 位颜色,每个红色,绿色,蓝色和 alpha 有 16 位

  • NRGBA64代表无透明度加乘的64-bit的颜色,它的每个红,绿,蓝,和透明度都是个16bit的数值。
type NRGBA struct {
	R, G, B, A uint16

3.5 color.AlphaModel:代表一个8-bit的透明度

type Alpha struct {
	A uint8

3.6 color.Alpha16Model:代表一个16位的透明度

type Alpha struct {
	A uint16

3.7 color.GrayModel:灰度通道,黑白图像

只有一个灰度通道,通常用于表示黑白图像【当你需要读取只带有灰度通道的图像时,你应该使用该标志来读取图像。】【也是由RGB组成,不过由于是单通道,因此呈现灰度】

3.8 color.Gray16Model:16位整数表示灰度通道值

16位整数表示灰度通道的值,通常用于表示黑白

  • https://blog.csdn.net/zxcasd11/article/details/109446056
  • https://blog.csdn.net/u013943420/article/details/76855416
在很多应用中,经常会直接把图片的二进制数据进行交换,比如说利用 socket 通信传送图片二进制数据,或者直接用内存数据库(例如 Redis)来传递图片二进制数据。 这个时候,当你的应用程序读到内存里的二进制图片数据时,怎么样直接转为 OpenCV 可以使用的图片格式呢,答案是用 cv::imdecode 这个函数: std::vectorchar> data(lpData, size cv2.imdecode报错“cv2.error: OpenCV(4.6.0) :-1: error: (-5:Bad argument) in function 'imdecode'”一招解决。 image_name = '1.jpg' im = cv.imread(image_name) img_encode = cv.imencode('.jpg', im)[1] data_encode = np.array(img_encode) img = data_encode.tostring() imdecode : nparr = np.fromstr 对于路径中含有中文的图像,直接用cv2.imread读取会报错,上次看到有大佬使用cv2.imdecode就可以正常读取,有点好奇,所以今天来记录下二者用法和区别。 最近遇到一个问题,由于刚刚接触opencv,花了很多时间才解决。问题是: 在android中有一些图片需要处理,处于性能和以后移植的考虑,决定将图片处理的部分用C来写,在安卓中通过JNI调用本地C中函数。安卓中将bitmap中的数据放到byte数组中,然后将byte数组传到C函数,C函数将byte数组恢复成Mat对象,以便使用opencv提供的一些函数。 //native 方法 public na 第一节 HighGUI基础 OpenCV将与操作系统,文件系统,摄像机之类的硬件进行交互的一些函数纳入HighGui(high-level graphical user interface)库中,有了HighGui,我们可以方便的打开窗口,显示图像,读出或者写入图像相关的文件。 1、图像读取与保存 OpenCVimgcodecs模块提供了很多储存格式的图像读取与保存。经常使用的图像读取与保存函数: 1)cv::imread:从指定的图像文件读取图像数据。如果文件不存在或不支持图像格式,则返回空的Mat。 cv2.imdecode()函数从指定的内存缓存中读取数据,并把数据转换(解码)成图像格式;主要用于从网络传输数据中恢复出图像。 cv2.imencode()函数是将图片格式转换(编码)成流数据,赋值到内存缓存中;主要用于图像数据格式的压缩,方便网络传输。 imdecode()使用 从网络读取图像数据并转换成图片格式: # -*- coding: utf-8 -*- 学习内容颜色空间RGBYUVYCbCrcv2.imread(img_oath, flag)[..., 0]cv2.imencode()cv2.imdecode()np.newaxisPSNR(Peak Signal-to-Noise Ratio) 峰值信噪比SSIM (Structural SIMilarity) 结构相似性 红绿蓝三个通道。但在科学研究一般不采用RGB颜色空间,因为它的细节难以进行数字化的调整。它将色调,亮度,饱和度三个量放在一起表示,很难分开 在 YUV空间中, https://blog.csdn.net/spadgerz/article/details/103145959 imag(a,b,c) 分别是图片的height,wide , channel(高,宽,通道数) b = image[:,:,0]#得到蓝色通道 g = image[:,:,1]#得