Thông báo

Collapse
No announcement yet.

[Trợ Giúp] Giúp mình kiểm tra đoạn code xử lý ảnh.

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • [Trợ Giúp] Giúp mình kiểm tra đoạn code xử lý ảnh.

    Chào các bác !

    Mình thực hiện 1 đoạn code xử lý ảnh trên QT ( C++ ) xử lý với 1 ảnh 32 bit 1280x1024. Ảnh lưu dạng QImage ( biến img).

    Code:
    for(int y=0;y<__height;y++) // __height là chiều cao bức ảnh.
    {
         for(int x=0;x<__stride;x+=4) // stride là số byte dữ lieu trên 1 line ngang của ảnh = width*4
         {
              img.scanline(y)[x]++; // tang màu Blue lên 1 đơn vị
              img.scanline(y)[x+1]++; // tang màu Green lên 1 đơn vị
              img.scanline(y)[x+2]++; // tang màu Red lên 1 đơn vị
         }
    }
    Kết quả OK nhưng vấn đề là thời gian thực thi thậm chí còn chậm gấp 1.2 đến gấp rưỡi C#. ( trong khi C# lại được gọi là cụ rùa so với C++)
    Mình đang loay hoay không biết vấn đề chậm chap này do thư viện và QT hay do giải thuật mình chưa đúng.
    Hóng cao nhân chỉ giáo hoặc có đôi điều tư vấn cho vấn đề này !

    Cảm ơn các bác !

  • #2
    Qt có sẵn trong máy tính hay tự biên dịch từ mã nguồn ?
    Phần mềm tự do hoặc không dùng máy tính nữa !.

    Comment


    • #3
      Nguyên văn bởi bqviet Xem bài viết
      Qt có sẵn trong máy tính hay tự biên dịch từ mã nguồn ?
      Em sử dung QT cài từ bộ cài QT 5.3.2 cho Windows bác ạ.

      Comment


      • #4
        Bạn nên tải về tất cả gói mã nguồn thư viện Qt rồi biên dịch lại. Khi biên dịch nhớ bỏ những thứ cồng kềnh như RTTI, STL ... đi. Tốc độ sẽ cải thiện đáng kể. Biên dịch ở chế độ release thay vì debug, nếu dùng GCC đặt optimize -O2 hoặc -O3.

        Ngoài ra, C# chạy trên Windows tất nhiên hiệu năng phải cao rồi vì được tối ưu từ trong lõi hệ điều hành. Dùng Qt cái hay nhất là tính khả chuyển, cùng một chương trình viết ra biên dịch chạy được ở khắp nơi. Tốc độ Qt cũng khá nhanh, nhưng không phải là thế mạnh nhất của nó. So với Java khả chuyển thì Qt chạy nhanh hơn nhiều. So với C# của Windows hoặc Swift của Apple thì Qt có thể chưa nhanh bằng nhưng chạy được trên cả Android, Win, Mac, Linux, Unix đủ kiểu.
        Phần mềm tự do hoặc không dùng máy tính nữa !.

        Comment


        • #5
          QT của em thấy ghi MinGW có phải GCC mà bác nhắc tới không.
          Nhưng em chưa cấu hình bao giờ bác có thể chỉ rõ hơn chút không.

          Comment


          • #6
            MinGW là bản GCC chạy trên Windows. Cách biên dịch Qt có trình bày ở link sau, dùng MinGW hoặc Visual Studio đều được
            http://doc.qt.io/qt-5/windows-building.html

            Đặt cấu hình biên dịch chẳng qua chỉ là gõ đúng cái tùy chọn lúc chạy lệnh configure thôi mà.
            Phần mềm tự do hoặc không dùng máy tính nữa !.

            Comment


            • #7
              Chắc em phải tìm hiểu them.
              Em cũng lọ mọ tập tành config , O1,O2,O3 nhưng vẫn không thấy thay đổi gì

              Comment


              • #8
                Nguyên văn bởi duong_act Xem bài viết
                Chào các bác !

                Mình thực hiện 1 đoạn code xử lý ảnh trên QT ( C++ ) xử lý với 1 ảnh 32 bit 1280x1024. Ảnh lưu dạng QImage ( biến img).

                Code:
                for(int y=0;y<__height;y++) // __height là chiều cao bức ảnh.
                {
                for(int x=0;x<__stride;x+=4) // stride là số byte dữ lieu trên 1 line ngang của ảnh = width*4
                {
                img.scanline(y)[x]++; // tang màu Blue lên 1 đơn vị
                img.scanline(y)[x+1]++; // tang màu Green lên 1 đơn vị
                img.scanline(y)[x+2]++; // tang màu Red lên 1 đơn vị
                }
                }
                Kết quả OK nhưng vấn đề là thời gian thực thi thậm chí còn chậm gấp 1.2 đến gấp rưỡi C#. ( trong khi C# lại được gọi là cụ rùa so với C++)
                Mình đang loay hoay không biết vấn đề chậm chap này do thư viện và QT hay do giải thuật mình chưa đúng.
                Hóng cao nhân chỉ giáo hoặc có đôi điều tư vấn cho vấn đề này !

                Cảm ơn các bác !
                Ảnh với kích thước [1280x1024] thì không phải dạng vừa đâu. Nếu bạn chỉ xử lý trên CPU mà không đa luồng thì chậm là đúng rồi. Có nhiều cách để tối ưu tốc độ xử lý:
                - Thực hiện đa luồng ứng dụng (không xử lý ảnh trong luồng chính - luồng GUI). Phân luồn capture riêng, luồng xử ý ảnh riêng. Nếu sử dụng camera thì phải có sự đồng bộ tuyệt đối
                - Với ảnh kích thước lớn như của bạn thì có thể chia ảnh thành nhiều phần để xử lý [2, 4, 8..] sau đó đồng bộ kết quả (cao thủ nhé!)
                - Thực hiện trên GPU (cực nhanh - mình đã làm)
                - Re-size ảnh thu được từ camera với kích thước bé hơn: [320,240], [640,480] (dễ làm)

                Lưu ý: stride = 4 * ((width_image * bytes_per_pixel + 3) / 4);

                Với đoạn code trên, có thể thực hiện như sau:
                Code:
                for ( int row = 1; row < img.height() + 1; ++row )
                       for ( int col = 1; col < img.width() + 1; ++col )
                       {
                               QColor cl( img.pixel( row, col ) );
                               int r = cl.red();
                               int g = cl.green();
                               int b = cl.blue();
                               int alpha = cl.alpha();
                      }

                Comment


                • #9
                  Nguyên văn bởi compvis Xem bài viết

                  Ảnh với kích thước [1280x1024] thì không phải dạng vừa đâu. Nếu bạn chỉ xử lý trên CPU mà không đa luồng thì chậm là đúng rồi. Có nhiều cách để tối ưu tốc độ xử lý:
                  - Thực hiện đa luồng ứng dụng (không xử lý ảnh trong luồng chính - luồng GUI). Phân luồn capture riêng, luồng xử ý ảnh riêng. Nếu sử dụng camera thì phải có sự đồng bộ tuyệt đối
                  - Với ảnh kích thước lớn như của bạn thì có thể chia ảnh thành nhiều phần để xử lý [2, 4, 8..] sau đó đồng bộ kết quả (cao thủ nhé!)
                  - Thực hiện trên GPU (cực nhanh - mình đã làm)
                  - Re-size ảnh thu được từ camera với kích thước bé hơn: [320,240], [640,480] (dễ làm)

                  Lưu ý: stride = 4 * ((width_image * bytes_per_pixel + 3) / 4);

                  Với đoạn code trên, có thể thực hiện như sau:
                  Code:
                  for ( int row = 1; row < img.height() + 1; ++row )
                  for ( int col = 1; col < img.width() + 1; ++col )
                  {
                  QColor cl( img.pixel( row, col ) );
                  int r = cl.red();
                  int g = cl.green();
                  int b = cl.blue();
                  int alpha = cl.alpha();
                  }
                  Mình cũng chia ra từng luồng riêng rồi. Kết quả thì chấp nhận được.Với ảnh như trên mình xử lý liên tục 500 lần thì mất tầm 1.6s, chắc được tầm ~ 300 frame/s. Yêu cầu của mình thì không phải xử lý video nên cũng không cần nhanh lắm. Capture rồi xử lý ảnh tĩnh thôi. Sắp tới còn phải chơi cả ảnh 1920x1080 nữa.
                  Nhưng mà mình thắc mắc là QT (C++) lại thua đẹp C#. Mình cũng thử cả với DevC++ cũng thua C# nốt. Có thằng MFC thì ngon hơn. Mình thì chưa rõ lý do chậm chạp đó là do mình làm chưa đúng hay do QT với DevC nữa.

                  Comment


                  • #10
                    300fps thì hơn cả mong đợi rồi. Vấn đề bạn thắc mắc chỉ là tốc độ giữa c# và c/c++. Nên nhớ QT và MFC là các thư viện GUI đều viết bằng c++. DevC hay Visual Studio là các IDE. Hiển nhiên C# sẽ chậm hơn. Đa số các thuật toán xla được viết bằng c/c++ (dang DDL, COM) sau đó được wrap để có thể sử dụng trong C#. Trong thời gian tới, Native Compiler ra đời sẽ giúp tốc độ của C# đuổi kịp C/C++. Cho dù thế nào, tốc độ trong xử lý ảnh sẽ vẫn là vấn đề tối ưu thuật toán trong cả vấn đề xử lý ảnh và xây dựng chương trình. Đạt được Fps như bạn và có kết quả tốt là quá mỹ mãn rồi.

                    Comment


                    • #11
                      Qt là cross-platform, không tối ưu cho nền tảng hệ điều hành cụ thể nào cả. C# là ứng dụng native, ngôn ngữ của Microsoft, thư viện của Microsoft, chạy trên hệ điều hành của Microsoft ... có thể chậm được sao ?
                      Phần mềm tự do hoặc không dùng máy tính nữa !.

                      Comment


                      • #12
                        Nguyên văn bởi bqviet Xem bài viết
                        Qt là cross-platform, không tối ưu cho nền tảng hệ điều hành cụ thể nào cả. C# là ứng dụng native, ngôn ngữ của Microsoft, thư viện của Microsoft, chạy trên hệ điều hành của Microsoft ... có thể chậm được sao ?
                        C# không phải là NATIVE code. "CODE" được phân biệt thành một số loại sau:
                        • Machine Code (ngôn ngữ máy): là tập các lệnh được thực hiện trực tiếp bởi đơn vị xử lý trung tâm (CPU) thực. Tất các các ngôn ngữ khác cần phải dịch và chuyển sang ngôn ngữ máy trước khi có thể thực hiện
                        • Native Code: đôi khi được sử dụng như Machine Code, đôi khi được sử dụng như Unmanaged Code (tùy từng ngữ cảnh)
                        • Unmanaged code: Là các ngôn ngữ như C/C++ được dịch trực tiếp sang ngôn ngữ máy (Machine Code)
                        • Manage Code: Là các ngôn ngữ C#/VB.NET/Java/Perl/Python/PHP/Ruby hoặc tương tự được thực thi trong môi trưởng ảo (.NET hoặc JavaVM). Các môi trường ảo này sẽ mô phỏng bộ xử lý trên phần mềm để các ngôn ngữ Unmanaged Code chạy trên đó. Hy vọng bạn sẽ hiệu tại sao nó lại chậm hơn C/C++ (và nhiều lý do khác nữa)
                        • Assembly code: Nó có thể là Unmanaged Code hoặc Managed Code (bạn tự tìm hiểu)

                        C# hay C/C++ cũng chỉ là ngôn ngữ lập trình. Bởi thế cho dù nó là của Microsoft hay của Apple ... thì nó vẫn chậm như thường nếu nó không được tối ưu. Không nói tới GPU ở đây, chúng ta chỉ nói tới CPU. Vấn đề tối ưu ở đây phải được ưu tiên cho từng bộ vi xử lý (số luồng/lõi) và đặc biệt là tập thanh ghi. Đó là lý do tại sao trong các thư viện xử lý ảnh, để tăng tốc độ xử lý người ta phải viết lại các thuật toán tính toán (cộng, trừ, nhân, chia...) dựa trên các loại thanh ghi, chẳng hạn như SSE (Streaming SIMD Extensions), SSE2, SSE3, SSE4 hay AVX...Tập đoàn Intel có thư viện IPP dành cho xử lý tín hiệu số (âm thanh, hình ảnh) được tối ưu theo từng nền tảng vi xử lý của hãng (mình đang dùng), phục vụ các khách hàng sử dụng nền tảng phần cứng của hãng này.


                        Comment


                        • #13
                          Mình có ý kiến hơi khác với bác compvis.
                          Theo mình biết thì C# dịch ra MSIL, Java dịch ra Bytecode ( cả 2 đều không phải machine code). Khi thực thi nhờ có JIT( dành cho MISL ) và JVM( cho bytecode) thì nó sẽ dịch mã MSIL và bytecode ra machine code cho CPU chạy chứ không phải tạo môi trường ảo. Ứng dụng bị chậm khi JIT hoặc JVM dịch ra machine code. JIT và JVM chỉ dịch 1 lần và từ lần sau CPU sẽ chạy bằng mã machine code đã được dịch trước đó nên tốc độ lần thực thi sau sẽ nhanh hơn lần đầu.

                          Còn vụ nhanh chậm giữa C++ và C# thì như bác nói rồi. Nhưng nó không xảy ra với mình. Mình đang gặp điều ngược lại là C++ ( QT ) chạy chậm hơn C# rất nhiều lần. Cụ thể như ví dụ thì QT chậm hơn những 7 lần C#
                          Mình vừa mới test xong, mình cũng chưa biết tại sao, có thể do QT nhưng up tạm cái hình các bác xem giúp. Lọ mọ với thằng QT mấy hôm nay chưa xong . Click image for larger version

Name:	Performance2.png
Views:	2088
Size:	231.0 KB
ID:	1649390

                          Comment


                          • #14
                            Chỉ là ảnh thôi thì mình ko giúp được gì

                            Comment


                            • #15
                              Đây là code của mình.
                              Mình đã tìm ra vấn đề QT chậm hơn hẳn C# do mình dùng hàm lấy con trỏ trong thư viện QT.
                              Mình đã sử dụng con trỏ trực tiếp. QT đã nhanh hơn C# nhưng không ấn tượng lắm (1,2 / 1).

                              QT
                              PHP Code:

                              QImage img
                              ("E:/IMG.bmp"); // load ảnh trên ổ E ( ảnh chụp màn hình 1280x1024 )  
                              QElapsedTimer tmr// bộ đếm thời gian thực        
                              void MainWindow::on_pushButton_clicked()  
                              {      
                                  
                              int depth img.depth()/8;  // số byte / 1 pixel      
                                  
                              int stride=depth*img.width(); // số byte trên 1 line ngang      
                                  
                              int height img.height(); // số line dữ liệu      

                                  
                              unsigned char** dataptr = new unsigned char*[height]; // tạo mảng con trỏ    
                                  
                              for(int i=0;i<height;i++)        
                                       
                              dataptr[i]=img.scanLine(i); // gán địa chỉ cho mỗi con trỏ
                                  
                              qint64 time=0// biến lưu thời gian thực thi      
                                  
                              tmr.restart(); // reset thời gian + bắt đầu tính thời gian      
                                  
                              for(int i=0;i<100;i++) // lặp 100 lần      
                                  
                              {          
                                      for(
                              int y=0;y<height;y++)  // duyệt từng line trên ảnh          
                                      
                              {
                                          
                              //duyệt từng điểm ảnh trên line              
                                          
                              for(int x=0;x<stride;x+=depth)          
                                          {                
                                              
                              // Lúc trước dùng thế này chậm 7 lần
                                              //img.scanLine(y)[x]++; // tăng màu blue                
                                              //img.scanLine(y)[x+1]++; // tăng màu green                  
                                              //img.scanLine(y)[x+2]++; // tăng màu red    

                                              // bây giờ dùng thế này thì nhanh hơn C# khoảng 1.1 - 1.2 lần.          
                                              
                              dataptr[y][x]++; // tăng màu blue                      
                                              
                              dataptr[y][x+1]++; // tăng màu green                                  
                                              
                              dataptr[y][x+2]++; // tăng màu red                  
                                          
                              }          
                                      }      
                                  }      
                                  
                              time=tmr.elapsed(); // kết thúc, lấy thời gian thực thi.
                                  
                              ui->lblDisplay->setPixmap(QPixmap::fromImage(img)); // hiển thị ảnh sau xử lý
                                  
                              ui->lblTime->setText("Thời gian xử lý : " QString::number(time) + " ms"); // hiển thị thời gian    
                                  
                              int fps 100000/time// tính fps      
                                  
                              ui->lblFps->setText("Frame per second : " +     QString::number(fps)); // hiển thị fps  

                              SCharp:

                              PHP Code:
                              Bitmap img = new Bitmap("E:\\IMG.bmp"); // load ảnh trên ổ E ( ảnh chụp màn hình 1280x1024)
                              Stopwatch st = new Stopwatch(); // bộ đếm thời gian thực


                                  
                              private unsafe void button1_Click(object senderEventArgs e// hàm xử lý
                                  
                              {
                                      
                              Rectangle __rect = new Rectangle(00img.Widthimg.Height); // hình chữ nhật bằng kích thước ảnh
                                      
                              BitmapData __bmpdata img.LockBits(__rect,ImageLockMode.ReadWriteimg.PixelFormat); // khóa dữ liệu ảnh
                                      
                              int stride __bmpdata.Stride// lấy số byte trên 1 line ngang
                                      
                              int height __bmpdata.Height// lấy số line của ảnh
                                      
                              int depth stride __bmpdata.Width// lấy số byte trên 1 pixel
                                      
                              byteptr = (byte*)__bmpdata.Scan0.ToPointer(); // lấy con trỏ dữ liệu ảnh
                                      
                              byte*[] pdata = new byte*[height]; // tạo mảng con trỏ dữ liệu ảnh
                                      
                              for (int i 0heighti++)
                                          
                              pdata[i] = ptr stride// gán địa chỉ cho mỗi con trỏ , mỗi con trỏ sẽ trỏ tới byte đầu tiên của 1 line
                                      
                              img.UnlockBits(__bmpdata); // mở khóa ảnh để cho phép các truy cập khác
                                      
                              long time 0// biến lưu thời gian xử lý
                                      
                              st.Restart(); // reset bộ đếm + bắt đầu tính thời gian thực thi
                                      
                              for(int i=0;i<100;i++) // lặp 100 lần
                                      
                              {
                                          for(
                              int y=0;y<height;y++) // duyệt từng line
                                          
                              {
                                              for(
                              int x=0;x<stride;x+=depth// duyệt từng pixel
                                              
                              {
                                                  
                              pdata[y][x]++; // tăng blue
                                                  
                              pdata[y][1]++; // tăng green
                                                  
                              pdata[y][2]++; // tăng red
                                              
                              }
                                          }
                                      }
                                      
                              time st.ElapsedMilliseconds// kết thúc xử lý, lấy thời gian thực thi
                                      
                              st.Stop(); // dừng bộ đếm
                                      
                              ptxDisplay.Image img// hiển thị ảnh
                                      
                              lblTime.Text "Thời gian xử lý : " time.ToString() + " ms"// hiển thị thời gian
                                      
                              int fps = (int)(100000 time); // tính fps
                                      
                              lblFps.Text "Frame per second : " fps.ToString(); // hiển thị fps
                                  
                              }

                              Comment

                              Về tác giả

                              Collapse

                              duong_act Tìm hiểu thêm về duong_act

                              Bài viết mới nhất

                              Collapse

                              Đang tải...
                              X